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, "Human readable name of the original caller"),
34 Paramater(None, "Origin hrn not specified"))
37 returns = Parameter(int, "1 if successful")
39 def call(self, cred, record_dict, origin_hrn=None):
40 user_cred = Credential(string=cred)
44 origin_hrn = user_cred.get_gid_caller().get_hrn()
45 self.api.logger.info("interface: %s\tcaller-hrn: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, origin_hrn, None, self.name))
48 self.api.auth.check(cred, "update")
50 new_record = GeniRecord(dict = record_dict)
51 type = new_record['type']
52 hrn = new_record['hrn']
53 self.api.auth.verify_object_permission(hrn)
55 # make sure the record exists
56 records = table.findObjects({'type': type, 'hrn': hrn})
58 raise RecordNotFound(hrn)
60 record['last_updated'] = time.gmtime()
62 # Update_membership needs the membership lists in the existing record
63 # filled in, so it can see if members were added or removed
64 self.api.fill_record_info(record)
66 # Use the pointer from the existing record, not the one that the user
67 # gave us. This prevents the user from inserting a forged pointer
68 pointer = record['pointer']
70 # update the PLC information that was specified with the record
72 if (type == "authority"):
73 self.api.plshell.UpdateSite(self.api.plauth, pointer, new_record)
76 pl_record=self.api.geni_fields_to_pl_fields(type, hrn, new_record)
77 if 'name' in pl_record:
79 self.api.plshell.UpdateSlice(self.api.plauth, pointer, pl_record)
82 # SMBAKER: UpdatePerson only allows a limited set of fields to be
83 # updated. Ideally we should have a more generic way of doing
84 # this. I copied the field names from UpdatePerson.py...
86 all_fields = new_record
87 for key in all_fields.keys():
88 if key in ['first_name', 'last_name', 'title', 'email',
89 'password', 'phone', 'url', 'bio', 'accepted_aup',
91 update_fields[key] = all_fields[key]
92 self.api.plshell.UpdatePerson(self.api.plauth, pointer, update_fields)
94 if 'key' in new_record and new_record['key']:
95 # must check this key against the previous one if it exists
96 persons = self.api.plshell.GetPersons(self.api.plauth, [pointer], ['key_ids'])
98 keys = person['key_ids']
99 keys = self.api.plshell.GetKeys(self.api.plauth, person['key_ids'])
101 if isinstance(new_record['key'], list):
102 new_key = new_record['key'][0]
104 new_key = new_record['key']
106 # Delete all stale keys
108 if new_record['key'] != key['key']:
109 self.api.plshell.DeleteKey(self.api.plauth, key['key_id'])
113 self.api.plshell.AddPersonKey(self.api.plauth, pointer, {'key_type': 'ssh', 'key': new_key})
115 # update the openssl key and gid
116 pkey = convert_public_key(new_key)
118 gid_object = self.api.auth.hierarchy.create_gid(hrn, uuid, pkey)
119 gid = gid_object.save_to_string(save_parents=True)
121 record = GeniRecord(dict=record)
125 self.api.plshell.UpdateNode(self.api.plauth, pointer, new_record)
128 raise UnknownGeniType(type)
130 # update membership for researchers, pis, owners, operators
131 self.api.update_membership(record, new_record)