Merge branch 'master' of ssh://git.onelab.eu/git/sfa
authorThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Tue, 24 May 2011 15:45:52 +0000 (17:45 +0200)
committerThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Tue, 24 May 2011 15:45:52 +0000 (17:45 +0200)
13 files changed:
sfa/client/sfi.py
sfa/client/sfiAddSliver.py
sfa/managers/aggregate_manager_max.py
sfa/managers/aggregate_manager_pl.py
sfa/managers/slice_manager_pl.py
sfa/plc/aggregate.py
sfa/plc/api.py
sfa/rspecs/pg_rspec.py
sfa/rspecs/rspec.py
sfa/rspecs/rspec_converter.py
sfa/rspecs/rspec_parser.py
sfa/rspecs/sfa_rspec.py
sfa/rspecs/sfa_rspec_converter.py

index 5a7ec7f..579d38e 100755 (executable)
@@ -209,6 +209,10 @@ class Sfi:
             parser.add_option("-f", "--format", dest="format", type="choice",
                              help="display format ([xml]|dns|ip)", default="xml",
                              choices=("xml", "dns", "ip"))
+            #panos: a new option to define the type of information about resources a user is interested in
+           parser.add_option("-i", "--info", dest="info",
+                                help="optional component information", default=None)
+
 
         if command in ("resources", "show", "list"):
            parser.add_option("-o", "--output", dest="file",
@@ -831,7 +835,7 @@ class Sfi:
         if args:
             cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
             hrn = args[0]
-            call_options = {'geni_slice_urn': hrn_to_urn(hrn, 'slice')}
+           call_options = {'geni_slice_urn': hrn_to_urn(hrn, 'slice')}
         else:
             cred = user_cred
             hrn = None
@@ -842,6 +846,9 @@ class Sfi:
             creds.append(delegated_cred)
         if opts.rspec_version:
             call_options['rspec_version'] = opts.rspec_version 
+        #panos add info options
+        if opts.info:
+            call_options['info'] = opts.info 
         result = server.ListResources(creds, call_options,unique_call_id())
         format = opts.format
         if opts.file is None:
index b51c705..7716f97 100755 (executable)
@@ -28,6 +28,9 @@ else:
 rspec = parse_rspec(infile)
 nodes = file(command.opts.nodefile).read().split()
 try:
+    if rspec.version['type'].lower() == 'protogeni':
+        rspec.xml.set('type', 'request')
+        rspec.remove_element('available')    
     slivers = [{'hostname': node} for node in nodes]
     rspec.add_slivers(slivers)
 except:
index 64ddda9..0c374b4 100644 (file)
-from sfa.util.rspec import RSpec
-import sys
-import pdb
-from sfa.util.namespace import *
-from sfa.util.rspec import *
-from sfa.util.specdict import *
-from sfa.util.faults import *
-from sfa.util.storage import *
-from sfa.util.policy import Policy
-from sfa.util.debug import log
-from sfa.server.aggregate import Aggregates
 from sfa.util.xrn import urn_to_hrn, hrn_to_urn, get_authority
 from sfa.util.plxrn import hrn_to_pl_slicename
 from sfa.util.plxrn import hrn_to_pl_slicename
-from sfa.server.registry import Registries
 from sfa.util.rspec import RSpec
 from sfa.util.sfalogging import sfa_logger
-from sfa.util.faults import *
-
-import xml.dom.minidom
-
-SFA_MAX_CONF_FILE = '/etc/sfa/max_allocations'
-SFA_MAX_DEFAULT_RSPEC = '/etc/sfa/max_physical.xml'
-SFA_MAX_CANNED_RSPEC = '/etc/sfa/max_physical_canned.xml'
-
-topology = {}
-
-class SfaOutOfResource(SfaFault):
-    def __init__(self, interface):
-        faultString = "Interface " + interface + " not available"
-        SfaFault.__init__(self, 100, faultString, '')
-
-class SfaNoPairRSpec(SfaFault):
-    def __init__(self, interface, interface2):
-        faultString = "Interface " + interface + " should be paired with " + interface2
-        SfaFault.__init__(self, 100, faultString, '')
-
-# Returns a mapping from interfaces to the nodes they lie on and their peer interfaces
-# i -> node,i_peer
-
-def get_interface_map():
-    r = RSpec()
-    r.parseFile(SFA_MAX_DEFAULT_RSPEC)
-    rspec = r.toDict()
-    capacity = rspec['rspec']['capacity']
-    netspec = capacity[0]['netspec'][0]
-    linkdefs = {}
-    for n in netspec['nodespec']:
-        ifspecs = n['ifspec']
-        nodename = n['node']
-        for i in ifspecs:
-            ifname = i['name']
-            linkid = i['linkid']
-
-            if (linkdefs.has_key(linkid)):
-                linkdefs[linkid].extend([(nodename,ifname)])
-            else:
-                linkdefs[linkid]=[(nodename,ifname)]
-    
-    # topology maps interface x interface -> link,node1,node2
-    topology={}
-
-    for k in linkdefs.keys():
-        (n1,i1) = linkdefs[k][0]
-        (n2,i2) = linkdefs[k][1]
-
-        topology[i1] = (n1, i2)
-        topology[i2] = (n2, i1)
-        
-
-    return topology    
-
-    
-def allocations_to_rspec(allocations):
-    rspec = xml.dom.minidom.parse(SFA_MAX_DEFAULT_RSPEC)
-    req = rspec.firstChild.appendChild(rspec.createElement("request"))
-    for (iname,ip) in allocations:
-        ifspec = req.appendChild(rspec.createElement("ifspec"))
-        ifspec.setAttribute("name","tns:"+iname)
-        ifspec.setAttribute("ip",ip)
-
-    return rspec.toxml()
-        
-    
-def if_endpoints(ifs):
-    nodes=[]
-    for l in ifs:
-        nodes.extend(topology[l][0])
-    return nodes
-
-def lock_state_file():
-    # Noop for demo
-    return True
-
-def unlock_state_file():
-    return True
-    # Noop for demo
-
-def read_alloc_dict():
-    alloc_dict={}
-    rows = open(SFA_MAX_CONF_FILE).read().split('\n')
-    for r in rows:
-        columns = r.split(' ')
-        if (len(columns)==2):
-            hrn = columns[0]
-            allocs = columns[1].split(',')
-            ipallocs = map(lambda alloc:alloc.split('/'), allocs)
-            alloc_dict[hrn]=ipallocs
-    return alloc_dict
-
-def commit_alloc_dict(d):
-    f = open(SFA_MAX_CONF_FILE, 'w')
-    for hrn in d.keys():
-        columns = d[hrn]
-        ipcolumns = map(lambda x:"/".join(x), columns)
-        row = hrn+' '+','.join(ipcolumns)+'\n'
-        f.write(row)
-    f.close()
-
-def collapse_alloc_dict(d):
-    ret = []
-    for k in d.keys():
-        ret.extend(d[k])
 from sfa.util.config import Config
-from sfa.managers.aggregate_manager_pl import GetVersion
+from sfa.managers.aggregate_manager_pl import GetVersion, __get_registry_objects
+from sfa.plc.slices import Slices
 import os
 import time
 
@@ -156,19 +39,6 @@ def call_am_apiclient(client_app, params, timeout):
     sys_cmd = "cd " + client_path + "; java -classpath AggregateWS-client-api.jar:lib/* net.geni.aggregate.client.examples." + client_app + " ./repo " + am_url + " " + ' '.join(params)
     ret = shell_execute(sys_cmd, timeout)
     sfa_logger().debug("shell_execute cmd: %s returns %s" % (sys_cmd, ret))
-    return ret
-
-
-def alloc_links(api, hrn, links_to_add, links_to_drop):
-    slicename=hrn_to_pl_slicename(hrn)
-    for (iface,ip) in links_to_add:
-        node = topology[iface][0][0]
-        try:
-            api.plshell.AddSliceTag(api.plauth, slicename, "ip_addresses", ip, node)
-            api.plshell.AddSliceTag(api.plauth, slicename, "vsys", "getvlan", node)
-        except Exception: 
-            # Probably a duplicate tag. XXX July 21
-            pass
 # save request RSpec xml content to a tmp file
 def save_rspec_to_file(rspec):
     path = RSPEC_TMP_FILE_PREFIX + "_" + time.strftime('%Y%m%dT%H:%M:%S', time.gmtime(time.time())) +".xml"
@@ -198,219 +68,38 @@ def get_xml_by_tag(text, tag):
         xml = text[indx1:indx2+len(tag)+2]
     return xml
 
+def prepare_slice(api, xrn, users):
+    reg_objects = __get_registry_objects(slice_xrn, creds, users)
+    (hrn, type) = urn_to_hrn(slice_xrn)
+    slices = Slices(api)
+    peer = slices.get_peer(hrn)
+    sfa_peer = slices.get_sfa_peer(hrn)
+    registry = api.registries[api.hrn]
+    credential = api.getCredential()
+    (site_id, remote_site_id) = slices.verify_site(registry, credential, hrn, peer, sfa_peer, reg_objects)
+    slices.verify_slice(registry, credential, hrn, site_id, remote_site_id, peer, sfa_peer, reg_objects)
+
 def create_slice(api, xrn, cred, rspec, users):
     indx1 = rspec.find("<RSpec")
     indx2 = rspec.find("</RSpec>")
     if indx1 > -1 and indx2 > indx1:
         rspec = rspec[indx1+len("<RSpec type=\"SFA\">"):indx2-1]
     rspec_path = save_rspec_to_file(rspec)
+    prepare_slice(api, xrn, users)
     (ret, output) = call_am_apiclient("CreateSliceNetworkClient", [rspec_path,], 3)
     # parse output ?
     rspec = "<RSpec type=\"SFA\"> Done! </RSpec>"
-    return True
-
-def alloc_nodes(api,hrn, requested_ifs):
-    requested_nodes = if_endpoints(requested_ifs)
-    create_slice_max_aggregate(api, hrn, requested_nodes)
-
-# Taken from slices.py
-
-def create_slice_max_aggregate(api, hrn, nodes):
-    # Get the slice record 
-    global topology
-    topology = get_interface_map()
-    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()
-                
-            # 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
-    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)
-
 def delete_slice(api, xrn, cred):
     slice_id = get_short_slice_id(cred, xrn)
     (ret, output) = call_am_apiclient("DeleteSliceNetworkClient", [slice_id,], 3)
     # parse output ?
-    return 1
-
-
-def get_rspec(api, creds, options):
-    # get slice's hrn from options
-    xrn = options.get('geni_slice_urn', None)
-    hrn, type = urn_to_hrn(xrn)
-    # Eg. config line:
-    # plc.princeton.sapan vlan23,vlan45
-
-    allocations = read_alloc_dict()
-    if (hrn and allocations.has_key(hrn)):
-            ret_rspec = allocations_to_rspec(allocations[hrn])
 def get_rspec(api, cred, options):
     #geni_slice_urn: urn:publicid:IDN+plc:maxpl+slice+xi_rspec_test1
     urn = options.get('geni_slice_urn')
     slice_id = get_short_slice_id(cred, urn)
     if slice_id == None:
         (ret, output) = call_am_apiclient("GetResourceTopology", ['all', '\"\"'], 5)
-    else:
-        ret_rspec = open(SFA_MAX_CANNED_RSPEC).read()
-
-    return (ret_rspec)
-
-
-def create_slice(api, xrn, creds, rspec_xml, users):
-    global topology
-    hrn = urn_to_hrn(xrn)[0]
-    topology = get_interface_map()
-
-    # Check if everything in rspec is either allocated by hrn
-    # or not allocated at all.
-    r = RSpec()
-    r.parseString(rspec_xml)
-    rspec = r.toDict()
-
-    lock_state_file()
-
-    allocations = read_alloc_dict()
-    requested_allocations = rspec_to_allocations (rspec)
-    current_allocations = collapse_alloc_dict(allocations)
-    try:
-        current_hrn_allocations=allocations[hrn]
-    except KeyError:
-        current_hrn_allocations=[]
-
-    # Check request against current allocations
-    requested_interfaces = map(lambda(elt):elt[0], requested_allocations)
-    current_interfaces = map(lambda(elt):elt[0], current_allocations)
-    current_hrn_interfaces = map(lambda(elt):elt[0], current_hrn_allocations)
-
-    for a in requested_interfaces:
-        if (a not in current_hrn_interfaces and a in current_interfaces):
-            raise SfaOutOfResource(a)
-        if (topology[a][1] not in requested_interfaces):
-            raise SfaNoPairRSpec(a,topology[a][1])
-    # Request OK
-
-    # Allocations to delete
-    allocations_to_delete = []
-    for a in current_hrn_allocations:
-        if (a not in requested_allocations):
-            allocations_to_delete.extend([a])
-
-    # Ok, let's do our thing
-    alloc_nodes(api, hrn, requested_interfaces)
-    alloc_links(api, hrn, requested_allocations, allocations_to_delete)
-    allocations[hrn] = requested_allocations
-    commit_alloc_dict(allocations)
-
-    unlock_state_file()
-
-    return True
-
-def rspec_to_allocations(rspec):
-    ifs = []
-    try:
-        ifspecs = rspec['rspec']['request'][0]['ifspec']
-        for l in ifspecs:
-            ifs.extend([(l['name'].replace('tns:',''),l['ip'])])
-    except KeyError:
-        # Bad RSpec
-        pass
-    return ifs
-    # xxx - fixme
-    (ret, output) = call_am_apiclient("GetResourceTopology", ['all', slice_id,], 5)
+        (ret, output) = call_am_apiclient("GetResourceTopology", ['all', slice_id,], 5)
     # parse output into rspec XML
     if output.find("No resouce found") > 0:
         rspec = "<RSpec type=\"SFA\"> <Fault>No resource found</Fault> </RSpec>"
@@ -448,16 +137,6 @@ return the basic information needed in a dict.
 def fetch_context(slice_hrn, user_hrn, contexts):
     base_context = {'sfa':{'user':{'hrn':user_hrn}}}
     return base_context
-
-def main():
-    t = get_interface_map()
     api = SfaAPI()
-    r = RSpec()
-    rspec_xml = open(sys.argv[1]).read()
-    #get_rspec(None,'foo')
-    create_slice(None, "plc.princeton.sap0", rspec_xml)
-    
     create_slice(api, "plc.maxpl.test000", None, rspec_xml, None)
 
-if __name__ == "__main__":
-    main()
index 557e325..894823c 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+
 
 import datetime
 import time
@@ -26,20 +26,20 @@ from sfa.plc.slices import *
 from sfa.util.version import version_core
 from sfa.rspecs.rspec_version import RSpecVersion
 from sfa.rspecs.sfa_rspec import sfa_rspec_version
-from sfa.rspecs.pg_rspec import pg_rspec_version
+from sfa.rspecs.pg_rspec import pg_rspec_ad_version, pg_rspec_request_version
 from sfa.rspecs.rspec_parser import parse_rspec 
 from sfa.util.sfatime import utcparse
 from sfa.util.callids import Callids
 
 def GetVersion(api):
     xrn=Xrn(api.hrn)
-
-    supported_rspecs = [dict(pg_rspec_version), dict(sfa_rspec_version)]
+    request_rspec_versions = [dict(pg_rspec_request_version), dict(sfa_rspec_version)]
+    ad_rspec_versions = [dict(pg_rspec_ad_version), dict(sfa_rspec_version)]
     version_more = {'interface':'aggregate',
                     'testbed':'myplc',
                     'hrn':xrn.get_hrn(),
-                    'request_rspec_versions': supported_rspecs,
-                    'ad_rspec_versions': supported_rspecs,
+                    'request_rspec_versions': request_rspec_versions,
+                    'ad_rspec_versions': ad_rspec_versions,
                     'default_ad_rspec': dict(sfa_rspec_version)
                     }
     return version_core(version_more)
@@ -283,8 +283,8 @@ def DeleteSliver(api, xrn, creds, call_id):
     return 1
 
 # xxx Thierry : caching at the aggregate level sounds wrong...
-caching=True
-#caching=False
+#caching=True
+caching=False
 def ListSlices(api, creds, call_id):
     if Callids().already_handled(call_id): return []
     # look in cache first
@@ -313,7 +313,11 @@ def ListResources(api, creds, options,call_id):
     # get the rspec's return format from options
     rspec_version = RSpecVersion(options.get('rspec_version'))
     version_string = "rspec_%s" % (rspec_version.get_version_name())
-    
+
+    #panos adding the info option to the caching key (can be improved)
+    if options.get('info'):
+       version_string = version_string + "_"+options.get('info', 'default')
+
     # look in cache first
     if caching and api.cache and not xrn:
         rspec = api.cache.get(version_string)
@@ -321,9 +325,12 @@ def ListResources(api, creds, options,call_id):
             api.logger.info("aggregate.ListResources: returning cached value for hrn %s"%hrn)
             return rspec 
 
-    aggregate = Aggregate(api)
+    #aggregate = Aggregate(api)
+    #panos: passing user-defined options
+    #print "manager options = ",options
+    aggregate = Aggregate(api, options)
 
-    rspec =  aggregate.get_rspec(slice_xrn=xrn, version=rspec_version, type='advertisement')
+    rspec =  aggregate.get_rspec(slice_xrn=xrn, version=rspec_version)
 
     # cache the result
     if caching and api.cache and not xrn:
index 13124d7..23f659a 100644 (file)
@@ -21,7 +21,7 @@ from sfa.rspecs.rspec_converter import RSpecConverter
 from sfa.rspecs.rspec_parser import parse_rspec    
 from sfa.rspecs.rspec_version import RSpecVersion
 from sfa.rspecs.sfa_rspec import sfa_rspec_version
-from sfa.rspecs.pg_rspec import pg_rspec_version    
+from sfa.rspecs.pg_rspec import pg_rspec_ad_version, pg_rspec_request_version   
 from sfa.util.policy import Policy
 from sfa.util.prefixTree import prefixTree
 from sfa.util.sfaticket import *
@@ -46,13 +46,14 @@ def GetVersion(api):
     peers =dict ([ (peername,get_serverproxy_url(v)) for (peername,v) in api.aggregates.iteritems() 
                    if peername != api.hrn])
     xrn=Xrn (api.hrn)
-    supported_rspecs = [dict(pg_rspec_version), dict(sfa_rspec_version)]
+    request_rspec_versions = [dict(pg_rspec_request_version), dict(sfa_rspec_version)]
+    ad_rspec_versions = [dict(pg_rspec_ad_version), dict(sfa_rspec_version)]
     version_more = {'interface':'slicemgr',
                     'hrn' : xrn.get_hrn(),
                     'urn' : xrn.get_urn(),
                     'peers': peers,
-                    'request_rspec_versions': supported_rspecs,
-                    'ad_rspec_versions': supported_rspecs,
+                    'request_rspec_versions': request_rspec_versions,
+                    'ad_rspec_versions': ad_rspec_versions,
                     'default_ad_rspec': dict(sfa_rspec_version)
                     }
     sm_version=version_core(version_more)
@@ -391,7 +392,7 @@ def ListResources(api, creds, options, call_id):
     results = threads.get_results()
     #results.append(open('/root/protogeni.rspec', 'r').read())
     rspec_version = RSpecVersion(my_opts.get('rspec_version'))
-    if rspec_version['type'] == pg_rspec_version['type']:
+    if rspec_version['type'] == pg_rspec_ad_version['type']:
         rspec = PGRSpec()
     else:
         rspec = SfaRSpec()
index 505155f..7f4fcb2 100644 (file)
@@ -14,9 +14,12 @@ class Aggregate:
     links = {}
     node_tags = {}
     prepared=False
+    #panos new user options variable
+    user_options = {}
 
-    def __init__(self, api):
+    def __init__(self, api, user_options={}):
         self.api = api
+        self.user_options = user_options
 
     def prepare_sites(self, force=False):
         if not self.sites or force:  
@@ -56,32 +59,39 @@ class Aggregate:
                 interfaces = [self.interfaces[interface_id] for interface_id in node['interface_ids']]
                 tags = [self.node_tags[tag_id] for tag_id in node['node_tag_ids']]
                 node['network'] = self.api.hrn
-                node['network_urn'] = hrn_to_urn(self.api.hrn, 'authority+sa')
+                node['network_urn'] = hrn_to_urn(self.api.hrn, 'authority+am')
                 node['urn'] = hostname_to_urn(self.api.hrn, site['login_base'], node['hostname'])
-                node['site_urn'] = hrn_to_urn(PlXrn.site_hrn(self.api.hrn, site['login_base']), 'authority') 
+                node['site_urn'] = hrn_to_urn(PlXrn.site_hrn(self.api.hrn, site['login_base']), 'authority+sa') 
                 node['site'] = site
                 node['interfaces'] = interfaces
                 node['tags'] = tags
 
         self.prepared = True  
 
-    def get_rspec(self, slice_xrn=None, version = None, type=None):
+    def get_rspec(self, slice_xrn=None, version = None):
         self.prepare()
         rspec = None
         rspec_version = RSpecVersion(version)
+        if slice_xrn:
+            type = 'manifest'
+        else:
+            type = 'advertisement' 
         if rspec_version['type'].lower() == 'protogeni':
             rspec = PGRSpec(type=type)
         elif rspec_version['type'].lower() == 'sfa':
-            rspec = SfaRSpec()
+            rspec = SfaRSpec(type=type, user_options=self.user_options)
         else:
-            rspec = SfaRSpec()
+            rspec = SfaRSpec(type=type, user_options=self.user_options)
+
 
         rspec.add_nodes(self.nodes.values())
         rspec.add_interfaces(self.interfaces.values()) 
         rspec.add_links(self.links.values())
 
         if slice_xrn:
-            # get slice details
+            # If slicename is specified then resulting rspec is a manifest. 
+            # Add sliver details to rspec and remove 'advertisement' elements
+            rspec.remove_element('available')
             slice_hrn, _ = urn_to_hrn(slice_xrn)
             slice_name = hrn_to_pl_slicename(slice_hrn)
             slices = self.api.plshell.GetSlices(self.api.plauth, slice_name)
@@ -102,6 +112,6 @@ class Aggregate:
                             tag_host = self.nodes[tag['node_id']]['hostname']
                             if tag_host == sliver['hostname']:
                                 sliver.tags.append(tag)
-                rspec.add_slivers(slivers)
+                rspec.add_slivers(slivers, sliver_urn=slice_xrn)
 
         return rspec.toxml()          
index a5d5f2a..59ad1cb 100644 (file)
@@ -386,7 +386,6 @@ class SfaAPI(BaseAPI):
        
         # convert ids to hrns
         for record in records:
-             
             # get all relevant data
             type = record['type']
             pointer = record['pointer']
@@ -420,7 +419,7 @@ class SfaAPI(BaseAPI):
                                if site_id in sites]
                 site_hrns = [".".join([auth_hrn, lbase]) for lbase in login_bases]
                 record['sites'] = site_hrns
-
+            
         return records   
 
     def fill_record_sfa_info(self, records):
@@ -484,20 +483,21 @@ class SfaAPI(BaseAPI):
             type = record['type']
             if (type == "slice"):
                 # all slice users are researchers
+                record['geni_urn'] = hrn_to_urn(record['hrn'], 'slice')
                 record['PI'] = []
                 record['researcher'] = []
-                for person_id in record['person_ids']:
+                for person_id in record.get('person_ids', []):
                     hrns = [person['hrn'] for person in persons[person_id]]
                     record['researcher'].extend(hrns)                
 
                 # pis at the slice's site
-                pl_pis = site_pis[record['site_id']]
-                pi_ids = [pi['person_id'] for pi in pl_pis]
-                for person_id in pi_ids:
-                    hrns = [person['hrn'] for person in persons[person_id]]
-                    record['PI'].extend(hrns)
-                record['geni_urn'] = hrn_to_urn(record['hrn'], 'slice')
-                record['geni_creator'] = record['PI'] 
+                if 'site_id' in record and record['site_id'] in site_pis:
+                    pl_pis = site_pis[record['site_id']]
+                    pi_ids = [pi['person_id'] for pi in pl_pis]
+                    for person_id in pi_ids:
+                        hrns = [person['hrn'] for person in persons[person_id]]
+                        record['PI'].extend(hrns)
+                        record['geni_creator'] = record['PI'] 
                 
             elif (type == "authority"):
                 record['PI'] = []
index a9493a7..c715f53 100755 (executable)
@@ -7,7 +7,17 @@ from sfa.util.plxrn import hostname_to_urn
 from sfa.util.config import Config 
 from sfa.rspecs.rspec_version import RSpecVersion 
 
-_version = {'type':  'ProtoGENI',
+_ad_version = {'type':  'ProtoGENI',
+            'version': '2',
+            'schema': 'http://www.protogeni.net/resources/rspec/2/ad.xsd',
+            'namespace': 'http://www.protogeni.net/resources/rspec/2',
+            'extensions':  [
+                'http://www.protogeni.net/resources/rspec/ext/gre-tunnel/1',
+                'http://www.protogeni.net/resources/rspec/ext/other-ext/3'
+            ]
+}
+
+_request_version = {'type':  'ProtoGENI',
             'version': '2',
             'schema': 'http://www.protogeni.net/resources/rspec/2/request.xsd',
             'namespace': 'http://www.protogeni.net/resources/rspec/2',
@@ -16,15 +26,43 @@ _version = {'type':  'ProtoGENI',
                 'http://www.protogeni.net/resources/rspec/ext/other-ext/3'
             ]
 }
-pg_rspec_version = RSpecVersion(_version)
+pg_rspec_ad_version = RSpecVersion(_ad_version)
+pg_rspec_request_version = RSpecVersion(_request_version)
 
 class PGRSpec(RSpec):
     xml = None
     header = '<?xml version="1.0"?>\n'
-    template = """<rspec xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.protogeni.net/resources/rspec/0.2" xsi:schemaLocation="http://www.protogeni.net/resources/rspec/0.2 http://www.protogeni.net/resources/rspec/0.2/ad.xsd"></rspec>"""
-    version = pg_rspec_version
-    namespaces = {'rspecv2': version['namespace']}
+    template = """<rspec xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.protogeni.net/resources/rspec/2" xsi:schemaLocation="http://www.protogeni.net/resources/rspec/2 http://www.protogeni.net/resources/rspec/2/%(rspec_type)s.xsd"></rspec>"""
 
+    def __init__(self, rspec="", namespaces={}, type=None):
+        if not type:
+            type = 'advertisement'
+        self.type = type
+
+        if type == 'advertisement':
+            self.version = pg_rspec_ad_version
+            rspec_type = 'ad'
+        else:
+            self.version = pg_rspec_request_version
+            rspec_type = type
+        
+        self.template = self.template % {'rspec_type': rspec_type}
+
+        if not namespaces:
+            self.namespaces = {'rspecv2': self.version['namespace']}
+        else:
+            self.namespaces = namespaces 
+
+        if rspec:
+            self.parse_rspec(rspec, self.namespaces)
+        else: 
+            self.create()
+
+    def create(self):
+        RSpec.create(self)
+        if self.type:
+            self.xml.set('type', self.type) 
+        
     def get_network(self):
         network = None 
         nodes = self.xml.xpath('//rspecv2:node[@component_manager_uuid][1]', namespaces=self.namespaces)
@@ -62,17 +100,18 @@ class PGRSpec(RSpec):
                 # node already exists
                 continue
                 
-            node_tag = etree.SubElement(self.xml, 'node')
+            node_tag = etree.SubElement(self.xml, 'node', exclusive='false')
             if 'network_urn' in node:
                 node_tag.set('component_manager_id', node['network_urn'])
             if 'urn' in node:
                 node_tag.set('component_id', node['urn'])
             if 'hostname' in node:
                 node_tag.set('component_name', node['hostname'])
-            node_type_tag = etree.SubElement(node_tag, 'node_type', type_name='pcvm', type_slots='100')
-            available_tag = etree.SubElement(node_tag, 'available').text = 'true'
-            exclusive_tag = etree.SubElement(node_tag, 'exclusive').text = 'false'
-            location_tag = etree.SubElement(node_tag, 'location', location="US")
+            # TODO: should replace plab-pc with pc model 
+            node_type_tag = etree.SubElement(node_tag, 'hardware_type', name='plab-pc')
+            node_type_tag = etree.SubElement(node_tag, 'hardware_type', name='pc')
+            available_tag = etree.SubElement(node_tag, 'available', now='true')
+            location_tag = etree.SubElement(node_tag, 'location', country="us")
             if 'site' in node:
                 if 'longitude' in node['site']:
                     location_tag.set('longitude', str(node['site']['longitude']))
@@ -81,7 +120,7 @@ class PGRSpec(RSpec):
             #if 'interfaces' in node:
             
 
-    def add_slivers(self, slivers, check_for_dupes=False): 
+    def add_slivers(self, slivers, sliver_urn=None, no_dupes=False): 
         if not isinstance(slivers, list):
             slivers = [slivers]
 
@@ -94,12 +133,14 @@ class PGRSpec(RSpec):
             if nodes:
                 node = nodes[0]
                 node.set('client_id', hostname)
-                etree.SubElement(node, 'sliver_type', name='planetlab-vnode')
+                if sliver_urn:
+                    node.set('sliver_id', sliver_urn)
+                etree.SubElement(node, 'sliver_type', name='plab-vnode')
 
-    def add_interfaces(self, interfaces, check_for_dupes=False):
+    def add_interfaces(self, interfaces, no_dupes=False):
         pass
 
-    def add_links(self, links, check_for_dupes=False):
+    def add_links(self, links, no_dupes=False):
         pass
 
 
index 2a331c1..91bac6c 100755 (executable)
@@ -14,10 +14,12 @@ class RSpec:
     xml = None
     type = None
     version = None
-    namespaces = None    
+    namespaces = None
+    user_options = {}
   
-    def __init__(self, rspec="", namespaces={}, type=None):
+    def __init__(self, rspec="", namespaces={}, type=None, user_options={}):
         self.type = type
+        self.user_options = user_options
         if rspec:
             self.parse_rspec(rspec, namespaces)
         else:
@@ -33,10 +35,8 @@ class RSpec:
         generated_ts = now.strftime(date_format)
         expires_ts = (now + timedelta(hours=1)).strftime(date_format) 
         self.parse_rspec(self.template, self.namespaces)
-        self.xml.set('valid_until', expires_ts)
+        self.xml.set('expires', expires_ts)
         self.xml.set('generated', generated_ts)
-        if self.type:
-            self.xml.set('type', self.type)
     
     def parse_rspec(self, rspec, namespaces={}):
         """
@@ -90,6 +90,21 @@ class RSpec:
                     if opt.text == value:
                         elem.remove(opt)
 
+    def remove_element(self, element_name, root_node = None):
+        """
+        Removes all occurences of an element from the tree. Start at 
+        specified root_node if specified, otherwise start at tree's root.   
+        """
+        if not root_node:
+            root_node = self.xml
+
+        elements = root_node.xpath('//rspecv2:%s | //%s' % (element_name, element_name), \
+                                                            namespaces=self.namespaces)
+        for element in elements:
+            parent = element.getparent()
+            parent.remove(element)
+         
+
     def merge(self, in_rspec):
         pass
 
index 8a66108..89f03a4 100755 (executable)
@@ -3,7 +3,7 @@
 from sfa.rspecs.pg_rspec_converter import PGRSpecConverter
 from sfa.rspecs.sfa_rspec_converter import SfaRSpecConverter
 from sfa.rspecs.sfa_rspec import sfa_rspec_version
-from sfa.rspecs.pg_rspec import pg_rspec_version
+from sfa.rspecs.pg_rspec import pg_rspec_ad_version, pg_rspec_request_version
 from sfa.rspecs.rspec_parser import parse_rspec
 
 
@@ -14,7 +14,7 @@ class RSpecConverter:
         rspec = parse_rspec(in_rspec)
         if rspec.version['type'] == sfa_rspec_version['type']: 
           return in_rspec
-        elif rspec.version['type'] == pg_rspec_version['type']:
+        elif rspec.version['type'] == pg_rspec_ad_version['type']:
             return PGRSpecConverter.to_sfa_rspec(in_rspec)
         else:
              return in_rspec 
@@ -22,7 +22,7 @@ class RSpecConverter:
     @staticmethod 
     def to_pg_rspec(in_rspec):
         rspec = parse_rspec(in_rspec)
-        if rspec.version['type'] == pg_rspec_version['type']:
+        if rspec.version['type'] == pg_rspec_ad_version['type']:
             return in_rspec
         elif rspec.version['type'] == sfa_rspec_version['type']:
             return SfaRSpecConverter.to_pg_rspec(in_rspec)
index 5625ec7..8e3bced 100755 (executable)
@@ -15,6 +15,7 @@ def parse_rspec(in_rspec):
         out_rspec.xml = rspec.xml
     else:
         #out_rspec = PGRSpec(in_rspec)
+        # TODO: determine if this is an ad or request
         out_rspec = PGRSpec()
         out_rspec.xml = rspec.xml
     return out_rspec
index 6ffc54c..0e73ef5 100755 (executable)
@@ -218,7 +218,7 @@ class SfaRSpec(RSpec):
     def add_links(self, links):
         pass
     
-    def add_slivers(self, slivers, network=None, no_dupes=False):
+    def add_slivers(self, slivers, network=None, sliver_urn=None, no_dupes=False):
         if not isinstance(slivers, list):
             slivers = [slivers]
 
index a7a189b..096f422 100755 (executable)
@@ -25,6 +25,7 @@ class SfaRSpecConverter:
             for sfa_node_element in sfa_node_elements:
                 # create node element
                 node_attrs = {}
+                node_attrs['exclusive'] = 'false'
                 node_attrs['component_manager_id'] = network
                 if sfa_node_element.find('hostname') != None:
                     node_attrs['component_name'] = sfa_node_element.find('hostname').text
@@ -33,12 +34,10 @@ class SfaRSpecConverter:
                 node_element = pg_rspec.add_element('node', node_attrs)
 
                 # create node_type element
-                node_type_attrs = {'type_name': 'pcvm', 'type_slots': '100'}    
-                node_type_element = pg_rspec.add_element('node_type', node_type_attrs, parent=node_element)
+                for hw_type in ['plab-pc', 'pc']:
+                    hdware_type_element = pg_rspec.add_element('hardware_type', {'name': hw_type}, parent=node_element)
                 # create available element
-                pg_rspec.add_element('available', parent=node_element, text='true')
-                # create exclusive element
-                pg_rspec.add_element('exclusive', parent=node_element, text='false')
+                pg_rspec.add_element('available', {'now': 'true'}, parent=node_element)
                 # create locaiton element
                 # We don't actually associate nodes with a country. 
                 # Set country to "unknown" until we figure out how to make