call logging
[sfa.git] / sfa / methods / update.py
1 ### $Id$
2 ### $URL$
3
4 from sfa.util.faults import *
5 from sfa.util.method import Method
6 from sfa.util.parameter import Parameter, Mixed
7 from sfa.trust.auth import Auth
8 from sfa.util.record import GeniRecord
9 from sfa.util.genitable import GeniTable
10 from sfa.trust.certificate import Keypair, convert_public_key
11 from sfa.trust.gid import *
12 from sfa.util.debug import log
13 from sfa.trust.credential import Credential
14
15 class update(Method):
16     """
17     Update an object in the registry. Currently, this only updates the
18     PLC information associated with the record. The Geni fields (name, type,
19     GID) are fixed.
20     
21     @param cred credential string specifying rights of the caller
22     @param record a record dictionary to be updated
23
24     @return 1 if successful, faults otherwise 
25     """
26
27     interfaces = ['registry']
28     
29     accepts = [
30         Parameter(str, "Credential string"),
31         Parameter(dict, "Record dictionary to be updated")
32         ]
33
34     returns = Parameter(int, "1 if successful")
35     
36     def call(self, cred, record_dict, caller_cred=None):
37         self.api.auth.check(cred, "update")
38         if caller_cred==None:
39            caller_cred=cred
40
41         #log the call
42         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))
43         new_record = GeniRecord(dict = record_dict)
44         type = new_record['type']
45         hrn = new_record['hrn']
46         self.api.auth.verify_object_permission(hrn)
47         table = GeniTable()
48         # make sure the record exists
49         records = table.findObjects({'type': type, 'hrn': hrn})
50         if not records:
51             raise RecordNotFound(hrn)
52         record = records[0]
53          
54         # Update_membership needs the membership lists in the existing record
55         # filled in, so it can see if members were added or removed
56         self.api.fill_record_info(record)
57
58          # Use the pointer from the existing record, not the one that the user
59         # gave us. This prevents the user from inserting a forged pointer
60         pointer = record['pointer']
61
62         # update the PLC information that was specified with the record
63
64         if (type == "authority"):
65             self.api.plshell.UpdateSite(self.api.plauth, pointer, new_record)
66
67         elif type == "slice":
68             pl_record=self.api.geni_fields_to_pl_fields(type, hrn, new_record)
69             if 'name' in pl_record:
70                 pl_record.pop('name')
71             self.api.plshell.UpdateSlice(self.api.plauth, pointer, pl_record)
72
73         elif type == "user":
74             # SMBAKER: UpdatePerson only allows a limited set of fields to be
75             #    updated. Ideally we should have a more generic way of doing
76             #    this. I copied the field names from UpdatePerson.py...
77             update_fields = {}
78             all_fields = new_record
79             for key in all_fields.keys():
80                 if key in ['first_name', 'last_name', 'title', 'email',
81                            'password', 'phone', 'url', 'bio', 'accepted_aup',
82                            'enabled']:
83                     update_fields[key] = all_fields[key]
84             self.api.plshell.UpdatePerson(self.api.plauth, pointer, update_fields)
85
86             if 'key' in new_record and new_record['key']:
87                 # must check this key against the previous one if it exists
88                 persons = self.api.plshell.GetPersons(self.api.plauth, [pointer], ['key_ids'])
89                 person = persons[0]
90                 keys = person['key_ids']
91                 keys = self.api.plshell.GetKeys(self.api.plauth, person['key_ids'])
92                 key_exists = False
93                 if isinstance(new_record['key'], list):
94                     new_key = new_record['key'][0]
95                 else:
96                     new_key = new_record['key']
97   
98                 # Delete all stale keys
99                 for key in keys:
100                     if new_record['key'] != key['key']:
101                         self.api.plshell.DeleteKey(self.api.plauth, key['key_id'])
102                     else:
103                         key_exists = True
104                 if not key_exists:
105                     self.api.plshell.AddPersonKey(self.api.plauth, pointer, {'key_type': 'ssh', 'key': new_key})
106
107                 # update the openssl key and gid
108                 pkey = convert_public_key(new_key)
109                 uuid = create_uuid()
110                 gid_object = self.api.auth.hierarchy.create_gid(hrn, uuid, pkey)
111                 gid = gid_object.save_to_string(save_parents=True)
112                 record['gid'] = gid
113                 record = GeniRecord(dict=record)
114                 table.update(record)
115                  
116         elif type == "node":
117             self.api.plshell.UpdateNode(self.api.plauth, pointer, new_record)
118
119         else:
120             raise UnknownGeniType(type)
121
122         # update membership for researchers, pis, owners, operators
123         self.api.update_membership(record, record)
124
125         return 1