methods="""
+create_gid
get_credential
+get_ticket
list
+register
+remove
resolve
+update
""".split()
--- /dev/null
+from geni.util.faults import *
+from geni.util.excep import *
+from geni.util.method import Method
+from geni.util.parameter import Parameter, Mixed
+from geni.util.auth import Auth
+from geni.util.cert import Keypair
+
+class create_gid(Method):
+ """
+ Create a new GID. For MAs and SAs that are physically located on the
+ registry, this allows a owner/operator/PI to create a new GID and have it
+ signed by his respective authority.
+
+ @param cred credential of caller
+ @param name hrn for new GID
+ @param uuid unique identifier for new GID
+ @param pkey_string public-key string (TODO: why is this a string and not a keypair object?)
+
+ @return the string representation of a GID object
+ """
+
+ interfaces = ['registry']
+
+ accepts = [
+ Parameter(str, "Credential string"),
+ Parameter(str, "Human readable name (hrn)"),
+ Mixed(Parameter(str, "Unique identifier for new GID (uuid)"),
+ Parameter(None, "Unique identifier (uuid) not specified")),
+ Parameter(str, "public-key string")
+ ]
+
+ returns = Parameter(str, "String represeneation of a GID object")
+
+ def call(self, cred, hrn, uuid, pubkey_str):
+ self.api.auth.decode_authentication(cred, "getcredential")
+ self.api.auth.verify_object_belongs_to_me(hrn)
+ self.api.auth.verify_object_permission(hrn)
+
+ if uuid == None:
+ uuid = create_uuid()
+
+ pkey = Keypair()
+ pkey.load_pubkey_from_string(pubkey_str)
+ gid = self.api.auth.hierarchy.create_gid(name, uuid, pkey)
+
+ return gid.save_to_string(save_parents=True)
Parameter(str, "Human readable name (hrn)")
]
- returns = [GeniRecord]
+ returns = Parameter(str, "String representation of a credential object")
def call(self, cred, type, hrn):
if not cred:
return self.get_self_credential(type, hrn)
self.api.auth.check(cred, 'getcredential')
-
self.api.auth.verify_object_belongs_to_me(name)
-
auth_hrn = self.api.auth.get_authority(hrn)
if not auth_hrn:
auth_hrn = hrn
auth_info = self.api.auth.get_auth_info(auth_hrn)
record = None
table = self.api.auth.get_auth_table(auth_hrn)
- records = table.resolve('*', auth_hrn)
+ records = table.resolve('*', hrn)
# verify_cancreate_credential requires that the member lists
# (researchers, pis, etc) be filled in
--- /dev/null
+from geni.util.faults import *
+from geni.util.excep import *
+from geni.util.method import Method
+from geni.util.parameter import Parameter, Mixed
+from geni.util.auth import Auth
+from geni.util.cert import Keypair
+from geni.util.geniticket import *
+
+class get_ticket(Method):
+ """
+ Retrieve a ticket. This operation is currently implemented on PLC
+ only (see SFA, engineering decisions); it is not implemented on
+ components.
+
+ The ticket is filled in with information from the PLC database. This
+ information includes resources, and attributes such as user keys and
+ initscripts.
+
+ @param cred credential string
+ @param name name of the slice to retrieve a ticket for
+ @param rspec resource specification dictionary
+
+ @return the string representation of a ticket object
+ """
+
+ interfaces = ['registry']
+
+ accepts = [
+ Parameter(str, "Credential string"),
+ Parameter(str, "Human readable name of slice to retrive a ticket for (hrn)"),
+ Parameter(str, "Resource specification (rspec)")
+ ]
+
+ returns = Parameter(str, "String represeneation of a ticket object")
+
+ def call(self, cred, hrn, rspec):
+ self.api.auth.decode_authentication(cred, "getticket")
+ self.api.auth.verify_object_belongs_to_me(hrn)
+ self.api.auth.verify_object_permission(name)
+
+ # XXX much of this code looks like get_credential... are they so similar
+ # that they should be combined?
+
+ auth_hrn = self.api.auth.get_authority(hrn)
+ if not auth_hrn:
+ auth_hrn = hrn
+ auth_info = self.api.auth.get_auth_info(auth_hrn)
+ record = None
+ table = self.api.auth.get_auth_table(auth_hrn)
+ records = table.resolve('slice', hrn)
+
+ object_gid = record.get_gid_object()
+ new_ticket = Ticket(subject = object_gid.get_subject())
+ new_ticket.set_gid_caller(self.client_gid)
+ new_ticket.set_gid_object(object_gid)
+ new_ticket.set_issuer(key=auth_info.get_pkey_object(), subject=auth_hrn)
+ new_ticket.set_pubkey(object_gid.get_pubkey())
+
+ self.api.fill_record_info(record)
+
+ (attributes, rspec) = self.api.record_to_slice_info(record)
+
+ new_ticket.set_attributes(attributes)
+ new_ticket.set_rspec(rspec)
+
+ new_ticket.set_parent(self.api.auth.hierarchy.get_auth_ticket(auth_hrn))
+
+ new_ticket.encode()
+ new_ticket.sign()
+
+ return new_ticket.save_to_string(save_parents=True)
+
interfaces = ['registry']
accepts = [
- Parameter(str, "credential"),
+ Parameter(str, "Credential string"),
Parameter(str, "Human readable name (hrn)")
]
--- /dev/null
+from geni.util.faults import *
+from geni.util.excep import *
+from geni.util.method import Method
+from geni.util.parameter import Parameter, Mixed
+from geni.util.auth import Auth
+from geni.util.record import GeniRecord
+from geni.util.debug import log
+
+class register(Method):
+ """
+ Register an object with the registry. In addition to being stored in the
+ Geni database, the appropriate records will also be created in the
+ PLC databases
+
+ @param cred credential string
+ @param record_dict dictionary containing record fields
+
+ @return gid string representation
+ """
+
+ interfaces = ['registry']
+
+ accepts = [
+ Parameter(str, "Credential string"),
+ Parameter(dict, "Record dictionary containing record fields")
+ ]
+
+ returns = Parameter(int, "String representation of gid object")
+
+ def call(self, cred, record_dict):
+ self.decode_authentication(cred, "register")
+ record = GeniRecord(dict = record_dict)
+ type = record.get_type()
+ name = record.get_name()
+ auth_name = self.api.auth.get_authority(name)
+ self.api.auth.verify_object_permission(auth_name)
+ auth_info = self.api.auth.get_auth_info(auth_name)
+ table = self.api.auth.get_auth_table(auth_name)
+ pkey = None
+
+ # check if record already exists
+ existing_records = table.resolve(type, name)
+ if existing_records:
+ raise ExistingRecord(name)
+
+ geni_fields = record.get_geni_info()
+ pl_fields = record.get_pl_info()
+
+ if (type == "sa") or (type=="ma"):
+ # update the tree
+ if not self.api.auth.hierarchy.auth_exists(name):
+ self.api.auth.hierarchy.create_auth(name)
+
+ # 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
+ child_auth_info = self.api.auth.get_auth_info(name)
+ gid = auth_info.get_gid_object()
+ record.set_gid(gid.save_to_string(save_parents=True))
+
+ # if registering a sa, see if a ma already exists
+ # if registering a ma, see if a sa already exists
+ if (type == "sa"):
+ other_rec = table.resolve("ma", record.get_name())
+ elif (type == "ma"):
+ other_rec = table.resolve("sa", record.get_name())
+
+ if other_rec:
+ print >> log, "linking ma and sa to the same plc site"
+ pointer = other_rec[0].get_pointer()
+ else:
+ self.api.geni_fields_to_pl_fields(type, name, geni_fields, pl_fields)
+ print >> log, "adding site with fields", pl_fields
+ pointer = self.api.plshell.AddSite(self.api.plauth, pl_fields)
+
+ record.set_pointer(pointer)
+
+ elif (type == "slice"):
+ self.api.geni_fields_to_pl_fields(type, name, geni_fields, pl_fields)
+ pointer = self.api.plshell.AddSlice(self.api.plauth, pl_fields)
+ record.set_pointer(pointer)
+
+ elif (type == "user"):
+ self.api.geni_fields_to_pl_fields(type, name, geni_fields, pl_fields)
+ pointer = self.api.plshell.AddPerson(self.api.plauth, pl_fields)
+ record.set_pointer(pointer)
+
+ elif (type == "node"):
+ self.api.geni_fields_to_pl_fields(type, name, geni_fields, pl_fields)
+ login_base = self.api.hrn_to_pl_login_base(auth_name)
+ pointer = self.api.plshell.AddNode(self.api.plauth, login_base, pl_fields)
+ record.set_pointer(pointer)
+
+ else:
+ raise UnknownGeniType(type)
+
+ table.insert(record)
+
+ # update membership for researchers, pis, owners, operators
+ self.api.update_membership(None, record)
+
+ return record.get_gid_object().save_to_string(save_parents=True)
--- /dev/null
+from geni.util.faults import *
+from geni.util.excep import *
+from geni.util.method import Method
+from geni.util.parameter import Parameter, Mixed
+from geni.util.auth import Auth
+from geni.util.record import GeniRecord
+from geni.util.debug import log
+
+class remove(Method):
+ """
+ Remove an object from the registry. If the object represents a PLC object,
+ then the PLC records will also be removed.
+
+ @param cred credential string
+ @param type record type
+ @param hrn human readable name of record to remove
+
+ @return 1 if successful, faults otherwise
+ """
+
+ interfaces = ['registry']
+
+ accepts = [
+ Parameter(str, "Credential string"),
+ Parameter(str, "Record type")
+ Parameter(str, "Human readable name (hrn) of record to be removed")
+ ]
+
+ returns = Parameter(int, "1 if successful")
+
+ def call(self, cred, type, hrn):
+ self.api.auth.decode_authentication(cred, "remove")
+ self.api.auth.verify_object_permission(hrn)
+ auth_name = self.api.auth.get_authority(hrn)
+ table = self.api.auth.get_auth_table(auth_name)
+ record_list = table.resolve(type, hrn)
+ if not record_list:
+ raise RecordNotFound(hrn)
+ record = record_list[0]
+
+ # TODO: sa, ma
+ if type == "user":
+ self.api.plshell.DeletePerson(self.api.plauth, record.get_pointer())
+ elif type == "slice":
+ self.api.plshell.DeleteSlice(self.api.plauth, record.get_pointer())
+ elif type == "node":
+ self.api.plshell.DeleteNode(self.api.plauth, record.get_pointer())
+ elif (type == "sa") or (type == "ma"):
+ if (type == "sa"):
+ other_rec = table.resolve("ma", record.get_name())
+ elif (type == "ma"):
+ other_rec = table.resolve("sa", record.get_name())
+
+ if other_rec:
+ # sa and ma both map to a site, so if we are deleting one
+ # but the other still exists, then do not delete the site
+ print >> log, "not removing site", record.get_name(), "because either sa or ma still exists"
+ pass
+ else:
+ print >> log, "removing site", record.get_name()
+ self.api.plshell.DeleteSite(self.api.plauth, record.get_pointer())
+ else:
+ raise UnknownGeniType(type)
+
+ table.remove(record)
+
+ return 1
interfaces = ['registry']
accepts = [
- Parameter(str, "credential"),
+ Parameter(str, "Credential string"),
Parameter(str, "Human readable name (hrn)")
]
--- /dev/null
+from geni.util.faults import *
+from geni.util.excep import *
+from geni.util.method import Method
+from geni.util.parameter import Parameter, Mixed
+from geni.util.auth import Auth
+from geni.util.record import GeniRecord
+from geni.util.debug import log
+
+class update(Method):
+ """
+ Update an object in the registry. Currently, this only updates the
+ PLC information associated with the record. The Geni fields (name, type,
+ GID) are fixed.
+
+ The record is expected to have the pl_info field filled in with the data
+ that should be updated.
+
+ TODO: The geni_info member of the record should be parsed and the pl_info
+ adjusted as necessary (add/remove users from a slice, etc)
+
+ @param cred credential string specifying rights of the caller
+ @param record a record dictionary to be updated
+
+ @return 1 if successful, faults otherwise
+ """
+
+ interfaces = ['registry']
+
+ accepts = [
+ Parameter(str, "Credential string"),
+ Parameter(dict, "Record dictionary to be updated")
+ ]
+
+ returns = Parameter(int, "1 if successful")
+
+ def call(self, cred, record_dict):
+ self.api.auth.decode_authentication(cred, "update")
+ record = GeniRecord(dict = record_dict)
+ type = record.get_type()
+ self.api.auth.verify_object_permission(record.get_name())
+ auth_name = self.api.auth.get_authority(record.get_name())
+ if not auth_name:
+ auth_name = record.get_name()
+ table = self.api.auth.get_auth_table(auth_name)
+
+ # make sure the record exists
+ existing_record_list = table.resolve(type, record.get_name())
+ if not existing_record_list:
+ raise RecordNotFound(record.get_name())
+ existing_record = existing_record_list[0]
+
+ # 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(existing_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 = existing_record.get_pointer()
+
+ # update the PLC information that was specified with the record
+
+ if (type == "sa") or (type == "ma"):
+ self.api.plshell.UpdateSite(self.api.plauth, pointer, record.get_pl_info())
+
+ elif type == "slice":
+ self.api.plshell.UpdateSlice(self.api.plauth, pointer, record.get_pl_info())
+
+ 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 = record.get_pl_info()
+ 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)
+
+ elif type == "node":
+ self.api.plshell.UpdateNode(self.api.plauth, pointer, record.get_pl_info())
+
+ else:
+ raise UnknownGeniType(type)
+
+ # update membership for researchers, pis, owners, operators^M
+ self.api.update_membership(existing_record, record)
+
+ return 1