X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sfa%2Frspecs%2Faggregates%2Frspec_manager_vini.py;h=20dc7fb566e57aa4dea4402e6e4286bd9a81f131;hb=3d7237fa0b5f2b4a60cb97c7fb3b6aecfd94558a;hp=a5d1fdbc7d9e978a193dcaa8dc73a2837864beb2;hpb=a6c7abd005411b9df5055be3514a608f4d96aaef;p=sfa.git diff --git a/sfa/rspecs/aggregates/rspec_manager_vini.py b/sfa/rspecs/aggregates/rspec_manager_vini.py index a5d1fdbc..20dc7fb5 100644 --- a/sfa/rspecs/aggregates/rspec_manager_vini.py +++ b/sfa/rspecs/aggregates/rspec_manager_vini.py @@ -1,178 +1,206 @@ from sfa.util.faults import * -from sfa.util.rspec import Rspec +from sfa.util.namespace import * +from sfa.util.rspec import RSpec from sfa.server.registry import Registries +from sfa.plc.nodes import * +from sfa.rspecs.aggregates.vini.utils import * +from sfa.rspecs.aggregates.vini.rspec import * import sys -import pdb -SFA_VINI_DEFAULT_RSPEC = '/etc/sfa/vini.rspec' +SFA_VINI_WHITELIST = '/etc/sfa/vini.whitelist' """ -Copied from create_slice_aggregate() in sfa.plc.slices. +Copied from create_slice_aggregate() in sfa.plc.slices """ -def create_slice_vini_aggregate(api, hrn, nodes): - # Get the slice record from geni - slice = {} - registries = Registries(api) - registry = registries[api.hrn] - credential = api.getCredential() - records = registry.resolve(credential, hrn) - for record in records: - if record.get_type() in ['slice']: - slice = record.as_dict() - if not slice: - raise RecordNotFound(hrn) - - # Make sure slice exists at plc, if it doesnt add it - slicename = hrn_to_pl_slicename(hrn) - slices = api.plshell.GetSlices(api.plauth, [slicename], ['node_ids']) - if not slices: - parts = slicename.split("_") - login_base = parts[0] - # if site doesnt exist add it - sites = api.plshell.GetSites(api.plauth, [login_base]) - if not sites: - authority = get_authority(hrn) - site_records = registry.resolve(credential, authority) - site_record = {} - if not site_records: - raise RecordNotFound(authority) - site_record = site_records[0] - site = site_record.as_dict() +def create_slice_vini_aggregate(api, hrn, nodes): + # Get the slice record from SFA + slice = {} + registries = Registries(api) + registry = registries[api.hrn] + credential = api.getCredential() + records = registry.resolve(credential, hrn) + for record in records: + if record['type'] in ['slice']: + slice = record + if not slice: + raise RecordNotFound(hrn) + + # Make sure slice exists at plc, if it doesnt add it + slicename = hrn_to_pl_slicename(hrn) + slices = api.plshell.GetSlices(api.plauth, [slicename], ['node_ids']) + if not slices: + parts = slicename.split("_") + login_base = parts[0] + # if site doesnt exist add it + sites = api.plshell.GetSites(api.plauth, [login_base]) + if not sites: + authority = get_authority(hrn) + site_records = registry.resolve(credential, authority) + site_record = {} + if not site_records: + raise RecordNotFound(authority) + site = site_records[0] - # add the site - site.pop('site_id') - site_id = api.plshell.AddSite(api.plauth, site) - else: - site = sites[0] + # add the site + site.pop('site_id') + site_id = api.plshell.AddSite(api.plauth, site) + else: + site = sites[0] - slice_fields = {} - slice_keys = ['name', 'url', 'description'] - for key in slice_keys: - if key in slice and slice[key]: - slice_fields[key] = slice[key] - api.plshell.AddSlice(api.plauth, slice_fields) - slice = slice_fields - slice['node_ids'] = 0 + slice_fields = {} + slice_keys = ['name', 'url', 'description'] + for key in slice_keys: + if key in slice and slice[key]: + slice_fields[key] = slice[key] + api.plshell.AddSlice(api.plauth, slice_fields) + slice = slice_fields + slice['node_ids'] = 0 + else: + slice = slices[0] + + # get the list of valid slice users from the registry and make + # they are added to the slice + researchers = record.get('researcher', []) + for researcher in researchers: + person_record = {} + person_records = registry.resolve(credential, researcher) + for record in person_records: + if record['type'] in ['user']: + person_record = record + if not person_record: + pass + person_dict = person_record + persons = api.plshell.GetPersons(api.plauth, [person_dict['email']], + ['person_id', 'key_ids']) + + # Create the person record + if not persons: + person_id=api.plshell.AddPerson(api.plauth, person_dict) + + # The line below enables the user account on the remote aggregate + # soon after it is created. + # without this the user key is not transfered to the slice + # (as GetSlivers returns key of only enabled users), + # which prevents the user from login to the slice. + # We may do additional checks before enabling the user. + + api.plshell.UpdatePerson(api.plauth, person_id, {'enabled' : True}) + key_ids = [] else: - slice = slices[0] - # get the list of valid slice users from the registry and make - # they are added to the slice - researchers = record.get('researcher', []) - for researcher in researchers: - person_record = {} - person_records = registry.resolve(credential, researcher) - for record in person_records: - if record.get_type() in ['user']: - person_record = record - if not person_record: - pass - person_dict = person_record.as_dict() - persons = api.plshell.GetPersons(api.plauth, [person_dict['email']], ['person_id', 'key_ids']) - - # Create the person record - if not persons: - person_id=api.plshell.AddPerson(api.plauth, person_dict) - - # The line below enables the user account on the remote aggregate soon after it is created. - # without this the user key is not transfered to the slice (as GetSlivers returns key of only enabled users), - # which prevents the user from login to the slice. We may do additional checks before enabling the user. - - api.plshell.UpdatePerson(api.plauth, person_id, {'enabled' : True}) - key_ids = [] - else: - key_ids = persons[0]['key_ids'] - - api.plshell.AddPersonToSlice(api.plauth, person_dict['email'], slicename) - - # Get this users local keys - keylist = api.plshell.GetKeys(api.plauth, key_ids, ['key']) - keys = [key['key'] for key in keylist] - - # add keys that arent already there - for personkey in person_dict['keys']: - if personkey not in keys: - key = {'key_type': 'ssh', 'key': personkey} - api.plshell.AddPersonKey(api.plauth, person_dict['email'], key) - - # find out where this slice is currently running - nodelist = api.plshell.GetNodes(api.plauth, slice['node_ids'], ['hostname']) - hostnames = [node['hostname'] for node in nodelist] - - # remove nodes not in rspec - deleted_nodes = list(set(hostnames).difference(nodes)) - # add nodes from rspec - added_nodes = list(set(nodes).difference(hostnames)) - - api.plshell.AddSliceToNodes(api.plauth, slicename, added_nodes) - api.plshell.DeleteSliceFromNodes(api.plauth, slicename, deleted_nodes) - - return 1 - + key_ids = persons[0]['key_ids'] + + api.plshell.AddPersonToSlice(api.plauth, person_dict['email'], + slicename) + + # Get this users local keys + keylist = api.plshell.GetKeys(api.plauth, key_ids, ['key']) + keys = [key['key'] for key in keylist] + + # add keys that arent already there + for personkey in person_dict['keys']: + if personkey not in keys: + key = {'key_type': 'ssh', 'key': personkey} + api.plshell.AddPersonKey(api.plauth, person_dict['email'], key) + + # find out where this slice is currently running + nodelist = api.plshell.GetNodes(api.plauth, slice['node_ids'], + ['hostname']) + hostnames = [node['hostname'] for node in nodelist] + + # remove nodes not in rspec + deleted_nodes = list(set(hostnames).difference(nodes)) + # add nodes from rspec + added_nodes = list(set(nodes).difference(hostnames)) + + """ + print >> sys.stderr, "Slice on nodes:" + for n in hostnames: + print >> sys.stderr, n + print >> sys.stderr, "Wants nodes:" + for n in nodes: + print >> sys.stderr, n + print >> sys.stderr, "Deleting nodes:" + for n in deleted_nodes: + print >> sys.stderr, n + print >> sys.stderr, "Adding nodes:" + for n in added_nodes: + print >> sys.stderr, n + """ + + api.plshell.AddSliceToNodes(api.plauth, slicename, added_nodes) + api.plshell.DeleteSliceFromNodes(api.plauth, slicename, deleted_nodes) + + return 1 def get_rspec(api, hrn): - rspec = None - + topo = Topology(api) if (hrn): - # Convert HRN to slice name - # Get SliceTags for the slice - - # Construct LinkSpecs from the topo_rspec SliceTags - # The first field is the NodeId of the remote node. - # So the endpoints are the SliceTag node and the remote node. + slicename = hrn_to_pl_slicename(hrn) + slice = get_slice(api, slicename) + if slice: + slice.hrn = hrn + topo.nodeTopoFromSliceTags(slice) + else: + # call the default sfa.plc.nodes.get_rspec() method + return Nodes(api).get_rspec(hrn) - # How to: - # - avoid duplicates? - # - verify both ends of the link? - pass - else: - # Return canned response for now... - r = Rspec() - r.parseFile(SFA_VINI_DEFAULT_RSPEC) - rspec = r.toxml() + return topo.toxml(hrn) - return rspec +""" +Hook called via 'sfi.py create' +""" def create_slice(api, hrn, xml): - r = Rspec() - r.parseString(xml) - rspec = r.toGenDict() + ### Check the whitelist + ### It consists of lines of the form: + whitelist = {} + f = open(SFA_VINI_WHITELIST) + for line in f.readlines(): + (slice, maxbw) = line.split() + whitelist[slice] = maxbw + + if hrn in whitelist: + maxbw = whitelist[hrn] + else: + raise PermissionError("%s not in VINI whitelist" % hrn) + + rspec = RSpec(xml) + topo = Topology(api) + + topo.nodeTopoFromRSpec(rspec) # Check request against current allocations - # Request OK - - nodes = rspec_to_nodeset(rspec) - create_slice_vini_aggregate(api, hrn, nodes) + topo.verifyNodeTopo(hrn, topo, maxbw) + + nodes = topo.nodesInTopo() + hostnames = [] + for node in nodes: + hostnames.append(node.hostname) + create_slice_vini_aggregate(api, hrn, hostnames) - # Add VINI-specific topology attributes to slice here + slicename = hrn_to_pl_slicename(hrn) + slice = get_slice(api, slicename) + if slice: + topo.updateSliceTags(slice) return True -def rspec_to_nodeset(rspec): - nodedict = {} - nodes = set() - try: - sitespecs = rspec['Rspec'][0]['Capacity'][0]['NetSpec'][0]['SiteSpec'] - for s in sitespecs: - for node in s['NodeSpec']: - nodedict[node['name'][0]] = node['hostname'][0] - - linkspecs = rspec['Rspec'][0]['Request'][0]['NetSpec'][0]['LinkSpec'] - for l in linkspecs: - for e in l['endpoint']: - nodes.add(nodedict[e]) - - except KeyError: - # Bad Rspec - pass - - return nodes +""" +Returns the request context required by sfatables. At some point, this mechanism should be changed +to refer to "contexts", which is the information that sfatables is requesting. But for now, we just +return the basic information needed in a dict. +""" +def fetch_context(slice_hrn, user_hrn, contexts): + base_context = {'sfa':{'user':{'hrn':user_hrn}, + 'slice':{'hrn':slice_hrn}}} + return base_context def main(): - r = Rspec() + r = RSpec() r.parseFile(sys.argv[1]) - rspec = r.toGenDict() + rspec = r.toDict() create_slice(None,'plc',rspec) - + if __name__ == "__main__": main()