solve merge conflict
authorThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Mon, 31 Oct 2011 18:31:42 +0000 (19:31 +0100)
committerThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Mon, 31 Oct 2011 18:31:42 +0000 (19:31 +0100)
18 files changed:
sfa.spec
sfa/client/sfi.py
sfa/client/sfiAddAttribute.py
sfa/client/sfiAddLinks.py [new file with mode: 0755]
sfa/client/sfiListLinks.py [new file with mode: 0755]
sfa/managers/aggregate_manager.py
sfa/managers/registry_manager.py
sfa/managers/slice_manager.py
sfa/plc/aggregate.py
sfa/plc/slices.py
sfa/plc/vlink.py
sfa/rspecs/elements/versions/pgv2Link.py
sfa/rspecs/versions/pgv2.py
sfa/rspecs/versions/sfav1.py
sfa/server/interface.py
sfa/util/cache.py
sfa/util/record.py
sfa/util/xml.py

index a9271fc..c470c49 100644 (file)
--- a/sfa.spec
+++ b/sfa.spec
@@ -1,6 +1,6 @@
 %define name sfa
 %define version 1.1
-%define taglevel 0
+%define taglevel 1
 
 %define release %{taglevel}%{?pldistro:.%{pldistro}}%{?date:.%{date}}
 %global python_sitearch        %( python -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)" )
@@ -196,6 +196,11 @@ fi
 [ "$1" -ge "1" ] && service sfa-cm restart || :
 
 %changelog
+* Fri Oct 28 2011 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - sfa-1.1-1
+- first support for protogeni rspecs is working
+- vini no longer needs a specific manager
+- refactoring underway towards more flexible/generic architecture
+
 * Thu Sep 15 2011 Tony Mack <tmack@cs.princeton.edu> - sfa-1.0-36
 - Unicode-friendliness for user names with accents/special chars.
 - Fix bug that could cause create the client to fail when calling CreateSliver for a slice that has the same hrn as a user.
index 0b44726..4939246 100755 (executable)
@@ -232,9 +232,9 @@ class Sfi:
             parser.add_option("-d", "--delegate", dest="delegate", default=None, 
                              action="store_true",
                              help="Include a credential delegated to the user's root"+\
-                                  "authority in set of credentials for this call")  
-        
-        # registy filter option    
+                                  "authority in set of credentials for this call")
+
+        # registy filter option
         if command in ("list", "show", "remove"):
             parser.add_option("-t", "--type", dest="type", type="choice",
                             help="type filter ([all]|user|slice|authority|node|aggregate)",
@@ -521,7 +521,7 @@ class Sfi:
         if args:
             hrn = args[0]
         gid = self._get_gid(hrn)
-        self.logger.debug("Sfi.get_gid-> %s",gid.save_to_string(save_parents=True))
+        self.logger.debug("Sfi.get_gid-> %s" % gid.save_to_string(save_parents=True))
         return gid
 
     def _get_gid(self, hrn=None, type=None):
@@ -985,10 +985,15 @@ class Sfi:
         slice_urn = hrn_to_urn(slice_hrn, 'slice')
         user_cred = self.get_user_cred()
         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
-        # delegate the cred to the callers root authority
-        delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority)+'.slicemanager')
-        #delegated_cred = self.delegate_cred(slice_cred, get_authority(slice_hrn))
-        #creds.append(delegated_cred)
+
+        if hasattr(opts, 'aggregate') and opts.aggregate:
+            delegated_cred = None
+        else:
+            # delegate the cred to the callers root authority
+            delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority)+'.slicemanager')
+            #delegated_cred = self.delegate_cred(slice_cred, get_authority(slice_hrn))
+            #creds.append(delegated_cred)
+
         rspec_file = self.get_rspec_file(args[1])
         rspec = open(rspec_file).read()
 
@@ -1013,11 +1018,13 @@ class Sfi:
                 creds = [slice_cred]
             else:
                 users = sfa_users_arg(user_records, slice_record)
-                creds = [slice_cred, delegated_cred]
+                creds = [slice_cred]
+                if delegated_cred:
+                    creds.append(delegated_cred)
         call_args = [slice_urn, creds, rspec, users]
         if self.server_supports_call_id_arg(server):
             call_args.append(unique_call_id())
-           
+
         result = server.CreateSliver(*call_args)
         if opts.file is None:
             print result
index 9c2eae5..f22e63e 100755 (executable)
@@ -1,7 +1,6 @@
 #! /usr/bin/env python
 
 import sys
-from sfa.util.rspecHelper import RSpec, Commands
 from sfa.client.sfi_commands import Commands
 from sfa.rspecs.rspec import RSpec
 
diff --git a/sfa/client/sfiAddLinks.py b/sfa/client/sfiAddLinks.py
new file mode 100755 (executable)
index 0000000..f5b2888
--- /dev/null
@@ -0,0 +1,45 @@
+#! /usr/bin/env python
+
+import sys
+from sfa.client.sfi_commands import Commands
+from sfa.rspecs.rspec import RSpec
+from sfa.rspecs.version_manager import VersionManager
+
+command = Commands(usage="%prog [options] node1 node2...",
+                   description="Add links to the RSpec. " +
+                   "This command reads in an RSpec and outputs a modified " +
+                   "RSpec. Use this to add links to your slivers")
+command.add_linkfile_option()
+command.prep()
+
+if not command.opts.linkfile:
+    print "Missing link list -- exiting"
+    command.parser.print_help()
+    sys.exit(1)
+    
+if command.opts.infile:
+    infile=file(command.opts.infile)
+else:
+    infile=sys.stdin
+if command.opts.outfile:
+    outfile=file(command.opts.outfile,"w")
+else:
+    outfile=sys.stdout
+ad_rspec = RSpec(infile)
+links = file(command.opts.linkfile).read().split('\n')
+link_tuples = map(lambda x: tuple(x.split()), links)
+
+version_manager = VersionManager()
+try:
+    type = ad_rspec.version.type
+    version_num = ad_rspec.version.version
+    request_version = version_manager._get_version(type, version_num, 'request')    
+    request_rspec = RSpec(version=request_version)
+    request_rspec.version.merge(ad_rspec)
+    request_rspec.version.add_link_requests(link_tuples)
+except:
+    print >> sys.stderr, "FAILED: %s" % links
+    raise
+    sys.exit(1)
+print >>outfile, request_rspec.toxml()
+sys.exit(0)
diff --git a/sfa/client/sfiListLinks.py b/sfa/client/sfiListLinks.py
new file mode 100755 (executable)
index 0000000..a4720ca
--- /dev/null
@@ -0,0 +1,26 @@
+#! /usr/bin/env python
+
+import sys
+from sfa.client.sfi_commands import Commands
+from sfa.rspecs.rspec import RSpec
+from sfa.util.xrn import Xrn 
+
+command = Commands(usage="%prog [options]",
+                   description="List all links in the RSpec. " + 
+                   "Use this to display the list of available links. " ) 
+command.prep()
+
+if command.opts.infile:
+    rspec = RSpec(command.opts.infile)
+    links = rspec.version.get_links()
+    if command.opts.outfile:
+        sys.stdout = open(command.opts.outfile, 'w')
+    
+    for link in links:
+        ifname1 = Xrn(link['interface1']['component_id']).get_leaf()
+        ifname2 = Xrn(link['interface2']['component_id']).get_leaf()
+        print "%s %s" % (ifname1, ifname2)
+
+
+
+    
index 20db05c..827b2d9 100644 (file)
@@ -188,6 +188,8 @@ def CreateSliver(api, slice_xrn, creds, rspec_string, users, call_id):
     requested_slivers = [str(host) for host in rspec.version.get_nodes_with_slivers()]
     slices.verify_slice_nodes(slice, requested_slivers, peer) 
 
+    aggregate.prepare_nodes({'hostname': requested_slivers})
+    aggregate.prepare_interfaces({'node_id': aggregate.nodes.keys()})    
     slices.verify_slice_links(slice, rspec.version.get_link_requests(), aggregate)
 
     # hanlde MyPLC peer association.
@@ -324,31 +326,17 @@ def ListResources(api, creds, options, call_id):
 
 def get_ticket(api, xrn, creds, rspec, users):
 
-#unused
-#    reg_objects = __get_registry_objects(xrn, creds, users)
-
     (slice_hrn, _) = urn_to_hrn(xrn)
-#unused
-#    slices = Slices(api)
-#    peer = slices.get_peer(slice_hrn)
-#    sfa_peer = slices.get_sfa_peer(slice_hrn)
+    slices = Slices(api)
+    peer = slices.get_peer(slice_hrn)
+    sfa_peer = slices.get_sfa_peer(slice_hrn)
 
     # get the slice record
-    registry = api.registries[api.hrn]
     credential = api.getCredential()
+    interface = api.registries[api.hrn]
+    registry = api.get_server(interface, credential)
     records = registry.Resolve(xrn, credential)
 
-    # similar to CreateSliver, we must verify that the required records exist
-    # at this aggregate before we can issue a ticket
-#Error (E1121, get_ticket): Too many positional arguments for function call
-#unused anyway
-#    site_id, remote_site_id = slices.verify_site(registry, credential, slice_hrn,
-#                                                 peer, sfa_peer, reg_objects)
-#Error (E1121, get_ticket): Too many positional arguments for function call
-#unused anyway
-#    slice = slices.verify_slice(registry, credential, slice_hrn, site_id,
-#                                remote_site_id, peer, sfa_peer, reg_objects)
-
     # make sure we get a local slice record
     record = None
     for tmp_record in records:
@@ -358,9 +346,25 @@ def get_ticket(api, xrn, creds, rspec, users):
             record = SliceRecord(dict=tmp_record)
     if not record:
         raise RecordNotFound(slice_hrn)
+    
+    # similar to CreateSliver, we must verify that the required records exist
+    # at this aggregate before we can issue a ticket
+    # parse rspec
+    rspec = RSpec(rspec_string)
+    requested_attributes = rspec.version.get_slice_attributes()
 
+    # ensure site record exists
+    site = slices.verify_site(hrn, slice_record, peer, sfa_peer)
+    # ensure slice record exists
+    slice = slices.verify_slice(hrn, slice_record, peer, sfa_peer)
+    # ensure person records exists
+    persons = slices.verify_persons(hrn, slice, users, peer, sfa_peer)
+    # ensure slice attributes exists
+    slices.verify_slice_attributes(slice, requested_attributes)
+    
     # get sliver info
-    slivers = Slices(api).get_slivers(slice_hrn)
+    slivers = slices.get_slivers(slice_hrn)
+
     if not slivers:
         raise SliverDoesNotExist(slice_hrn)
 
index e4a5b17..085bc39 100644 (file)
@@ -119,7 +119,9 @@ def resolve(api, xrns, type=None, full=True):
         xrns = xrn_dict[registry_hrn]
         if registry_hrn != api.hrn:
             credential = api.getCredential()
-            peer_records = registries[registry_hrn].Resolve(xrns, credential)
+            interface = api.registries[registry_hrn]
+            server = api.get_server(interface, credential)
+            peer_records = server.Resolve(xrns, credential)
             records.extend([SfaRecord(dict=record).as_dict() for record in peer_records])
 
     # try resolving the remaining unfound records at the local registry
@@ -155,13 +157,14 @@ def list(api, xrn, origin_hrn=None):
     #if there was no match then this record belongs to an unknow registry
     if not registry_hrn:
         raise MissingAuthority(xrn)
-    
     # if the best match (longest matching hrn) is not the local registry,
     # forward the request
     records = []    
     if registry_hrn != api.hrn:
         credential = api.getCredential()
-        record_list = registries[registry_hrn].List(xrn, credential)
+        interface = api.registries[registry_hrn]
+        server = api.get_server(interface, credential)
+        record_list = server.List(xrn, credential)
         records = [SfaRecord(dict=record).as_dict() for record in record_list]
     
     # if we still have not found the record yet, try the local registry
index b84ef71..2911313 100644 (file)
@@ -8,7 +8,6 @@ from sfa.trust.sfaticket import SfaTicket
 from sfa.trust.credential import Credential
 
 from sfa.util.sfalogging import logger
-from sfa.util.rspecHelper import merge_rspecs
 from sfa.util.xrn import Xrn, urn_to_hrn
 from sfa.util.threadmanager import ThreadManager
 from sfa.util.version import version_core
@@ -434,7 +433,7 @@ def get_ticket(api, xrn, creds, rspec, users):
     results = threads.get_results()
     
     # gather information from each ticket 
-    rspecs = []
+    rspec = None
     initscripts = []
     slivers = [] 
     object_gid = None  
@@ -443,15 +442,17 @@ def get_ticket(api, xrn, creds, rspec, users):
         attrs = agg_ticket.get_attributes()
         if not object_gid:
             object_gid = agg_ticket.get_gid_object()
-        rspecs.append(agg_ticket.get_rspec())
+        if not rspec:
+            rspec = RSpec(agg_ticket.get_rspec())
+        else:
+            rspec.version.merge(agg_ticket.get_rspec())
         initscripts.extend(attrs.get('initscripts', [])) 
         slivers.extend(attrs.get('slivers', [])) 
     
     # merge info
     attributes = {'initscripts': initscripts,
                  'slivers': slivers}
-    merged_rspec = merge_rspecs(rspecs) 
-
+    
     # create a new ticket
     ticket = SfaTicket(subject = slice_hrn)
     ticket.set_gid_caller(api.auth.client_gid)
@@ -460,7 +461,7 @@ def get_ticket(api, xrn, creds, rspec, users):
     ticket.set_pubkey(object_gid.get_pubkey())
     #new_ticket.set_parent(api.auth.hierarchy.get_auth_ticket(auth_hrn))
     ticket.set_attributes(attributes)
-    ticket.set_rspec(merged_rspec)
+    ticket.set_rspec(rspec.toxml())
     ticket.encode()
     ticket.sign()          
     return ticket.save_to_string(save_parents=True)
index 77784cb..f210705 100644 (file)
@@ -25,14 +25,26 @@ class Aggregate:
         self.api = api
         self.user_options = user_options
 
-    def prepare_sites(self, force=False):
+    def prepare_sites(self, filter={}, force=False):
         if not self.sites or force:  
-            for site in self.api.plshell.GetSites(self.api.plauth):
+            for site in self.api.plshell.GetSites(self.api.plauth, filter):
                 self.sites[site['site_id']] = site
     
-    def prepare_nodes(self, force=False):
+    def prepare_nodes(self, filter={}, force=False):
         if not self.nodes or force:
-            for node in self.api.plshell.GetNodes(self.api.plauth, {'peer_id': None}):
+            filter.update({'peer_id': None})
+            nodes = self.api.plshell.GetNodes(self.api.plauth, filter)
+            site_ids = []
+            interface_ids = []
+            tag_ids = []
+            for node in nodes:
+                site_ids.append(node['site_id'])
+                interface_ids.extend(node['interface_ids'])
+                tag_ids.extend(node['node_tag_ids'])
+            self.prepare_sites({'site_id': site_ids})
+            self.prepare_interfaces({'interface_id': interface_ids})
+            self.prepare_node_tags({'node_tag_id': tag_ids}) 
+            for node in nodes:
                 # add site/interface info to nodes.
                 # assumes that sites, interfaces and tags have already been prepared.
                 site = self.sites[node['site_id']]
@@ -47,12 +59,12 @@ class Aggregate:
                 node['tags'] = tags
                 self.nodes[node['node_id']] = node
 
-    def prepare_interfaces(self, force=False):
+    def prepare_interfaces(self, filter={}, force=False):
         if not self.interfaces or force:
-            for interface in self.api.plshell.GetInterfaces(self.api.plauth):
+            for interface in self.api.plshell.GetInterfaces(self.api.plauth, filter):
                 self.interfaces[interface['interface_id']] = interface
 
-    def prepare_links(self, force=False):
+    def prepare_links(self, filter={}, force=False):
         if not self.links or force:
             if not self.api.config.SFA_AGGREGATE_TYPE.lower() == 'vini':
                 return
@@ -73,10 +85,12 @@ class Aggregate:
                 # set interfaces
                 # just get first interface of the first node
                 if1_xrn = PlXrn(auth=self.api.hrn, interface='node%s:eth0' % (node1['node_id']))
+                if1_ipv4 = self.interfaces[node1['interface_ids'][0]]['ip']
                 if2_xrn = PlXrn(auth=self.api.hrn, interface='node%s:eth0' % (node2['node_id']))
+                if2_ipv4 = self.interfaces[node2['interface_ids'][0]]['ip']
 
-                if1 = Interface({'component_id': if1_xrn.urn} )
-                if2 = Interface({'component_id': if2_xrn.urn} )
+                if1 = Interface({'component_id': if1_xrn.urn, 'ipv4': if1_ipv4} )
+                if2 = Interface({'component_id': if2_xrn.urn, 'ipv4': if2_ipv4} )
 
                 # set link
                 link = Link({'capacity': '1000000', 'latency': '0', 'packet_loss': '0', 'type': 'ipv4'})
@@ -88,28 +102,36 @@ class Aggregate:
                 self.links[link['component_name']] = link
 
 
-    def prepare_node_tags(self, force=False):
+    def prepare_node_tags(self, filter={}, force=False):
         if not self.node_tags or force:
-            for node_tag in self.api.plshell.GetNodeTags(self.api.plauth):
+            for node_tag in self.api.plshell.GetNodeTags(self.api.plauth, filter):
                 self.node_tags[node_tag['node_tag_id']] = node_tag
 
-    def prepare_pl_initscripts(self, force=False):
+    def prepare_pl_initscripts(self, filter={}, force=False):
         if not self.pl_initscripts or force:
-            for initscript in self.api.plshell.GetInitScripts(self.api.plauth, {'enabled': True}):
+            filter.update({'enabled': True})
+            for initscript in self.api.plshell.GetInitScripts(self.api.plauth, filter):
                 self.pl_initscripts[initscript['initscript_id']] = initscript
 
-    def prepare(self, force=False):
-        if not self.prepared or force:
-            self.prepare_sites(force)
-            self.prepare_interfaces(force)
-            self.prepare_node_tags(force)
-            self.prepare_nodes(force)
-            self.prepare_links(force)
-            self.prepare_pl_initscripts()
-        self.prepared = True  
+    def prepare(self, slice = None, force=False):
+        if not self.prepared or force or slice:
+            if not slice:
+                self.prepare_sites(force=force)
+                self.prepare_interfaces(force=force)
+                self.prepare_node_tags(force=force)
+                self.prepare_nodes(force=force)
+                self.prepare_links(force=force)
+                self.prepare_pl_initscripts(force=force)
+            else:
+                self.prepare_sites({'site_id': slice['site_id']})
+                self.prepare_interfaces({'node_id': slice['node_ids']})
+                self.prepare_node_tags({'node_id': slice['node_ids']})
+                self.prepare_nodes({'node_id': slice['node_ids']})
+                self.prepare_links({'slice_id': slice['slice_id']})
+                self.prepare_pl_initscripts()
+            self.prepared = True  
 
     def get_rspec(self, slice_xrn=None, version = None):
-        self.prepare()
         version_manager = VersionManager()
         version = version_manager.get_version(version)
         if not slice_xrn:
@@ -125,8 +147,11 @@ class Aggregate:
             slice_name = hrn_to_pl_slicename(slice_hrn)
             slices = self.api.plshell.GetSlices(self.api.plauth, slice_name)
             if slices:
-                slice = slices[0]            
-
+                slice = slices[0]
+            self.prepare(slice=slice)
+        else:
+            self.prepare()
+            
         # filter out nodes with a whitelist:
         valid_nodes = [] 
         for node in self.nodes.values():
index 5edce64..5cead3b 100644 (file)
@@ -6,6 +6,7 @@ from sfa.util.plxrn import hrn_to_pl_slicename
 from sfa.util.policy import Policy
 from sfa.rspecs.rspec import RSpec
 from sfa.plc.vlink import VLink
+from sfa.util.xrn import Xrn
 
 MAXINT =  2L**31-1
 
@@ -185,10 +186,20 @@ class Slices:
 
     def verify_slice_links(self, slice, links, aggregate):
         # nodes is undefined here
-        if not links or not aggregate.nodes:
+        if not links:
             return 
+        
         for link in links:
-            topo_rspec = VLink.get_topo_rspec(link)            
+            # get the ip address of the first node in the link
+            ifname1 = Xrn(link['interface1']['component_id']).get_leaf()
+            (node, device) = ifname1.split(':')
+            node_id = int(node.replace('node', ''))
+            node = aggregate.nodes[node_id]
+            if1 = aggregate.interfaces[node['interface_ids'][0]]
+            ipaddr = if1['ip']
+            topo_rspec = VLink.get_topo_rspec(link, ipaddr)
+            self.api.plshell.AddSliceTag(self.api.plauth, slice['name'], 'topo_rspec', str([topo_rspec]), node_id) 
+                        
         
 
     def handle_peer(self, site, slice, persons, peer):
index 73ebae7..625963d 100644 (file)
@@ -1,4 +1,4 @@
-
+import re
 from sfa.util.xrn import Xrn
 # Taken from bwlimit.py
 #
@@ -79,34 +79,37 @@ class VLink:
 
     @staticmethod
     def get_virt_ip(if1, if2):
-        link_id = get_link_id(if1, if2)
-        iface_id = get_iface_id(if1, if2)
+        link_id = VLink.get_link_id(if1, if2)
+        iface_id = VLink.get_iface_id(if1, if2)
         first = link_id >> 6
         second = ((link_id & 0x3f)<<2) + iface_id
-        return "192.168.%d.%s" % (frist, second)
+        return "192.168.%d.%s" % (first, second)
 
     @staticmethod
     def get_virt_net(link):
-        link_id = self.get_link_id(link)
+        link_id = VLink.get_link_id(link['interface1'], link['interface2'])
         first = link_id >> 6
         second = (link_id & 0x3f)<<2
         return "192.168.%d.%d/30" % (first, second)
 
     @staticmethod
     def get_interface_id(interface):
-        if_name = Xrn(interface=interface['component_id']).get_leaf()
+        if_name = Xrn(interface['component_id']).get_leaf()
         node, dev = if_name.split(":")
-        node_id = int(node.replace("pc", ""))
+        node_id = int(node.replace("node", ""))
         return node_id
 
         
     @staticmethod
-    def get_topo_rspec(link):
+    def get_topo_rspec(link, ipaddr):
         link['interface1']['id'] = VLink.get_interface_id(link['interface1'])
         link['interface2']['id'] = VLink.get_interface_id(link['interface2'])
         my_ip = VLink.get_virt_ip(link['interface1'], link['interface2'])
         remote_ip = VLink.get_virt_ip(link['interface2'], link['interface1'])
         net = VLink.get_virt_net(link)
         bw = format_tc_rate(long(link['capacity']))
-        ipaddr = remote.get_primary_iface().ipv4
-        return (link['interface2']['id'], ipaddr, bw, my_ip, remote_ip, net) 
+        return (link['interface2']['id'], ipaddr, bw, my_ip, remote_ip, net)
+
+    @staticmethod 
+    def topo_rspec_to_link(topo_rspec):
+        pass          
index e39ef35..aeef760 100644 (file)
@@ -17,9 +17,8 @@ class PGv2Link:
     
     @staticmethod
     def add_links(xml, links):
-        root = xml.root
         for link in links:
-            link_elem = etree.SubElement(root, 'link')
+            link_elem = etree.SubElement(xml, 'link')
             for attrib in ['component_name', 'component_id', 'client_id']:
                 if attrib in link and link[attrib] is not None:
                     link_elem.set(attrib, link[attrib])
@@ -38,7 +37,6 @@ class PGv2Link:
                 latency=link['latency'], packet_loss=link['packet_loss'])
             if 'type' in link and link['type']:
                 type_elem = etree.SubElement(link_elem, 'link_type', name=link['type'])             
-   
     @staticmethod 
     def get_links(xml):
         links = []
@@ -87,18 +85,16 @@ class PGv2Link:
         available_links = PGv2Link.get_links(xml)
         recently_added = []
         for link in available_links:
-            auth = Xrn(link['component_id']).get_authority_hrn()
             if_name1 =  Xrn(link['interface1']['component_id']).get_leaf()
             if_name2 =  Xrn(link['interface2']['component_id']).get_leaf()
-            
+             
             requested_link = None
             l_tup_1 = (if_name1, if_name2)
-            l_tup_2 = (if_name2, if_name1) 
+            l_tup_2 = (if_name2, if_name1)
             if link_tuples.issuperset([(if_name1, if_name2)]):
                 requested_link = (if_name1, if_name2)        
             elif link_tuples.issuperset([(if_name2, if_name2)]):
                 requested_link = (if_name2, if_name1)
-            
             if requested_link:
                 # add client id to link ane interface elements 
                 link.element.set('client_id', link['component_name'])
index af5b367..b57cd9b 100644 (file)
@@ -99,10 +99,10 @@ class PGv2(BaseVersion):
         return PGv2Link.get_link_requests(self.xml)  
 
     def add_links(self, links):
-        PGv2Link.add_links(self.xml, links)
+        PGv2Link.add_links(self.xml.root, links)
 
     def add_link_requests(self, link_tuples, append=False):
-        PGv2Link.add_link_requests(self.xml, link_tuples, append)
+        PGv2Link.add_link_requests(self.xml.root, link_tuples, append)
 
     def attributes_list(self, elem):
         opts = []
index c3bb208..3917b39 100644 (file)
@@ -1,3 +1,4 @@
+from copy import deepcopy
 from lxml import etree
 from sfa.util.xrn import hrn_to_urn, urn_to_hrn
 from sfa.util.plxrn import PlXrn
@@ -217,7 +218,8 @@ class SFAv1(BaseVersion):
                     if 'bwlimit' in interface and interface['bwlimit']:
                         bwlimit = etree.SubElement(node_tag, 'bw_limit', units='kbps').text = str(interface['bwlimit']/1000)
                     comp_id = PlXrn(auth=network, interface='node%s:eth%s' % (node['node_id'], i)).get_urn() 
-                    interface_tag = etree.SubElement(node_tag, 'interface', component_id=comp_id)
+                    ipaddr = interface['ip'] 
+                    interface_tag = etree.SubElement(node_tag, 'interface', component_id=comp_id, ipv4=ipaddr)
                     i+=1
             if 'bw_unallocated' in node:
                 bw_unallocated = etree.SubElement(node_tag, 'bw_unallocated', units='kbps').text = str(node['bw_unallocated']/1000) 
@@ -245,7 +247,15 @@ class SFAv1(BaseVersion):
         pass
 
     def add_links(self, links):
-        PGv2Link.add_links(self.xml, links)
+        networks = self.get_network_elements()
+        if len(networks) > 0:
+            xml = networks[0]
+        else:
+            xml = self.xml    
+        PGv2Link.add_links(xml, links)
+
+    def add_link_requests(self, links):
+        PGv2Link.add_link_requests(self.xml, links)
 
     def add_slivers(self, slivers, network=None, sliver_urn=None, no_dupes=False, append=False):
         # add slice name to network tag
index 7d2beef..94302ec 100644 (file)
@@ -1,6 +1,6 @@
 #from sfa.util.faults import *
-from sfa.util.storage import XmlStorage
 import sfa.util.xmlrpcprotocol as xmlrpcprotocol
+from sfa.util.xml import XML
 
 # GeniLight client support is optional
 try:
@@ -57,25 +57,20 @@ class Interfaces(dict):
     def __init__(self, conf_file):
         dict.__init__(self, {})
         # load config file
-        self.interface_info = XmlStorage(conf_file, self.default_dict)
-        self.interface_info.load()
-        records = self.interface_info.values()[0]
-        if not isinstance(records, list):
-            records = [records]
-        
-        required_fields = self.default_fields.keys()
-        for record in records:
-            if not record or not set(required_fields).issubset(record.keys()):
-                continue
-            # port is appended onto the domain, before the path. Should look like:
-            # http://domain:port/path
-            hrn, address, port = record['hrn'], record['addr'], record['port']
-            # sometime this is called at a very early stage with no config loaded
-            # avoid to remember this instance in such a case
-            if not address or not port:
-                continue
-            interface = Interface(hrn, address, port) 
-            self[hrn] = interface
+        required_fields = set(self.default_fields.keys())
+        self.interface_info = XML(conf_file).todict()
+        for value in self.interface_info.values():
+            if isinstance(value, list):
+                for record in value:
+                    if isinstance(record, dict) and \
+                      required_fields.issubset(record.keys()):
+                        hrn, address, port = record['hrn'], record['addr'], record['port']
+                        # sometime this is called at a very early stage with no config loaded
+                        # avoid to remember this instance in such a case
+                        if not address or not port:
+                            continue     
+                        interface = Interface(hrn, address, port)
+                        self[hrn] = interface   
 
     def get_server(self, hrn, key_file, cert_file, timeout=30):
         return self[hrn].get_server(key_file, cert_file, timeout)
index 0383ccc..a2ded4a 100644 (file)
@@ -82,9 +82,18 @@ class Cache:
            
     def get(self, key):
         data = self.cache.get(key)
-        if not data or data.is_expired():
-            return None 
-        return data.get_data()
+        if not data:  
+            data = None
+        elif data.is_expired():
+            self.pop(key)
+            data = None 
+        else:
+            data = data.get_data()
+        return data
+
+    def pop(self, key):
+        if key in self.cache:
+            self.cache.pop(key) 
 
     def dump(self):
         result = {}
index 54c3f9f..7ebf379 100644 (file)
@@ -279,6 +279,7 @@ class SfaRecord(Row):
         """
         Load the record from a dictionary 
         """
+
         self.set_name(dict['hrn'])
         gidstr = dict.get("gid", None)
         if gidstr:
@@ -316,7 +317,7 @@ class SfaRecord(Row):
         representation of the record.
         """
         #dict = xmlrpclib.loads(str)[0][0]
-        
+
         record = XML(str)
         self.load_from_dict(record.todict())
 
index 78e4c6a..8f51ce3 100755 (executable)
@@ -96,8 +96,15 @@ class XML:
             elif isinstance(value, int):
                 d[key] = unicode(d[key])  
             elif value is None:
-                d.pop(key)          
-             
+                d.pop(key)
+
+        # element.attrib.update will explode if DateTimes are in the
+        # dcitionary.
+        d=d.copy()
+        for k in d.keys():
+            if (type(d[k]) != str) and (type(d[k]) != unicode):
+                del d[k]
+
         element.attrib.update(d)
 
     def validate(self, schema):
@@ -209,6 +216,7 @@ class XML:
     def toxml(self):
         return etree.tostring(self.root, encoding='UTF-8', pretty_print=True)  
     
+    # XXX smbaker, for record.load_from_string
     def todict(self, elem=None):
         if elem is None:
             elem = self.root
@@ -219,7 +227,11 @@ class XML:
             if child.tag not in d:
                 d[child.tag] = []
             d[child.tag].append(self.todict(child))
-        return d            
+
+        if len(d)==1 and ("text" in d):
+            d = d["text"]
+
+        return d
         
     def save(self, filename):
         f = open(filename, 'w')