remove request_hash argument
[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, origin_hrn=None):
40         user_cred = Credential(string=cred)
41
42         #log the call
43         if not origin_hrn:
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, hrn, self.name))
46         
47         # validate the cred
48         self.api.auth.check(cred, "register")
49         
50         record = GeniRecord(dict = record_dict)
51         record['authority'] = get_authority(record['hrn'])
52         type = record['type']
53         hrn = record['hrn']
54         self.api.auth.verify_object_permission(hrn)
55         auth_info = self.api.auth.get_auth_info(record['authority'])
56         pub_key = None  
57         # make sure record has a gid
58         if 'gid' not in record:
59             uuid = create_uuid()
60             pkey = Keypair(create=True)
61             if 'key' in record and record['key']:
62                 if isinstance(record['key'], list):
63                     pub_key = record['key'][0]
64                 else:
65                     pub_key = record['key']
66                 pkey = convert_public_key(pub_key)
67             
68             gid_object = self.api.auth.hierarchy.create_gid(hrn, uuid, pkey)
69             gid = gid_object.save_to_string(save_parents=True)
70             record['gid'] = gid
71             record.set_gid(gid)
72
73         # check if record already exists
74         table = GeniTable()
75         existing_records = table.find({'type': type, 'hrn': hrn})
76         if existing_records:
77             raise ExistingRecord(hrn)
78  
79         if type in ["authority"]:
80             # update the tree
81             if not self.api.auth.hierarchy.auth_exists(hrn):
82                 self.api.auth.hierarchy.create_auth(hrn)
83
84             # authorities are special since they are managed by the registry
85             # rather than by the caller. We create our own GID for the
86             # authority rather than relying on the caller to supply one.
87
88             # get the GID from the newly created authority
89             gid = auth_info.get_gid_object()
90             record.set_gid(gid.save_to_string(save_parents=True))
91
92             pl_record = self.api.geni_fields_to_pl_fields(type, hrn, record)
93             sites = self.api.plshell.GetSites(self.api.plauth, [pl_record['login_base']])
94             if not sites:    
95                 pointer = self.api.plshell.AddSite(self.api.plauth, pl_record)
96             else:
97                 pointer = sites[0]['site_id']
98
99             record.set_pointer(pointer)
100             record['pointer'] = pointer
101
102         elif (type == "slice"):
103             acceptable_fields=['url', 'instantiation', 'name', 'description']
104             pl_record = self.api.geni_fields_to_pl_fields(type, hrn, record)
105             for key in pl_record.keys():
106                 if key not in acceptable_fields:
107                    pl_record.pop(key)
108             slices = self.api.plshell.GetSlices(self.api.plauth, [pl_record['name']])
109             if not slices: 
110                 pointer = self.api.plshell.AddSlice(self.api.plauth, pl_record)
111             else:
112                 pointer = slices[0]['slice_id']
113             record.set_pointer(pointer)
114             record['pointer'] = pointer
115
116         elif  (type == "user"):
117             persons = self.api.plshell.GetPersons(self.api.plauth, [record['email']])
118             if not persons:
119                 pointer = self.api.plshell.AddPerson(self.api.plauth, dict(record))
120             else:
121                 raise ExistingRecord(record['email'])
122  
123             if 'enabled' in record and record['enabled']:
124                 self.api.plshell.UpdatePerson(self.api.plauth, pointer, {'enabled': record['enabled']})
125             # add this persons to the site only if he is being added for the first
126             # time by sfa and doesont already exist in plc     
127             if not persons or not persons[0]['site_ids']:
128                 login_base = get_leaf(record['authority'])
129                 self.api.plshell.AddPersonToSite(self.api.plauth, pointer, login_base)
130         
131             # What roles should this user have?
132             self.api.plshell.AddRoleToPerson(self.api.plauth, 'user', pointer) 
133             record.set_pointer(pointer)
134             record['pointer'] = pointer
135             # Add the user's key
136             if pub_key:
137                 self.api.plshell.AddPersonKey(self.api.plauth, pointer, {'key_type' : 'ssh', 'key' : pub_key})
138
139         elif (type == "node"):
140             pl_record = self.api.geni_fields_to_pl_fields(type, hrn, record)
141             login_base = hrn_to_pl_login_base(record['authority'])
142             nodes = self.api.plshell.GetNodes(self.api.plauth, [pl_record['hostname']])
143             if not nodes:
144                 pointer = self.api.plshell.AddNode(self.api.plauth, login_base, pl_record)
145             else:
146                 pointer = nodes[0]['node_id']
147             record['pointer'] = pointer
148             record.set_pointer(pointer)
149
150         else:
151             raise UnknownGeniType(type)
152
153         record_id = table.insert(record)
154         record['record_id'] = record_id
155
156         # update membership for researchers, pis, owners, operators
157         self.api.update_membership(None, record)
158
159         return record.get_gid_object().save_to_string(save_parents=True)