X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sfa%2Fserver%2Fsfa_component_setup.py;h=236d253a11015e0647f04d80bbe9d10c95b67b4d;hb=713d58df0baa1f9739eec9bfa30ceb41d7149e23;hp=2c136fa8717d0d351a9b71a35745ada71df03ddf;hpb=9d136039a69721a80775327301f401b706a00080;p=sfa.git diff --git a/sfa/server/sfa_component_setup.py b/sfa/server/sfa_component_setup.py index 2c136fa8..236d253a 100755 --- a/sfa/server/sfa_component_setup.py +++ b/sfa/server/sfa_component_setup.py @@ -1,99 +1,331 @@ #!/usr/bin/python +from __future__ import print_function + import sys import os +import tempfile from optparse import OptionParser + +from sfa.util.faults import ConnectionKeyGIDMismatch from sfa.util.config import Config -from sfa.util.xmlrpcprotocol import * + from sfa.trust.certificate import Keypair, Certificate from sfa.trust.credential import Credential +from sfa.trust.gid import GID +from sfa.trust.hierarchy import Hierarchy + +from sfa.client.sfaserverproxy import SfaServerProxy + +from sfa.planetlab.plxrn import hrn_to_pl_slicename, slicename_to_hrn + +KEYDIR = "/var/lib/sfa/" +CONFDIR = "/etc/sfa/" + + +def handle_gid_mismatch_exception(f): + def wrapper(*args, **kwds): + try: + return f(*args, **kwds) + except ConnectionKeyGIDMismatch: + # clean regen server keypair and try again + print("cleaning keys and trying again") + clean_key_cred() + return f(args, kwds) + + return wrapper + + +def server_proxy(url=None, port=None, keyfile=None, certfile=None, verbose=False): + """ + returns an xmlrpc connection to the service a the specified + address + """ + if url: + url_parts = url.split(":") + if len(url_parts) > 1: + pass + else: + url = "http://%(url)s:%(port)s" % locals() + else: + # connect to registry by default + config = Config() + addr, port = config.SFA_REGISTRY_HOST, config.SFA_REGISTRY_PORT + url = "http://%(addr)s:%(port)s" % locals() + + if verbose: + print("Contacting registry at: %(url)s" % locals()) + + server = SfaServerProxy(url, keyfile, certfile) + return server -CONFIG_DIR='/etc/sfa' -TRUSTED_CERTS_DIR = '/etc/sfa/trusted_roots' -DATA_DIR = '/var/lib/sfa' def create_default_dirs(): - all_dirs = [CONFIG_DIR, TRUSTED_CERTS_DIR, DATA_DIR] + config = Config() + hierarchy = Hierarchy() + config_dir = config.config_path + trusted_certs_dir = config.get_trustedroots_dir() + authorities_dir = hierarchy.basedir + all_dirs = [config_dir, trusted_certs_dir, authorities_dir] for dir in all_dirs: if not os.path.exists(dir): - os.mkdir(dir) - -def get_node_key(options): - if options.verbose: - print "Getting the component's pkey" - # this call requires no authentication, + os.makedirs(dir) + + +def has_node_key(): + key_file = KEYDIR + os.sep + 'server.key' + return os.path.exists(key_file) + + +def clean_key_cred(): + """ + remove the existing keypair and cred and generate new ones + """ + files = ["server.key", "server.cert", "node.cred"] + for f in files: + filepath = KEYDIR + os.sep + f + if os.path.isfile(filepath): + os.unlink(f) + + # install the new key pair + # GetCredential will take care of generating the new keypair + # and credential + GetCredential() + + +def get_node_key(registry=None, verbose=False): + # this call requires no authentication, # so we can generate a random keypair here - subject="component" - keyfile = tempfile.mktemp() - certfile = tempfile.mktemp() + subject = "component" + (kfd, keyfile) = tempfile.mkstemp() + (cfd, certfile) = tempfile.mkstemp() key = Keypair(create=True) key.save_to_file(keyfile) - cert = Certificate(subject=component) + cert = Certificate(subject=subject) cert.set_issuer(key=key, subject=subject) cert.set_pubkey(key) cert.sign() cert.save_to_file(certfile) - - # get the registry url - url = "" - if options.registry: - url_parts = options.registry.split(":") - if len(url_parts) >1: - url = options.registry - else: - url = "http://%s:12346" % options.registry + + registry = server_proxy(url=registry, keyfile=keyfile, certfile=certfile) + registry.get_key_from_incoming_ip() + + +def create_server_keypair(keyfile=None, certfile=None, hrn="component", verbose=False): + """ + create the server key/cert pair in the right place + """ + key = Keypair(filename=keyfile) + key.save_to_file(keyfile) + cert = Certificate(subject=hrn) + cert.set_issuer(key=key, subject=hrn) + cert.set_pubkey(key) + cert.sign() + cert.save_to_file(certfile, save_parents=True) + + +@handle_gid_mismatch_exception +def GetCredential(registry=None, force=False, verbose=False): + config = Config() + hierarchy = Hierarchy() + key_dir = hierarchy.basedir + data_dir = config.data_path + config_dir = config.config_path + credfile = data_dir + os.sep + 'node.cred' + # check for existing credential + if not force and os.path.exists(credfile): + if verbose: + print("Loading Credential from %(credfile)s " % locals()) + cred = Credential(filename=credfile).save_to_string(save_parents=True) else: - config = Config() - addr, port = config.SFA_REGISTRY_HOST, config.SFA_REGISTRY_PORT_ - url = "http://%(addr)s:%(port)s" % locals() - - if options.verbose: - print "Contacting registry at: %(url)s" % locals() - - registry = xmlrpcprotocol.get_server(url, keyfile, certfile) - -def get_credential(options): - if options.verbose: - print "Getting the component's credential" - pass - -def get_trusted_certs(options): - if options.verbose: - print "Getting the component's trusted certs" - pass - -def get_gids(options): - if options.verbose: - print "Geting the component's GIDs" - - pass + if verbose: + print("Getting credential from registry") + # make sure node private key exists + node_pkey_file = config_dir + os.sep + "node.key" + node_gid_file = config_dir + os.sep + "node.gid" + if not os.path.exists(node_pkey_file) or \ + not os.path.exists(node_gid_file): + get_node_key(registry=registry, verbose=verbose) + + gid = GID(filename=node_gid_file) + hrn = gid.get_hrn() + # create server key and certificate + keyfile = data_dir + os.sep + "server.key" + certfile = data_dir + os.sep + "server.cert" + key = Keypair(filename=node_pkey_file) + key.save_to_file(keyfile) + create_server_keypair(keyfile, certfile, hrn, verbose) + + # get credential from registry + registry = server_proxy( + url=registry, keyfile=keyfile, certfile=certfile) + cert = Certificate(filename=certfile) + cert_str = cert.save_to_string(save_parents=True) + cred = registry.GetSelfCredential(cert_str, 'node', hrn) + Credential(string=cred).save_to_file(credfile, save_parents=True) + + return cred + + +@handle_gid_mismatch_exception +def get_trusted_certs(registry=None, verbose=False): + """ + refresh our list of trusted certs. + """ + # define useful variables + config = Config() + data_dir = config.SFA_DATA_DIR + config_dir = config.SFA_CONFIG_DIR + trusted_certs_dir = config.get_trustedroots_dir() + keyfile = data_dir + os.sep + "server.key" + certfile = data_dir + os.sep + "server.cert" + node_gid_file = config_dir + os.sep + "node.gid" + node_gid = GID(filename=node_gid_file) + hrn = node_gid.get_hrn() + # get credential + cred = GetCredential(registry=registry, verbose=verbose) + # make sure server key cert pair exists + create_server_keypair( + keyfile=keyfile, certfile=certfile, hrn=hrn, verbose=verbose) + registry = server_proxy(url=registry, keyfile=keyfile, certfile=certfile) + # get the trusted certs and save them in the right place + if verbose: + print("Getting trusted certs from registry") + trusted_certs = registry.get_trusted_certs(cred) + trusted_gid_names = [] + for gid_str in trusted_certs: + gid = GID(string=gid_str) + gid.decode() + relative_filename = gid.get_hrn() + ".gid" + trusted_gid_names.append(relative_filename) + gid_filename = trusted_certs_dir + os.sep + relative_filename + if verbose: + print("Writing GID for %s as %s" % (gid.get_hrn(), gid_filename)) + gid.save_to_file(gid_filename, save_parents=True) + + # remove old certs + all_gids_names = os.listdir(trusted_certs_dir) + for gid_name in all_gids_names: + if gid_name not in trusted_gid_names: + if verbose: + print("Removing old gid ", gid_name) + os.unlink(trusted_certs_dir + os.sep + gid_name) + + +@handle_gid_mismatch_exception +def get_gids(registry=None, verbose=False): + """ + Get the gid for all instantiated slices on this node and store it + in /etc/sfa/slice.gid in the slice's filesystem + """ + # define useful variables + config = Config() + data_dir = config.data_path + config_dir = config.SFA_CONFIG_DIR + trusted_certs_dir = config.get_trustedroots_dir() + keyfile = data_dir + os.sep + "server.key" + certfile = data_dir + os.sep + "server.cert" + node_gid_file = config_dir + os.sep + "node.gid" + node_gid = GID(filename=node_gid_file) + hrn = node_gid.get_hrn() + interface_hrn = config.SFA_INTERFACE_HRN + # get credential + cred = GetCredential(registry=registry, verbose=verbose) + # make sure server key cert pair exists + create_server_keypair( + keyfile=keyfile, certfile=certfile, hrn=hrn, verbose=verbose) + registry = server_proxy(url=registry, keyfile=keyfile, certfile=certfile) + + if verbose: + print("Getting current slices on this node") + # get a list of slices on this node + from sfa.generic import Generic + generic = Generic.the_flavour() + api = generic.make_api(interface='component') + xids_tuple = api.driver.nodemanager.GetXIDs() + slices = eval(xids_tuple[1]) + slicenames = slices.keys() + + # generate a list of slices that dont have gids installed + slices_without_gids = [] + for slicename in slicenames: + if not os.path.isfile("/vservers/%s/etc/slice.gid" % slicename) \ + or not os.path.isfile("/vservers/%s/etc/node.gid" % slicename): + slices_without_gids.append(slicename) + + # convert slicenames to hrns + hrns = [slicename_to_hrn(interface_hrn, slicename) + for slicename in slices_without_gids] + + # exit if there are no gids to install + if not hrns: + return + + if verbose: + print("Getting gids for slices on this node from registry") + # get the gids + # and save them in the right palce + records = registry.GetGids(hrns, cred) + for record in records: + # if this isnt a slice record skip it + if not record['type'] == 'slice': + continue + slicename = hrn_to_pl_slicename(record['hrn']) + # if this slice isnt really instatiated skip it + if not os.path.exists("/vservers/%(slicename)s" % locals()): + continue + + # save the slice gid in /etc/sfa/ in the vservers filesystem + vserver_path = "/vservers/%(slicename)s" % locals() + gid = record['gid'] + slice_gid_filename = os.sep.join([vserver_path, "etc", "slice.gid"]) + if verbose: + print("Saving GID for %(slicename)s as %(slice_gid_filename)s" % locals()) + GID(string=gid).save_to_file(slice_gid_filename, save_parents=True) + # save the node gid in /etc/sfa + node_gid_filename = os.sep.join([vserver_path, "etc", "node.gid"]) + if verbose: + print("Saving node GID for %(slicename)s as %(node_gid_filename)s" % locals()) + node_gid.save_to_file(node_gid_filename, save_parents=True) + + +def dispatch(options, args): + + create_default_dirs() + if options.key: + if options.verbose: + print("Getting the component's pkey") + get_node_key(registry=options.registry, verbose=options.verbose) + if options.certs: + if options.verbose: + print("Getting the component's trusted certs") + get_trusted_certs(verbose=options.verbose) + if options.gids: + if options.verbose: + print("Geting the component's GIDs") + get_gids(verbose=options.verbose) + def main(): args = sys.argv prog_name = args[0] parser = OptionParser(usage="%(prog_name)s [options]" % locals()) parser.add_option("-v", "--verbose", dest="verbose", action="store_true", - default=False, help="Be verbose") + default=False, help="Be verbose") parser.add_option("-r", "--registry", dest="registry", default=None, - help="Url of registry to contact") - parser.add_option("-k", "--key", dest="key", action="store_true", - default=False, - help="Get the node's pkey from the registry") + help="Url of registry to contact") + parser.add_option("-k", "--key", dest="key", action="store_true", + default=False, + help="Get the node's pkey from the registry") parser.add_option("-c", "--certs", dest="certs", action="store_true", default=False, help="Get the trusted certs from the registry") - parser.add_option("-g", "--gids", dest="gids", action="store_true", + parser.add_option("-g", "--gids", dest="gids", action="store_true", default=False, help="Get gids for all the slices on the component") (options, args) = parser.parse_args() - create_default_dirs() - if options.key: - get_node_key(options) - if options.certs: - get_certs(options) - if options.gids: - get_gids(options) + dispatch(options, args) if __name__ == '__main__': - main() + main()