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