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