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