From b073401948a91054f0963f9b3ca0fbbb9a5b2ecc Mon Sep 17 00:00:00 2001 From: Tony Mack Date: Sun, 3 Jan 2010 21:01:44 +0000 Subject: [PATCH] refactored registry methods to use the registry manager module --- sfa/managers/registry_manager_pl.py | 395 ++++++++++++++++++++++++++++ sfa/methods/create_slice.py | 1 - sfa/methods/delete_slice.py | 1 - sfa/methods/get_aggregates.py | 1 - sfa/methods/get_credential.py | 52 +--- sfa/methods/get_gid.py | 1 - sfa/methods/get_gids.py | 1 - sfa/methods/get_key.py | 2 +- sfa/methods/get_registries.py | 1 - sfa/methods/get_self_credential.py | 55 +--- sfa/methods/get_slices.py | 1 - sfa/methods/get_trusted_certs.py | 1 - sfa/methods/list.py | 41 +-- sfa/methods/reboot.py | 1 - sfa/methods/redeem_ticket.py | 1 - sfa/methods/register.py | 123 +-------- sfa/methods/register_peer_object.py | 2 +- sfa/methods/remove.py | 53 +--- sfa/methods/remove_peer_object.py | 1 - sfa/methods/reset_slice.py | 1 - sfa/methods/resolve.py | 53 +--- sfa/methods/start_slice.py | 2 +- sfa/methods/stop_slice.py | 2 +- sfa/methods/update.py | 94 +------ 24 files changed, 454 insertions(+), 432 deletions(-) create mode 100644 sfa/managers/registry_manager_pl.py diff --git a/sfa/managers/registry_manager_pl.py b/sfa/managers/registry_manager_pl.py new file mode 100644 index 00000000..5c70ee7c --- /dev/null +++ b/sfa/managers/registry_manager_pl.py @@ -0,0 +1,395 @@ +import types +import time +from sfa.server.registry import Registries +from sfa.util.prefixTree import prefixTree +from sfa.util.record import GeniRecord +from sfa.util.genitable import GeniTable +from sfa.util.record import GeniRecord +from sfa.util.genitable import GeniTable +from sfa.trust.gid import GID +from sfa.util.namespace import * +from sfa.trust.credential import * +from sfa.trust.certificate import * +from sfa.util.faults import * + +def get_credential(api, hrn, type, is_self=False): + # Is this a root or sub authority + auth_hrn = api.auth.get_authority(hrn) + if not auth_hrn or hrn == api.config.SFA_INTERFACE_HRN: + auth_hrn = hrn + # get record info + auth_info = api.auth.get_auth_info(auth_hrn) + table = GeniTable() + records = table.findObjects({'type': type, 'hrn': hrn}) + if not records: + raise RecordNotFound(hrn) + record = records[0] + + # verify_cancreate_credential requires that the member lists + # (researchers, pis, etc) be filled in + api.fill_record_info(record) + + # get the callers gid + # if this is a self cred the record's gid is the caller's gid + if is_self: + caller_hrn = hrn + caller_gid = record.get_gid_object() + else: + caller_gid = api.auth.client_cred.get_gid_caller() + caller_hrn = caller_gid.get_hrn() + + object_hrn = record.get_gid_object().get_hrn() + rights = api.auth.determine_user_rights(caller_hrn, record) + # make sure caller has rights to this object + if rights.is_empty(): + raise PermissionError(caller_hrn + " has no rights to " + record['name']) + + object_gid = GID(string=record['gid']) + new_cred = Credential(subject = object_gid.get_subject()) + new_cred.set_gid_caller(caller_gid) + new_cred.set_gid_object(object_gid) + new_cred.set_issuer(key=auth_info.get_pkey_object(), subject=auth_hrn) + new_cred.set_pubkey(object_gid.get_pubkey()) + new_cred.set_privileges(rights) + new_cred.set_delegate(True) + auth_kind = "authority,ma,sa" + new_cred.set_parent(api.auth.hierarchy.get_auth_cred(auth_hrn, kind=auth_kind)) + new_cred.encode() + new_cred.sign() + + return new_cred.save_to_string(save_parents=True) + +def resolve(api, hrns, type=None, origin_hrn): + + # load all know registry names into a prefix tree and attempt to find + # the longest matching prefix + if not isinstance(hrns, types.ListType): + hrns = [hrns] + + # create a dict whre key is an registry hrn and its value is a + # hrns at that registry (determined by the known prefix tree). + hrn_dict = {} + registries = Registries(api) + tree = prefixTree() + registry_hrns = registries.keys() + tree.load(registry_hrns) + for hrn in hrns: + registry_hrn = tree.best_match(hrn) + if registry_hrn not in hrn_dict: + hrn_dict[registry_hrn] = [] + hrn_dict[registry_hrn].append(hrn) + + records = [] + for registry_hrn in hrn_dict: + # skip the hrn without a registry hrn + # XX should we let the user know the authority is unknown? + if not registry_hrn: + continue + + # if the best match (longest matching hrn) is not the local registry, + # forward the request + hrns = hrn_dict[registry_hrn] + if registry_hrn != api.hrn: + credential = api.getCredential() + peer_records = registries[registry_hrn].resolve(credential, hrn, origin_hrn) + records.extend([GeniRecord(dict=record).as_dict() for record in peer_records]) + + # try resolving the remaining unfound records at the local registry + remaining_hrns = set(hrns).difference([record['hrn'] for record in records]) + table = GeniTable() + local_records = table.findObjects({'hrn': remaining_hrns}) + for record in local_records: + try: + api.fill_record_info(record) + records.append(dict(record)) + except PlanetLabRecordDoesNotExist: + # silently drop the ones that are missing in PL + print >> log, "ignoring geni record ", record['hrn'], \ + " because pl record does not exist" + table.remove(record) + + if not records: + raise RecordNotFound(str(hrns)) + + if type: + records = filter(lambda rec: rec['type'] == type, records) + + return records + +def list(api, hrn): + # load all know registry names into a prefix tree and attempt to find + # the longest matching prefix + records = [] + registries = Registries(api) + hrns = registries.keys() + tree = prefixTree() + tree.load(hrns) + registry_hrn = tree.best_match(hrn) + + #if there was no match then this record belongs to an unknow registry + if not registry_hrn: + raise MissingAuthority(hrn) + + # if the best match (longest matching hrn) is not the local registry, + # forward the request + records = [] + if registry_hrn != api.hrn: + credential = api.getCredential() + record_list = registries[registry_hrn].list(credential, hrn, origin_hrn) + records = [GeniRecord(dict=record).as_dict() for record in record_list] + + # if we still havnt found the record yet, try the local registry + if not records: + if not api.auth.hierarchy.auth_exists(hrn): + raise MissingAuthority(hrn) + + table = GeniTable() + records = table.find({'authority': hrn}) + + return records + + +def register(api, record): + + hrn, type = record['hrn'], record['type'] + + # validate the type + if type not in ['authority', 'slice', 'node', 'user']: + raise UnknownGeniType(type) + + # check if record already exists + table = GeniTable() + existing_records = table.find({'type': type, 'hrn': hrn}) + if existing_records: + raise ExistingRecord(hrn) + + record = GeniRecord(dict = record) + record['authority'] = get_authority(record['hrn']) + type = record['type'] + hrn = record['hrn'] + api.auth.verify_object_permission(hrn) + auth_info = api.auth.get_auth_info(record['authority']) + pub_key = None + # make sure record has a gid + if 'gid' not in record: + uuid = create_uuid() + pkey = Keypair(create=True) + if 'key' in record and record['key']: + if isinstance(record['key'], list): + pub_key = record['key'][0] + else: + pub_key = record['key'] + pkey = convert_public_key(pub_key) + + gid_object = api.auth.hierarchy.create_gid(hrn, uuid, pkey) + gid = gid_object.save_to_string(save_parents=True) + record['gid'] = gid + record.set_gid(gid) + + if type in ["authority"]: + # update the tree + if not api.auth.hierarchy.auth_exists(hrn): + api.auth.hierarchy.create_auth(hrn) + + # get the GID from the newly created authority + gid = auth_info.get_gid_object() + record.set_gid(gid.save_to_string(save_parents=True)) + pl_record = api.geni_fields_to_pl_fields(type, hrn, record) + sites = api.plshell.GetSites(api.plauth, [pl_record['login_base']]) + if not sites: + pointer = api.plshell.AddSite(api.plauth, pl_record) + else: + pointer = sites[0]['site_id'] + + record.set_pointer(pointer) + record['pointer'] = pointer + + elif (type == "slice"): + acceptable_fields=['url', 'instantiation', 'name', 'description'] + pl_record = api.geni_fields_to_pl_fields(type, hrn, record) + for key in pl_record.keys(): + if key not in acceptable_fields: + pl_record.pop(key) + slices = api.plshell.GetSlices(api.plauth, [pl_record['name']]) + if not slices: + pointer = api.plshell.AddSlice(api.plauth, pl_record) + else: + pointer = slices[0]['slice_id'] + record.set_pointer(pointer) + record['pointer'] = pointer + + elif (type == "user"): + persons = api.plshell.GetPersons(api.plauth, [record['email']]) + if not persons: + pointer = api.plshell.AddPerson(api.plauth, dict(record)) + else: + pointer = persons[0]['person_id'] + + if 'enabled' in record and record['enabled']: + api.plshell.UpdatePerson(api.plauth, pointer, {'enabled': record['enabled']}) + # add this persons to the site only if he is being added for the first + # time by sfa and doesont already exist in plc + if not persons or not persons[0]['site_ids']: + login_base = get_leaf(record['authority']) + api.plshell.AddPersonToSite(api.plauth, pointer, login_base) + + # What roles should this user have? + api.plshell.AddRoleToPerson(api.plauth, 'user', pointer) + # Add the user's key + if pub_key: + api.plshell.AddPersonKey(api.plauth, pointer, {'key_type' : 'ssh', 'key' : pub_key}) + + elif (type == "node"): + pl_record = api.geni_fields_to_pl_fields(type, hrn, record) + login_base = hrn_to_pl_login_base(record['authority']) + nodes = api.plshell.GetNodes(api.plauth, [pl_record['hostname']]) + if not nodes: + pointer = api.plshell.AddNode(api.plauth, login_base, pl_record) + else: + pointer = nodes[0]['node_id'] + + record['pointer'] = pointer + record.set_pointer(pointer) + record_id = table.insert(record) + record['record_id'] = record_id + + # update membership for researchers, pis, owners, operators + api.update_membership(None, record) + + return record.get_gid_object().save_to_string(save_parents=True) + +def update(api, record_dict): + new_record = GeniRecord(dict = record_dict) + type = new_record['type'] + hrn = new_record['hrn'] + api.auth.verify_object_permission(hrn) + table = GeniTable() + # make sure the record exists + records = table.findObjects({'type': type, 'hrn': hrn}) + if not records: + raise RecordNotFound(hrn) + record = records[0] + record['last_updated'] = time.gmtime() + + # Update_membership needs the membership lists in the existing record + # filled in, so it can see if members were added or removed + api.fill_record_info(record) + + # Use the pointer from the existing record, not the one that the user + # gave us. This prevents the user from inserting a forged pointer + pointer = record['pointer'] + # update the PLC information that was specified with the record + + if (type == "authority"): + api.plshell.UpdateSite(api.plauth, pointer, new_record) + + elif type == "slice": + pl_record=api.geni_fields_to_pl_fields(type, hrn, new_record) + if 'name' in pl_record: + pl_record.pop('name') + api.plshell.UpdateSlice(api.plauth, pointer, pl_record) + + elif type == "user": + # SMBAKER: UpdatePerson only allows a limited set of fields to be + # updated. Ideally we should have a more generic way of doing + # this. I copied the field names from UpdatePerson.py... + update_fields = {} + all_fields = new_record + for key in all_fields.keys(): + if key in ['first_name', 'last_name', 'title', 'email', + 'password', 'phone', 'url', 'bio', 'accepted_aup', + 'enabled']: + update_fields[key] = all_fields[key] + api.plshell.UpdatePerson(api.plauth, pointer, update_fields) + + if 'key' in new_record and new_record['key']: + # must check this key against the previous one if it exists + persons = api.plshell.GetPersons(api.plauth, [pointer], ['key_ids']) + person = persons[0] + keys = person['key_ids'] + keys = api.plshell.GetKeys(api.plauth, person['key_ids']) + key_exists = False + if isinstance(new_record['key'], list): + new_key = new_record['key'][0] + else: + new_key = new_record['key'] + + # Delete all stale keys + for key in keys: + if new_record['key'] != key['key']: + api.plshell.DeleteKey(api.plauth, key['key_id']) + else: + key_exists = True + if not key_exists: + api.plshell.AddPersonKey(api.plauth, pointer, {'key_type': 'ssh', 'key': new_key}) + + # update the openssl key and gid + pkey = convert_public_key(new_key) + uuid = create_uuid() + gid_object = api.auth.hierarchy.create_gid(hrn, uuid, pkey) + gid = gid_object.save_to_string(save_parents=True) + record['gid'] = gid + record = GeniRecord(dict=record) + table.update(record) + + elif type == "node": + api.plshell.UpdateNode(api.plauth, pointer, new_record) + + else: + raise UnknownGeniType(type) + + # update membership for researchers, pis, owners, operators + api.update_membership(record, new_record) + + return 1 + +def remove(api, hrn, type, origin_hrn=None): + table = GeniTable() + filter = {'hrn': hrn} + if type not in ['all', '*']: + filter['type'] = type + records = table.find(filter) + if not records: + raise RecordNotFound(hrn) + record = records[0] + type = record['type'] + + credential = api.getCredential() + registries = Registries(api) + + # Try to remove the object from the PLCDB of federated agg. + # This is attempted before removing the object from the local agg's PLCDB and sfa table + if hrn.startswith(api.hrn) and type in ['user', 'slice', 'authority']: + for registry in registries: + if registry not in [api.hrn]: + try: + result=registries[registry].remove_peer_object(credential, record, origin_hrn) + except: + pass + if type == "user": + persons = api.plshell.GetPersons(api.plauth, record['pointer']) + # only delete this person if he has site ids. if he doesnt, it probably means + # he was just removed from a site, not actually deleted + if persons and persons[0]['site_ids']: + api.plshell.DeletePerson(api.plauth, record['pointer']) + elif type == "slice": + if api.plshell.GetSlices(api.plauth, record['pointer']): + api.plshell.DeleteSlice(api.plauth, record['pointer']) + elif type == "node": + if api.plshell.GetNodes(api.plauth, record['pointer']): + api.plshell.DeleteNode(api.plauth, record['pointer']) + elif type == "authority": + if api.plshell.GetSites(api.plauth, record['pointer']): + api.plshell.DeleteSite(api.plauth, record['pointer']) + else: + raise UnknownGeniType(type) + + table.remove(record) + + return 1 + +def remove_peer_object(api, record, origin_hrn=None): + pass + +def register_peer_object(api, record, origin_hrn=None): + pass diff --git a/sfa/methods/create_slice.py b/sfa/methods/create_slice.py index 7287b512..5bad7f8a 100644 --- a/sfa/methods/create_slice.py +++ b/sfa/methods/create_slice.py @@ -2,7 +2,6 @@ ### $URL$ from sfa.util.faults import * -from sfa.util.misc import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed from sfa.trust.auth import Auth diff --git a/sfa/methods/delete_slice.py b/sfa/methods/delete_slice.py index cc43c50f..8e413c12 100644 --- a/sfa/methods/delete_slice.py +++ b/sfa/methods/delete_slice.py @@ -2,7 +2,6 @@ ### $URL$ from sfa.util.faults import * -from sfa.util.misc import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed from sfa.trust.auth import Auth diff --git a/sfa/methods/get_aggregates.py b/sfa/methods/get_aggregates.py index 0625431e..66720d2c 100644 --- a/sfa/methods/get_aggregates.py +++ b/sfa/methods/get_aggregates.py @@ -2,7 +2,6 @@ ### $URL: https://svn.planet-lab.org/svn/sfa/trunk/sfa/methods/get_aggregates.py $ from types import StringTypes from sfa.util.faults import * -from sfa.util.misc import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed from sfa.trust.auth import Auth diff --git a/sfa/methods/get_credential.py b/sfa/methods/get_credential.py index cc11cab0..c11c5671 100644 --- a/sfa/methods/get_credential.py +++ b/sfa/methods/get_credential.py @@ -6,10 +6,6 @@ from sfa.trust.rights import * from sfa.util.faults import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed -from sfa.trust.auth import Auth -from sfa.trust.gid import GID -from sfa.util.record import GeniRecord -from sfa.util.genitable import * from sfa.util.debug import log class get_credential(Method): @@ -38,46 +34,10 @@ class get_credential(Method): self.api.auth.check(cred, 'getcredential') self.api.auth.verify_object_belongs_to_me(hrn) - auth_hrn = self.api.auth.get_authority(hrn) - - # Is this a root or sub authority - if not auth_hrn or hrn == self.api.config.SFA_INTERFACE_HRN: - auth_hrn = hrn - - # get record info - auth_info = self.api.auth.get_auth_info(auth_hrn) - table = GeniTable() - records = table.find({'type': type, 'hrn': hrn}) - if not records: - raise RecordNotFound(hrn) - record = records[0] - - # verify_cancreate_credential requires that the member lists - # (researchers, pis, etc) be filled in - self.api.fill_record_info(record) - - caller_hrn = self.api.auth.client_cred.get_gid_caller().get_hrn() - object_hrn = self.api.auth.client_cred.get_gid_object().get_hrn() - rights = self.api.auth.determine_user_rights(caller_hrn, record) - # make sure caller has rights to this object - if rights.is_empty(): - raise PermissionError(object_hrn + " has no rights to " + record['name']) - - gid = record['gid'] - gid_object = GID(string=gid) - new_cred = Credential(subject = gid_object.get_subject()) - new_cred.set_gid_caller(self.api.auth.client_gid) - new_cred.set_gid_object(gid_object) - new_cred.set_issuer(key=auth_info.get_pkey_object(), subject=auth_hrn) - new_cred.set_pubkey(gid_object.get_pubkey()) - new_cred.set_privileges(rights) - new_cred.set_delegate(True) - - auth_kind = "authority,ma,sa" - new_cred.set_parent(self.api.auth.hierarchy.get_auth_cred(auth_hrn, kind=auth_kind)) - - new_cred.encode() - new_cred.sign() - - return new_cred.save_to_string(save_parents=True) + # send the call to the right manager + manager_base = 'sfa.managers' + mgr_type = self.api.config.SFA_REGISTRY_TYPE + manager_module = manager_base + ".registry_manager_%s" % mgr_type + manager = __import__(manager_module, fromlist=[manager_base]) + return manager.get_credential(self.api, hrn, type) diff --git a/sfa/methods/get_gid.py b/sfa/methods/get_gid.py index 06faf603..65f71e56 100644 --- a/sfa/methods/get_gid.py +++ b/sfa/methods/get_gid.py @@ -6,7 +6,6 @@ # raise ConnectionKeyGIDMismatch(gid.get_subject()) from sfa.util.faults import * -from sfa.util.misc import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed from sfa.trust.auth import Auth diff --git a/sfa/methods/get_gids.py b/sfa/methods/get_gids.py index b4912f8a..444cd98e 100644 --- a/sfa/methods/get_gids.py +++ b/sfa/methods/get_gids.py @@ -6,7 +6,6 @@ # raise ConnectionKeyGIDMismatch(gid.get_subject()) from sfa.util.faults import * -from sfa.util.misc import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed from sfa.trust.auth import Auth diff --git a/sfa/methods/get_key.py b/sfa/methods/get_key.py index 2a31a919..6ede861a 100644 --- a/sfa/methods/get_key.py +++ b/sfa/methods/get_key.py @@ -4,7 +4,7 @@ import os import tempfile import commands from sfa.util.faults import * -from sfa.util.misc import * +from sfa.util.namespace import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed from sfa.trust.auth import Auth diff --git a/sfa/methods/get_registries.py b/sfa/methods/get_registries.py index 13055d3a..dcc259a8 100644 --- a/sfa/methods/get_registries.py +++ b/sfa/methods/get_registries.py @@ -2,7 +2,6 @@ ### $URL: https://svn.planet-lab.org/svn/sfa/trunk/sfa/methods/get_registries.py $ from types import StringTypes from sfa.util.faults import * -from sfa.util.misc import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed from sfa.trust.auth import Auth diff --git a/sfa/methods/get_self_credential.py b/sfa/methods/get_self_credential.py index eeac6d9d..ab55c47c 100644 --- a/sfa/methods/get_self_credential.py +++ b/sfa/methods/get_self_credential.py @@ -6,10 +6,7 @@ from sfa.trust.rights import * from sfa.util.faults import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed -from sfa.trust.auth import Auth -from sfa.trust.gid import GID from sfa.util.record import GeniRecord -from sfa.util.genitable import * from sfa.util.debug import log class get_self_credential(Method): @@ -50,54 +47,24 @@ class get_self_credential(Method): @return string representation of a credential object """ self.api.auth.verify_object_belongs_to_me(hrn) - auth_hrn = self.api.auth.get_authority(hrn) - - # if this is a root or sub authority get_authority will return - # an empty string - if not auth_hrn or hrn == self.api.config.SFA_INTERFACE_HRN: - auth_hrn = hrn - - auth_info = self.api.auth.get_auth_info(auth_hrn) + + # send the call to the right manager + manager_base = 'sfa.managers' + mgr_type = self.api.config.SFA_REGISTRY_TYPE + manager_module = manager_base + ".registry_manager_%s" % mgr_type + manager = __import__(manager_module, fromlist=[manager_base]) - # find a record that matches - record = None - table = GeniTable() - records = table.findObjects({'type': type, 'hrn': hrn}) + # authenticate the gid + records = manager.resolve(self.api, hrn, type) if not records: raise RecordNotFound(hrn) - record = records[0] - - # authenticate the gid + record = GeniRecord(dict=records[0]) gid = record.get_gid_object() gid_str = gid.save_to_string(save_parents=True) self.api.auth.authenticateGid(gid_str, [cert, type, hrn], request_hash) - # authenticate the certificate against the gid in the db certificate = Certificate(string=cert) if not certificate.is_pubkey(gid.get_pubkey()): raise ConnectionKeyGIDMismatch(gid.get_subject()) - - # get the right of this record - #caller_hrn = certificate.get_subject() - # server.cert has subject 'registry' - caller_hrn=hrn - rights = self.api.auth.determine_user_rights(caller_hrn, record) - if rights.is_empty(): - raise PermissionError(caller_hrn + " has no rights to " + record.get_name()) - - # create the credential - gid = record.get_gid_object() - cred = Credential(subject = gid.get_subject()) - cred.set_gid_caller(gid) - cred.set_gid_object(gid) - cred.set_issuer(key=auth_info.get_pkey_object(), subject=auth_hrn) - cred.set_pubkey(gid.get_pubkey()) - cred.set_privileges(rights) - cred.set_delegate(True) - - auth_kind = "authority,sa,ma" - cred.set_parent(self.api.auth.hierarchy.get_auth_cred(auth_hrn, kind=auth_kind)) - - cred.encode() - cred.sign() - return cred.save_to_string(save_parents=True) + + return manager.get_credential(self.api, hrn, type, is_self=True) diff --git a/sfa/methods/get_slices.py b/sfa/methods/get_slices.py index fe5c0941..b5d23d25 100644 --- a/sfa/methods/get_slices.py +++ b/sfa/methods/get_slices.py @@ -2,7 +2,6 @@ ### $URL$ from sfa.util.faults import * -from sfa.util.misc import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed from sfa.trust.auth import Auth diff --git a/sfa/methods/get_trusted_certs.py b/sfa/methods/get_trusted_certs.py index 9aaca122..7c62240d 100644 --- a/sfa/methods/get_trusted_certs.py +++ b/sfa/methods/get_trusted_certs.py @@ -2,7 +2,6 @@ ### $URL: https://svn.planet-lab.org/svn/sfa/trunk/sfa/methods/reset_slices.py $ from sfa.util.faults import * -from sfa.util.misc import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed from sfa.trust.auth import Auth diff --git a/sfa/methods/list.py b/sfa/methods/list.py index 727e5449..bd600d3f 100644 --- a/sfa/methods/list.py +++ b/sfa/methods/list.py @@ -4,11 +4,7 @@ from sfa.util.faults import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed -from sfa.trust.auth import Auth from sfa.util.record import GeniRecord -from sfa.util.genitable import GeniTable -from sfa.server.registry import Registries -from sfa.util.prefixTree import prefixTree from sfa.trust.credential import Credential class list(Method): @@ -39,35 +35,10 @@ class list(Method): # validate the cred self.api.auth.check(cred, 'list') - - # load all know registry names into a prefix tree and attempt to find - # the longest matching prefix - records = [] - registries = Registries(self.api) - hrns = registries.keys() - tree = prefixTree() - tree.load(hrns) - registry_hrn = tree.best_match(hrn) - - #if there was no match then this record belongs to an unknow registry - if not registry_hrn: - raise MissingAuthority(hrn) - - # if the best match (longest matching hrn) is not the local registry, - # forward the request - if registry_hrn != self.api.hrn: - credential = self.api.getCredential() - record_list = registries[registry_hrn].list(credential, hrn, origin_hrn) - records = [GeniRecord(dict=record).as_dict() for record in record_list] - - if records: - return records - - # if we still havnt found the record yet, try the local registry - if not self.api.auth.hierarchy.auth_exists(hrn): - raise MissingAuthority(hrn) - - table = GeniTable() - records = table.find({'authority': hrn}) - return records + # send the call to the right manager + manager_base = 'sfa.managers' + mgr_type = self.api.config.SFA_REGISTRY_TYPE + manager_module = manager_base + ".registry_manager_%s" % mgr_type + manager = __import__(manager_module, fromlist=[manager_base]) + return manager.list(self.api, hrn) diff --git a/sfa/methods/reboot.py b/sfa/methods/reboot.py index 3136be3b..ae9e9b5d 100644 --- a/sfa/methods/reboot.py +++ b/sfa/methods/reboot.py @@ -2,7 +2,6 @@ ### $URL: https://svn.planet-lab.org/svn/sfa/trunk/sfacomponent/methods/reboot.py $ import os from sfa.util.faults import * -from sfa.util.misc import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed diff --git a/sfa/methods/redeem_ticket.py b/sfa/methods/redeem_ticket.py index 4ea1dba5..db686cc7 100644 --- a/sfa/methods/redeem_ticket.py +++ b/sfa/methods/redeem_ticket.py @@ -2,7 +2,6 @@ ### $URL: https://svn.planet-lab.org/svn/sfa/trunk/sfacomponent/methods/reset_slice.py $ import xmlrpclib from sfa.util.faults import * -from sfa.util.misc import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed diff --git a/sfa/methods/register.py b/sfa/methods/register.py index 8339afe3..c8216059 100644 --- a/sfa/methods/register.py +++ b/sfa/methods/register.py @@ -3,9 +3,7 @@ from sfa.trust.certificate import Keypair, convert_public_key from sfa.trust.gid import * - from sfa.util.faults import * -from sfa.util.misc import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed from sfa.util.record import GeniRecord @@ -36,124 +34,23 @@ class register(Method): returns = Parameter(int, "String representation of gid object") - def call(self, cred, record_dict, origin_hrn=None): + def call(self, cred, record, origin_hrn=None): user_cred = Credential(string=cred) #log the call if not origin_hrn: origin_hrn = user_cred.get_gid_caller().get_hrn() + hrn = None + if 'hrn' in record: + hrn = record['hrn'] self.api.logger.info("interface: %s\tcaller-hrn: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, origin_hrn, hrn, self.name)) # validate the cred self.api.auth.check(cred, "register") - - record = GeniRecord(dict = record_dict) - record['authority'] = get_authority(record['hrn']) - type = record['type'] - hrn = record['hrn'] - self.api.auth.verify_object_permission(hrn) - auth_info = self.api.auth.get_auth_info(record['authority']) - pub_key = None - # make sure record has a gid - if 'gid' not in record: - uuid = create_uuid() - pkey = Keypair(create=True) - if 'key' in record and record['key']: - if isinstance(record['key'], list): - pub_key = record['key'][0] - else: - pub_key = record['key'] - pkey = convert_public_key(pub_key) - - gid_object = self.api.auth.hierarchy.create_gid(hrn, uuid, pkey) - gid = gid_object.save_to_string(save_parents=True) - record['gid'] = gid - record.set_gid(gid) - - # check if record already exists - table = GeniTable() - existing_records = table.find({'type': type, 'hrn': hrn}) - if existing_records: - raise ExistingRecord(hrn) - - if type in ["authority"]: - # update the tree - if not self.api.auth.hierarchy.auth_exists(hrn): - self.api.auth.hierarchy.create_auth(hrn) - - # authorities are special since they are managed by the registry - # rather than by the caller. We create our own GID for the - # authority rather than relying on the caller to supply one. - - # get the GID from the newly created authority - gid = auth_info.get_gid_object() - record.set_gid(gid.save_to_string(save_parents=True)) - - pl_record = self.api.geni_fields_to_pl_fields(type, hrn, record) - sites = self.api.plshell.GetSites(self.api.plauth, [pl_record['login_base']]) - if not sites: - pointer = self.api.plshell.AddSite(self.api.plauth, pl_record) - else: - pointer = sites[0]['site_id'] - - record.set_pointer(pointer) - record['pointer'] = pointer - - elif (type == "slice"): - acceptable_fields=['url', 'instantiation', 'name', 'description'] - pl_record = self.api.geni_fields_to_pl_fields(type, hrn, record) - for key in pl_record.keys(): - if key not in acceptable_fields: - pl_record.pop(key) - slices = self.api.plshell.GetSlices(self.api.plauth, [pl_record['name']]) - if not slices: - pointer = self.api.plshell.AddSlice(self.api.plauth, pl_record) - else: - pointer = slices[0]['slice_id'] - record.set_pointer(pointer) - record['pointer'] = pointer - - elif (type == "user"): - persons = self.api.plshell.GetPersons(self.api.plauth, [record['email']]) - if not persons: - pointer = self.api.plshell.AddPerson(self.api.plauth, dict(record)) - else: - raise ExistingRecord(record['email']) - - if 'enabled' in record and record['enabled']: - self.api.plshell.UpdatePerson(self.api.plauth, pointer, {'enabled': record['enabled']}) - # add this persons to the site only if he is being added for the first - # time by sfa and doesont already exist in plc - if not persons or not persons[0]['site_ids']: - login_base = get_leaf(record['authority']) - self.api.plshell.AddPersonToSite(self.api.plauth, pointer, login_base) - - # What roles should this user have? - self.api.plshell.AddRoleToPerson(self.api.plauth, 'user', pointer) - record.set_pointer(pointer) - record['pointer'] = pointer - # Add the user's key - if pub_key: - self.api.plshell.AddPersonKey(self.api.plauth, pointer, {'key_type' : 'ssh', 'key' : pub_key}) - - elif (type == "node"): - pl_record = self.api.geni_fields_to_pl_fields(type, hrn, record) - login_base = hrn_to_pl_login_base(record['authority']) - nodes = self.api.plshell.GetNodes(self.api.plauth, [pl_record['hostname']]) - if not nodes: - pointer = self.api.plshell.AddNode(self.api.plauth, login_base, pl_record) - else: - pointer = nodes[0]['node_id'] - record['pointer'] = pointer - record.set_pointer(pointer) - - else: - raise UnknownGeniType(type) - - record_id = table.insert(record) - record['record_id'] = record_id - - # update membership for researchers, pis, owners, operators - self.api.update_membership(None, record) - return record.get_gid_object().save_to_string(save_parents=True) + #send the call to the right manager + manager_base = 'sfa.managers' + mgr_type = self.api.config.SFA_REGISTRY_TYPE + manager_module = manager_base + ".registry_manager_%s" % mgr_type + manager = __import__(manager_module, fromlist=[manager_base]) + return manager.register(self.api, record) diff --git a/sfa/methods/register_peer_object.py b/sfa/methods/register_peer_object.py index 70057166..0d8c8537 100644 --- a/sfa/methods/register_peer_object.py +++ b/sfa/methods/register_peer_object.py @@ -5,7 +5,7 @@ from sfa.trust.certificate import Keypair, convert_public_key from sfa.trust.gid import * from sfa.util.faults import * -from sfa.util.misc import * +from sfa.util.namespace import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed from sfa.util.record import GeniRecord diff --git a/sfa/methods/remove.py b/sfa/methods/remove.py index 89250027..1b1ae989 100644 --- a/sfa/methods/remove.py +++ b/sfa/methods/remove.py @@ -4,12 +4,8 @@ from sfa.util.faults import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed -from sfa.trust.auth import Auth -from sfa.util.record import GeniRecord -from sfa.util.genitable import GeniTable from sfa.util.debug import log from sfa.trust.credential import Credential -from sfa.server.registry import Registries class remove(Method): """ @@ -46,45 +42,10 @@ class remove(Method): # validate the cred self.api.auth.check(cred, "remove") self.api.auth.verify_object_permission(hrn) - - table = GeniTable() - filter = {'hrn': hrn} - if type not in ['all', '*']: - filter['type'] = type - records = table.find(filter) - if not records: - raise RecordNotFound(hrn) - record = records[0] - type = record['type'] - - credential = self.api.getCredential() - registries = Registries(self.api) - - # Try to remove the object from the PLCDB of federated agg. - # This is attempted before removing the object from the local agg's PLCDB and sfa table - if hrn.startswith(self.api.hrn) and type in ['user', 'slice', 'authority']: - for registry in registries: - if registry not in [self.api.hrn]: - result=registries[registry].remove_peer_object(credential, record, origin_hrn) - pass - if type == "user": - persons = self.api.plshell.GetPersons(self.api.plauth, record['pointer']) - # only delete this person if he has site ids. if he doesnt, it probably means - # he was just removed from a site, not actually deleted - if persons and persons[0]['site_ids']: - self.api.plshell.DeletePerson(self.api.plauth, record['pointer']) - elif type == "slice": - if self.api.plshell.GetSlices(self.api.plauth, record['pointer']): - self.api.plshell.DeleteSlice(self.api.plauth, record['pointer']) - elif type == "node": - if self.api.plshell.GetNodes(self.api.plauth, record['pointer']): - self.api.plshell.DeleteNode(self.api.plauth, record['pointer']) - elif type == "authority": - if self.api.plshell.GetSites(self.api.plauth, record['pointer']): - self.api.plshell.DeleteSite(self.api.plauth, record['pointer']) - else: - raise UnknownGeniType(type) - - table.remove(record) - - return 1 + + # send the call to the right manager + manager_base = 'sfa.managers' + mgr_type = self.api.config.SFA_REGISTRY_TYPE + manager_module = manager_base + ".registry_manager_%s" % mgr_type + manager = __import__(manager_module, fromlist=[manager_base]) + return manager.remove(self.api, hrn, type, origin_hrn) diff --git a/sfa/methods/remove_peer_object.py b/sfa/methods/remove_peer_object.py index be8f09cd..83432642 100644 --- a/sfa/methods/remove_peer_object.py +++ b/sfa/methods/remove_peer_object.py @@ -6,7 +6,6 @@ from sfa.util.record import GeniRecord from sfa.util.genitable import GeniTable from sfa.util.debug import log from sfa.trust.credential import Credential -from sfa.util.misc import * from types import StringTypes class remove_peer_object(Method): diff --git a/sfa/methods/reset_slice.py b/sfa/methods/reset_slice.py index 89eeb880..8bb47307 100644 --- a/sfa/methods/reset_slice.py +++ b/sfa/methods/reset_slice.py @@ -2,7 +2,6 @@ ### $URL: https://svn.planet-lab.org/svn/sfa/trunk/sfa/methods/reset_slices.py $ from sfa.util.faults import * -from sfa.util.misc import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed from sfa.trust.auth import Auth diff --git a/sfa/methods/resolve.py b/sfa/methods/resolve.py index ba785d69..5761d342 100644 --- a/sfa/methods/resolve.py +++ b/sfa/methods/resolve.py @@ -4,13 +4,9 @@ import traceback from sfa.util.faults import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed -from sfa.trust.auth import Auth -from sfa.util.record import GeniRecord -from sfa.util.genitable import GeniTable from sfa.util.debug import log -from sfa.server.registry import Registries -from sfa.util.prefixTree import prefixTree from sfa.trust.credential import Credential +from sfa.util.record import GeniRecord class resolve(Method): """ @@ -25,7 +21,8 @@ class resolve(Method): accepts = [ Parameter(str, "Credential string"), - Parameter(str, "Human readable name (hrn)") + Mixed(Parameter(str, "Human readable name (hrn)"), + Parameter(list, "List of Human readable names ([hrn])")) ] returns = [GeniRecord] @@ -40,44 +37,12 @@ class resolve(Method): # validate the cred self.api.auth.check(cred, 'resolve') - - # load all know registry names into a prefix tree and attempt to find - # the longest matching prefix - good_records = [] - registries = Registries(self.api) - hrns = registries.keys() - tree = prefixTree() - tree.load(hrns) - registry_hrn = tree.best_match(hrn) - - #if there was no match then this record belongs to an unknow registry - if not registry_hrn: - raise MissingAuthority(hrn) - - # if the best match (longest matching hrn) is not the local registry, - # forward the request - if registry_hrn != self.api.hrn: - credential = self.api.getCredential() - records = registries[registry_hrn].resolve(credential, hrn, origin_hrn) - good_records = [GeniRecord(dict=record).as_dict() for record in records] - if good_records: - return good_records - - # if we still havnt found the record yet, try the local registry - table = GeniTable() - records = table.findObjects(hrn) - if not records: - raise RecordNotFound(hrn) - for record in records: - try: - self.api.fill_record_info(record) - good_records.append(dict(record)) - except PlanetLabRecordDoesNotExist: - # silently drop the ones that are missing in PL - print >> log, "ignoring geni record ", record['hrn'], \ - " because pl record does not exist" - table.remove(record) + # send the call to the right manager + manager_base = 'sfa.managers' + mgr_type = self.api.config.SFA_REGISTRY_TYPE + manager_module = manager_base + ".registry_manager_%s" % mgr_type + manager = __import__(manager_module, fromlist=[manager_base]) + return manager.resolve(self.api, hrn, origin_hrn=origin_hrn) - return good_records diff --git a/sfa/methods/start_slice.py b/sfa/methods/start_slice.py index 01d8293a..f145f282 100644 --- a/sfa/methods/start_slice.py +++ b/sfa/methods/start_slice.py @@ -2,7 +2,7 @@ ### $URL$ from sfa.util.faults import * -from sfa.util.misc import * +from sfa.util.namespace import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed from sfa.trust.auth import Auth diff --git a/sfa/methods/stop_slice.py b/sfa/methods/stop_slice.py index 77ecd3fb..f34c1bc8 100644 --- a/sfa/methods/stop_slice.py +++ b/sfa/methods/stop_slice.py @@ -2,7 +2,7 @@ ### $URL$ from sfa.util.faults import * -from sfa.util.misc import * +from sfa.util.namespace import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed from sfa.trust.auth import Auth diff --git a/sfa/methods/update.py b/sfa/methods/update.py index e97a3267..05916b3b 100644 --- a/sfa/methods/update.py +++ b/sfa/methods/update.py @@ -5,11 +5,6 @@ import time from sfa.util.faults import * from sfa.util.method import Method from sfa.util.parameter import Parameter, Mixed -from sfa.trust.auth import Auth -from sfa.util.record import GeniRecord -from sfa.util.genitable import GeniTable -from sfa.trust.certificate import Keypair, convert_public_key -from sfa.trust.gid import * from sfa.util.debug import log from sfa.trust.credential import Credential @@ -47,87 +42,10 @@ class update(Method): # validate the cred self.api.auth.check(cred, "update") - new_record = GeniRecord(dict = record_dict) - type = new_record['type'] - hrn = new_record['hrn'] - self.api.auth.verify_object_permission(hrn) - table = GeniTable() - # make sure the record exists - records = table.findObjects({'type': type, 'hrn': hrn}) - if not records: - raise RecordNotFound(hrn) - record = records[0] - record['last_updated'] = time.gmtime() - - # Update_membership needs the membership lists in the existing record - # filled in, so it can see if members were added or removed - self.api.fill_record_info(record) + # send the call to the right manager + manager_base = 'sfa.managers' + mgr_type = self.api.config.SFA_REGISTRY_TYPE + manager_module = manager_base + ".registry_manager_%s" % mgr_type + manager = __import__(manager_module, fromlist=[manager_base]) + return manager.update(self.api, record_dict) - # Use the pointer from the existing record, not the one that the user - # gave us. This prevents the user from inserting a forged pointer - pointer = record['pointer'] - - # update the PLC information that was specified with the record - - if (type == "authority"): - self.api.plshell.UpdateSite(self.api.plauth, pointer, new_record) - - elif type == "slice": - pl_record=self.api.geni_fields_to_pl_fields(type, hrn, new_record) - if 'name' in pl_record: - pl_record.pop('name') - self.api.plshell.UpdateSlice(self.api.plauth, pointer, pl_record) - - elif type == "user": - # SMBAKER: UpdatePerson only allows a limited set of fields to be - # updated. Ideally we should have a more generic way of doing - # this. I copied the field names from UpdatePerson.py... - update_fields = {} - all_fields = new_record - for key in all_fields.keys(): - if key in ['first_name', 'last_name', 'title', 'email', - 'password', 'phone', 'url', 'bio', 'accepted_aup', - 'enabled']: - update_fields[key] = all_fields[key] - self.api.plshell.UpdatePerson(self.api.plauth, pointer, update_fields) - - if 'key' in new_record and new_record['key']: - # must check this key against the previous one if it exists - persons = self.api.plshell.GetPersons(self.api.plauth, [pointer], ['key_ids']) - person = persons[0] - keys = person['key_ids'] - keys = self.api.plshell.GetKeys(self.api.plauth, person['key_ids']) - key_exists = False - if isinstance(new_record['key'], list): - new_key = new_record['key'][0] - else: - new_key = new_record['key'] - - # Delete all stale keys - for key in keys: - if new_record['key'] != key['key']: - self.api.plshell.DeleteKey(self.api.plauth, key['key_id']) - else: - key_exists = True - if not key_exists: - self.api.plshell.AddPersonKey(self.api.plauth, pointer, {'key_type': 'ssh', 'key': new_key}) - - # update the openssl key and gid - pkey = convert_public_key(new_key) - uuid = create_uuid() - gid_object = self.api.auth.hierarchy.create_gid(hrn, uuid, pkey) - gid = gid_object.save_to_string(save_parents=True) - record['gid'] = gid - record = GeniRecord(dict=record) - table.update(record) - - elif type == "node": - self.api.plshell.UpdateNode(self.api.plauth, pointer, new_record) - - else: - raise UnknownGeniType(type) - - # update membership for researchers, pis, owners, operators - self.api.update_membership(record, new_record) - - return 1 -- 2.47.0