Bug that andy found...
[sfa.git] / sfa / rspecs / aggregates / rspec_manager_max.py
1 from sfa.util.rspec import Rspec
2 import sys
3 import pdb
4
5 SFA_MAX_CONF_FILE = '/etc/sfa/max_allocations'
6
7 # Topology 
8
9 topology = {'pl23':('planetlab2.dragon.maxgigapop.net','planetlab3.dragon.maxgigapop.net'),
10             'pl24':('planetlab2.dragon.maxgigapop.net','planetlab4.dragon.maxgigapop.net'),
11             'pl25':('planetlab2.dragon.maxgigapop.net','planetlab5.dragon.maxgigapop.net'),
12             'pl34':('planetlab3.dragon.maxgigapop.net','planetlab4.dragon.maxgigapop.net'),
13             'pl35':('planetlab3.dragon.maxgigapop.net','planetlab5.dragon.maxgigapop.net'),
14             'pl45':('planetlab4.dragon.maxgigapop.net','planetlab5.dragon.maxgigapop.net')
15             }
16
17 def link_endpoints(links):
18     nodes=[]
19     for l in links:
20         nodes.extend(topology[l])
21     return nodes
22
23 def lock_state_file():
24     # Noop for demo
25     return True
26
27 def unlock_state_file():
28     return True
29     # Noop for demo
30
31 def read_alloc_dict():
32     alloc_dict={}
33     rows = open(SFA_MAX_CONF_FILE).read().split('\n')
34     for r in rows:
35         columns = r.split(' ')
36         if (len(columns)>2):
37             hrn = columns[0]
38             allocs = columns[1].split(',')
39             alloc_dict[hrn]=allocs
40     return alloc_dict
41
42 def commit_alloc_dict(d):
43     f = open(SFA_MAX_CONF_FILE, 'w')
44     for hrn in d.keys():
45         columns = d[hrn]
46         row = hrn+' '+','.join(columns)+'\n'
47         f.write(row)
48     f.close()
49
50 def collapse_alloc_dict(d):
51     ret = []
52     for k in d.keys():
53         ret.extend(d[k])
54     return ret
55
56 #def bootstrap_slice(api, hrn, added_nodes, deleted_nodes):    
57 #        # This code is taken from slices.py
58 #        # To clean up after 21 July
59 #        # Get the slice record from geni
60 #        slice = {}
61 #        registries = Registries(api)
62 #        registry = registries[self.api.hrn]
63 #        credential = self.api.getCredential()
64 #        records = registry.resolve(credential, hrn)
65 #        for record in records:
66 #            if record.get_type() in ['slice']:
67 #                slice = record.as_dict()
68 #        if not slice:
69 #            raise RecordNotFound(hrn)   
70 #
71 #        # Make sure slice exists at plc, if it doesnt add it
72 #        slicename = hrn_to_pl_slicename(hrn)
73 #        slices = api.plshell.GetSlices(api.plauth, [slicename], ['node_ids'])
74 #        if not slices:
75 #            parts = slicename.split("_")
76 #            login_base = parts[0]
77 #            # if site doesnt exist add it
78 #            sites = api.plshell.GetSites(api.plauth, [login_base])
79 #            if not sites:
80 #                authority = get_authority(hrn)
81 #                site_records = registry.resolve(credential, authority)
82 #                site_record = {}
83 #                if not site_records:
84 #                    raise RecordNotFound(authority)
85 #                site_record = site_records[0]
86 #                site = site_record.as_dict()
87 #                
88 #                 # add the site
89 #                site.pop('site_id')
90 #                site_id = api.plshell.AddSite(api.plauth, site)
91 #            else:
92 #                site = sites[0]
93 #            
94 #            slice_fields = {}
95 #            slice_keys = ['name', 'url', 'description']
96 #            for key in slice_keys:
97 #                if key in slice and slice[key]:
98 #                    slice_fields[key] = slice[key]  
99 #            api.plshell.AddSlice(api.plauth, slice_fields)
100 #            slice = slice_fields
101 #            slice['node_ids'] = 0
102 #        else:
103 #            slice = slices[0]    
104 #        # get the list of valid slice users from the registry and make 
105 #        # they are added to the slice 
106 #        researchers = record.get('researcher', [])
107 #        for researcher in researchers:
108 #            person_record = {}
109 #            person_records = registry.resolve(credential, researcher)
110 #            for record in person_records:
111 #                if record.get_type() in ['user']:
112 #                    person_record = record
113 #            if not person_record:
114 #                pass
115 #            person_dict = person_record.as_dict()
116 #            persons = api.plshell.GetPersons(api.plauth, [person_dict['email']], ['person_id', 'key_ids'])
117 #
118 #            # Create the person record 
119 #            if not persons:
120 #                person_id=api.plshell.AddPerson(api.plauth, person_dict)
121 #
122 #        # The line below enables the user account on the remote aggregate soon after it is created.
123 #        # without this the user key is not transfered to the slice (as GetSlivers returns key of only enabled users),
124 #        # which prevents the user from login to the slice. We may do additional checks before enabling the user.
125 #
126 #        api.plshell.UpdatePerson(api.plauth, person_id, {'enabled' : True})
127 #                #key_ids = []
128 #            #else:
129 #                #key_ids = persons[0]['key_ids']
130 #
131 #            api.plshell.AddPersonToSlice(api.plauth, person_dict['email'], slicename)        
132 #
133 #            # Get this users local keys
134 #            keylist = api.plshell.GetKeys(api.plauth, key_ids, ['key'])
135 #            keys = [key['key'] for key in keylist]
136 #
137 #            # add keys that arent already there 
138 #            for personkey in person_dict['keys']:
139 #                if personkey not in keys:
140 #                    key = {'key_type': 'ssh', 'key': personkey}
141 #                    api.plshell.AddPersonKey(api.plauth, person_dict['email'], key)
142 #
143 #        # find out where this slice is currently running
144 #        nodelist = api.plshell.GetNodes(api.plauth, slice['node_ids'], ['hostname'])
145 #        hostnames = [node['hostname'] for node in nodelist]
146 #
147 #        api.plshell.AddSliceToNodes(self.api.plauth, slicename, added_nodes) 
148 #        api.plshell.DeleteSliceFromNodes(self.api.plauth, slicename, deleted_nodes)
149 #
150 #        return 1
151
152 def alloc_links(api, links_to_add, links_to_drop, foo):
153     return True
154
155 def alloc_nodes(api,hrn, links_to_add, links_to_delete):
156     
157     nodes_to_add = link_endpoints(links_to_add)
158     nodes_to_delete = link_endpoints(links_to_delete)
159
160     pdb.set_trace()
161     bootstrap_slice(api, hrn, nodes_to_add, nodes_to_delete)
162
163
164 def get_rspec(hrn):
165     # Eg. config line:
166     # plc.princeton.sapan vlan23,vlan45
167
168     allocations = read_alloc_dict()
169     if (hrn):
170         current_allocations = allocations[hrn]
171     else:
172         current_allocations = collapse_alloc_dict(allocations)
173
174     return (allocations_to_rspec_dict(current_allocations))
175
176
177 def create_slice(api, hrn, rspec):
178     # Check if everything in rspec is either allocated by hrn
179     # or not allocated at all.
180
181     lock_state_file()
182
183     allocations = read_alloc_dict()
184     requested_allocations = rspec_to_allocations (rspec)
185     current_allocations = collapse_alloc_dict(allocations)
186     try:
187         current_hrn_allocations=allocations[hrn]
188     except KeyError:
189         current_hrn_allocations=[]
190
191     # Check request against current allocations
192     for a in requested_allocations:
193         if (a not in current_hrn_allocations and a in current_allocations):
194             return False
195     # Request OK
196
197     # Allocations to delete
198     allocations_to_delete = []
199     for a in current_hrn_allocations:
200         if (a not in requested_allocations):
201             allocations_to_delete.extend([a])
202
203     # Ok, let's do our thing
204     alloc_nodes(api, hrn, requested_allocations, allocations_to_delete)
205     alloc_links(api, hrn, requested_allocations, allocations_to_delete)
206     allocations[hrn] = requested_allocations
207     commit_alloc_dict(allocations)
208
209     unlock_state_file()
210
211     return True
212
213 def rspec_to_allocations(rspec):
214     links = []
215     try:
216         linkspecs = rspec['rspec']['request'][0]['netspec'][0]['linkspec']
217         for l in linkspecs:
218             links.extend([l['name'].replace('tns:','')])
219         
220     except KeyError:
221         # Bad Rspec
222         pass
223     return links
224
225 def main():
226     r = Rspec()
227     rspec_xml = open(sys.argv[1]).read()
228     r.parseString(rspec_xml)
229     rspec = r.toDict()
230     create_slice(None,'plc',rspec)
231     
232 if __name__ == "__main__":
233     main()