5 from sfa.util.faults import *
6 from sfa.util.method import Method
7 from sfa.util.parameter import Parameter, Mixed
8 from sfa.trust.auth import Auth
9 from sfa.util.record import GeniRecord
10 from sfa.util.genitable import GeniTable
11 from sfa.trust.certificate import Keypair, convert_public_key
12 from sfa.trust.gid import *
13 from sfa.util.debug import log
14 from sfa.trust.credential import Credential
18 Update an object in the registry. Currently, this only updates the
19 PLC information associated with the record. The Geni fields (name, type,
22 @param cred credential string specifying rights of the caller
23 @param record a record dictionary to be updated
25 @return 1 if successful, faults otherwise
28 interfaces = ['registry']
31 Parameter(str, "Credential string"),
32 Parameter(dict, "Record dictionary to be updated"),
33 Mixed(Parameter(str, "Request hash"),
34 Parameter(None, "Request hash not specified"))
37 returns = Parameter(int, "1 if successful")
39 def call(self, cred, record_dict, request_hash=None, caller_cred=None):
44 self.api.logger.info("interface: %s\tcaller-hrn: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, Credential(string=caller_cred).get_gid_caller().get_hrn(), None, self.name))
45 # This cred might be an authority cred, not a user, so we cant use it to
46 # authenticate the caller's request_hash. Let just get the caller's gid
47 # from the cred and authenticate using that
48 client_gid = Credential(string=cred).get_gid_caller()
49 client_gid_str = client_gid.save_to_string(save_parents=True)
50 self.api.auth.authenticateGid(client_gid_str, [cred], request_hash)
51 self.api.auth.check(cred, "update")
52 new_record = GeniRecord(dict = record_dict)
53 type = new_record['type']
54 hrn = new_record['hrn']
55 self.api.auth.verify_object_permission(hrn)
57 # make sure the record exists
58 records = table.findObjects({'type': type, 'hrn': hrn})
60 raise RecordNotFound(hrn)
62 record['last_updated'] = time.gmtime()
64 # Update_membership needs the membership lists in the existing record
65 # filled in, so it can see if members were added or removed
66 self.api.fill_record_info(record)
68 # Use the pointer from the existing record, not the one that the user
69 # gave us. This prevents the user from inserting a forged pointer
70 pointer = record['pointer']
72 # update the PLC information that was specified with the record
74 if (type == "authority"):
75 self.api.plshell.UpdateSite(self.api.plauth, pointer, new_record)
78 pl_record=self.api.geni_fields_to_pl_fields(type, hrn, new_record)
79 if 'name' in pl_record:
81 self.api.plshell.UpdateSlice(self.api.plauth, pointer, pl_record)
84 # SMBAKER: UpdatePerson only allows a limited set of fields to be
85 # updated. Ideally we should have a more generic way of doing
86 # this. I copied the field names from UpdatePerson.py...
88 all_fields = new_record
89 for key in all_fields.keys():
90 if key in ['first_name', 'last_name', 'title', 'email',
91 'password', 'phone', 'url', 'bio', 'accepted_aup',
93 update_fields[key] = all_fields[key]
94 self.api.plshell.UpdatePerson(self.api.plauth, pointer, update_fields)
96 if 'key' in new_record and new_record['key']:
97 # must check this key against the previous one if it exists
98 persons = self.api.plshell.GetPersons(self.api.plauth, [pointer], ['key_ids'])
100 keys = person['key_ids']
101 keys = self.api.plshell.GetKeys(self.api.plauth, person['key_ids'])
103 if isinstance(new_record['key'], list):
104 new_key = new_record['key'][0]
106 new_key = new_record['key']
108 # Delete all stale keys
110 if new_record['key'] != key['key']:
111 self.api.plshell.DeleteKey(self.api.plauth, key['key_id'])
115 self.api.plshell.AddPersonKey(self.api.plauth, pointer, {'key_type': 'ssh', 'key': new_key})
117 # update the openssl key and gid
118 pkey = convert_public_key(new_key)
120 gid_object = self.api.auth.hierarchy.create_gid(hrn, uuid, pkey)
121 gid = gid_object.save_to_string(save_parents=True)
123 record = GeniRecord(dict=record)
127 self.api.plshell.UpdateNode(self.api.plauth, pointer, new_record)
130 raise UnknownGeniType(type)
132 # update membership for researchers, pis, owners, operators
133 self.api.update_membership(record, new_record)