call logging
[sfa.git] / sfa / methods / register.py
1 ### $Id$
2 ### $URL$
3
4 from sfa.trust.certificate import Keypair, convert_public_key
5 from sfa.trust.gid import *
6
7 from sfa.util.faults import *
8 from sfa.util.misc import *
9 from sfa.util.method import Method
10 from sfa.util.parameter import Parameter, Mixed
11 from sfa.util.record import GeniRecord
12 from sfa.util.genitable import GeniTable
13 from sfa.util.debug import log
14 from sfa.trust.auth import Auth
15 from sfa.trust.gid import create_uuid
16 from sfa.trust.credential import Credential
17
18 class register(Method):
19     """
20     Register an object with the registry. In addition to being stored in the
21     Geni database, the appropriate records will also be created in the
22     PLC databases
23     
24     @param cred credential string
25     @param record_dict dictionary containing record fields
26     
27     @return gid string representation
28     """
29
30     interfaces = ['registry']
31     
32     accepts = [
33         Parameter(str, "Credential string"),
34         Parameter(dict, "Record dictionary containing record fields")
35         ]
36
37     returns = Parameter(int, "String representation of gid object")
38     
39     def call(self, cred, record_dict, caller_cred=None):
40         self.api.auth.check(cred, "register")
41         if caller_cred==None:
42            caller_cred=cred
43         
44         #log the call
45         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))
46         record = GeniRecord(dict = record_dict)
47         table = GeniTable()
48         type = record['type']
49         hrn = record['hrn']
50         auth_name = get_authority(hrn)
51         self.api.auth.verify_object_permission(hrn)
52         auth_info = self.api.auth.get_auth_info(auth_name)
53         pub_key = None  
54         # make sure record has a gid
55         if 'gid' not in record:
56             uuid = create_uuid()
57             pkey = Keypair(create=True)
58             if 'key' in record and record['key']:
59                 if isinstance(record['key'], list):
60                     pub_key = record['key'][0]
61                 else:
62                     pub_key = record['key']
63                 pkey = convert_public_key(pub_key)
64             
65             gid_object = self.api.auth.hierarchy.create_gid(hrn, uuid, pkey)
66             gid = gid_object.save_to_string(save_parents=True)
67             record['gid'] = gid
68             record.set_gid(gid)
69
70         # check if record already exists
71         existing_records = table.find({'type': type, 'hrn': hrn})
72         if existing_records:
73             raise ExistingRecord(hrn)
74         
75         if type in ["authority"]:
76             # update the tree
77             if not self.api.auth.hierarchy.auth_exists(hrn):
78                 self.api.auth.hierarchy.create_auth(hrn)
79
80             # authorities are special since they are managed by the registry
81             # rather than by the caller. We create our own GID for the
82             # authority rather than relying on the caller to supply one.
83
84             # get the GID from the newly created authority
85             gid = auth_info.get_gid_object()
86             record.set_gid(gid.save_to_string(save_parents=True))
87
88             pl_record = self.api.geni_fields_to_pl_fields(type, hrn, record)
89             sites = self.api.plshell.GetSites(self.api.plauth, [pl_record['login_base']])
90             if not sites:    
91                 pointer = self.api.plshell.AddSite(self.api.plauth, pl_record)
92             else:
93                 pointer = sites[0]['site_id']
94
95             record.set_pointer(pointer)
96
97         elif (type == "slice"):
98             pl_record = self.api.geni_fields_to_pl_fields(type, hrn, record)
99             slices = self.api.plshell.GetSlices(self.api.plauth, [pl_record['name']])
100             if not slices: 
101                 pointer = self.api.plshell.AddSlice(self.api.plauth, pl_record)
102             else:
103                 pointer = slices[0]['slice_id']
104             record.set_pointer(pointer)
105
106         elif (type == "user"):
107             persons = self.api.plshell.GetPersons(self.api.plauth, [record['email']])
108             if not persons:
109                 pointer = self.api.plshell.AddPerson(self.api.plauth, dict(record))
110             else:
111                 pointer = persons[0]['person_id']
112  
113             if 'enabled' in record and record['enabled']:
114                 self.api.plshell.UpdatePerson(self.api.plauth, pointer, {'enabled': record['enabled']})
115             login_base = get_leaf(auth_name)
116             self.api.plshell.AddPersonToSite(self.api.plauth, pointer, login_base)
117             # What roles should this user have?
118             self.api.plshell.AddRoleToPerson(self.api.plauth, 'user', pointer) 
119             record.set_pointer(pointer)
120             
121             # Add the user's key
122             if pub_key:
123                 self.api.plshell.AddPersonKey(self.api.plauth, pointer, {'key_type' : 'ssh', 'key' : pub_key})
124
125         elif (type == "node"):
126             pl_record = self.api.geni_fields_to_pl_fields(type, hrn, record)
127             login_base = hrn_to_pl_login_base(auth_name)
128             nodes = self.api.plshell.GetNodes(self.api.plauth, [pl_record['hostname']])
129             if not nodes:
130                 pointer = self.api.plshell.AddNode(self.api.plauth, login_base, pl_record)
131             else:
132                 pointer = nodes[0]['node_id']
133             record.set_pointer(pointer)
134
135         else:
136             raise UnknownGeniType(type)
137
138         # SFA upcalls may exist in PLCAPI and they could have already added the
139         # record for us. Lets check if the record already exists  
140         existing_records = table.find({'type': type, 'hrn': hrn})
141         if not existing_records:
142             table.insert(record)
143
144         # update membership for researchers, pis, owners, operators
145         self.api.update_membership(None, record)
146
147         return record.get_gid_object().save_to_string(save_parents=True)