3 from sfa.util.rspec import Rspec
6 from sfa.util.misc import *
7 from sfa.util.rspec import *
8 from sfa.util.specdict import *
9 from sfa.util.faults import *
10 from sfa.util.storage import *
11 from sfa.util.policy import Policy
12 from sfa.util.debug import log
13 from sfa.server.aggregate import Aggregates
14 from sfa.server.registry import Registries
16 SFA_MAX_CONF_FILE = '/etc/sfa/max_allocations'
17 SFA_MAX_DEFAULT_RSPEC = '/etc/sfa/max_physical.xml'
21 topology = {'pl23':('planetlab2.dragon.maxgigapop.net','planetlab3.dragon.maxgigapop.net'),
22 'pl24':('planetlab2.dragon.maxgigapop.net','planetlab4.dragon.maxgigapop.net'),
23 'pl25':('planetlab2.dragon.maxgigapop.net','planetlab5.dragon.maxgigapop.net'),
24 'pl34':('planetlab3.dragon.maxgigapop.net','planetlab4.dragon.maxgigapop.net'),
25 'pl35':('planetlab3.dragon.maxgigapop.net','planetlab5.dragon.maxgigapop.net'),
26 'pl45':('planetlab4.dragon.maxgigapop.net','planetlab5.dragon.maxgigapop.net')
29 def link_endpoints(links):
32 nodes.extend(topology[l])
35 def lock_state_file():
39 def unlock_state_file():
43 def read_alloc_dict():
45 rows = open(SFA_MAX_CONF_FILE).read().split('\n')
47 columns = r.split(' ')
50 allocs = columns[1].split(',')
51 alloc_dict[hrn]=allocs
54 def commit_alloc_dict(d):
55 f = open(SFA_MAX_CONF_FILE, 'w')
58 row = hrn+' '+','.join(columns)+'\n'
62 def collapse_alloc_dict(d):
69 def alloc_links(api, links_to_add, links_to_drop, foo):
71 for l in links_to_add:
72 (node1,ip1,node2,ip2) = l
73 api.plshell.AddSliceTag(api.plauth, [slicename], ['node_ids'])
76 def alloc_nodes(api,hrn, requested_links):
78 requested_nodes = link_endpoints(requested_links)
80 create_slice_max_aggregate(api, hrn, requested_nodes)
82 # Taken from slices.py
84 def create_slice_max_aggregate(api, hrn, nodes):
85 # Get the slice record from geni
87 registries = Registries(api)
88 registry = registries[api.hrn]
89 credential = api.getCredential()
90 records = registry.resolve(credential, hrn)
91 for record in records:
92 if record.get_type() in ['slice']:
93 slice = record.as_dict()
95 raise RecordNotFound(hrn)
97 # Make sure slice exists at plc, if it doesnt add it
98 slicename = hrn_to_pl_slicename(hrn)
99 slices = api.plshell.GetSlices(api.plauth, [slicename], ['node_ids'])
101 parts = slicename.split("_")
102 login_base = parts[0]
103 # if site doesnt exist add it
104 sites = api.plshell.GetSites(api.plauth, [login_base])
106 authority = get_authority(hrn)
107 site_records = registry.resolve(credential, authority)
110 raise RecordNotFound(authority)
111 site_record = site_records[0]
112 site = site_record.as_dict()
116 site_id = api.plshell.AddSite(api.plauth, site)
121 slice_keys = ['name', 'url', 'description']
122 for key in slice_keys:
123 if key in slice and slice[key]:
124 slice_fields[key] = slice[key]
125 api.plshell.AddSlice(api.plauth, slice_fields)
127 slice['node_ids'] = 0
131 # get the list of valid slice users from the registry and make
132 # they are added to the slice
133 researchers = record.get('researcher', [])
134 for researcher in researchers:
136 person_records = registry.resolve(credential, researcher)
137 for record in person_records:
138 if record.get_type() in ['user']:
139 person_record = record
140 if not person_record:
142 person_dict = person_record.as_dict()
143 persons = api.plshell.GetPersons(api.plauth, [person_dict['email']],
144 ['person_id', 'key_ids'])
146 # Create the person record
148 person_id=api.plshell.AddPerson(api.plauth, person_dict)
150 # The line below enables the user account on the remote aggregate
151 # soon after it is created.
152 # without this the user key is not transfered to the slice
153 # (as GetSlivers returns key of only enabled users),
154 # which prevents the user from login to the slice.
155 # We may do additional checks before enabling the user.
157 api.plshell.UpdatePerson(api.plauth, person_id, {'enabled' : True})
160 key_ids = persons[0]['key_ids']
162 api.plshell.AddPersonToSlice(api.plauth, person_dict['email'],
165 # Get this users local keys
166 keylist = api.plshell.GetKeys(api.plauth, key_ids, ['key'])
167 keys = [key['key'] for key in keylist]
169 # add keys that arent already there
170 for personkey in person_dict['keys']:
171 if personkey not in keys:
172 key = {'key_type': 'ssh', 'key': personkey}
173 api.plshell.AddPersonKey(api.plauth, person_dict['email'], key)
175 # find out where this slice is currently running
176 nodelist = api.plshell.GetNodes(api.plauth, slice['node_ids'],
178 hostnames = [node['hostname'] for node in nodelist]
180 # remove nodes not in rspec
181 deleted_nodes = list(set(hostnames).difference(nodes))
182 # add nodes from rspec
183 added_nodes = list(set(nodes).difference(hostnames))
185 api.plshell.AddSliceToNodes(api.plauth, slicename, added_nodes)
186 api.plshell.DeleteSliceFromNodes(api.plauth, slicename, deleted_nodes)
191 def get_rspec(api, hrn):
193 # plc.princeton.sapan vlan23,vlan45
195 allocations = read_alloc_dict()
197 ret_rspec = rspec(allocations[hrn])
199 ret_rspec = open(SFA_MAX_DEFAULT_RSPEC).read()
204 def create_slice(api, hrn, rspec_xml):
205 # Check if everything in rspec is either allocated by hrn
206 # or not allocated at all.
209 r.parseString(rspec_xml)
214 allocations = read_alloc_dict()
215 requested_allocations = rspec_to_allocations (rspec)
216 current_allocations = collapse_alloc_dict(allocations)
218 current_hrn_allocations=allocations[hrn]
220 current_hrn_allocations=[]
222 # Check request against current allocations
223 for a in requested_allocations:
224 if (a not in current_hrn_allocations and a in current_allocations):
228 # Allocations to delete
229 allocations_to_delete = []
230 for a in current_hrn_allocations:
231 if (a not in requested_allocations):
232 allocations_to_delete.extend([a])
234 # Ok, let's do our thing
235 alloc_nodes(api, hrn, requested_allocations)
236 alloc_links(api, hrn, requested_allocations, allocations_to_delete)
237 allocations[hrn] = requested_allocations
238 commit_alloc_dict(allocations)
244 def rspec_to_allocations(rspec):
247 linkspecs = rspec['rspec']['request'][0]['netspec'][0]['linkspec']
249 links.extend([l['name'].replace('tns:','')])
258 rspec_xml = open(sys.argv[1]).read()
259 r.parseString(rspec_xml)
261 create_slice(None,'plc',rspec)
263 if __name__ == "__main__":