only add the person to the site if this is a new record
[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            
116             # add this persons to the site only if he is being added for the first
117             # time by sfa and doesont already exist in plc     
118             if not persons or not persons[0]['site_ids']:
119                 login_base = get_leaf(auth_name)
120                 self.api.plshell.AddPersonToSite(self.api.plauth, pointer, login_base)
121
122             # What roles should this user have?
123             self.api.plshell.AddRoleToPerson(self.api.plauth, 'user', pointer) 
124             record.set_pointer(pointer)
125             
126             # Add the user's key
127             if pub_key:
128                 self.api.plshell.AddPersonKey(self.api.plauth, pointer, {'key_type' : 'ssh', 'key' : pub_key})
129
130         elif (type == "node"):
131             pl_record = self.api.geni_fields_to_pl_fields(type, hrn, record)
132             login_base = hrn_to_pl_login_base(auth_name)
133             nodes = self.api.plshell.GetNodes(self.api.plauth, [pl_record['hostname']])
134             if not nodes:
135                 pointer = self.api.plshell.AddNode(self.api.plauth, login_base, pl_record)
136             else:
137                 pointer = nodes[0]['node_id']
138             record.set_pointer(pointer)
139
140         else:
141             raise UnknownGeniType(type)
142
143         # SFA upcalls may exist in PLCAPI and they could have already added the
144         # record for us. Lets check if the record already exists  
145         existing_records = table.find({'type': type, 'hrn': hrn})
146         if not existing_records:
147             table.insert(record)
148
149         # update membership for researchers, pis, owners, operators
150         self.api.update_membership(None, record)
151
152         return record.get_gid_object().save_to_string(save_parents=True)