From c805ff7f9d7a6eea97143767a83282944ab3dede Mon Sep 17 00:00:00 2001 From: Andy Bavier Date: Thu, 28 Jan 2010 15:38:01 +0000 Subject: [PATCH] Use lxml.etree to parse VINI RSpec, validate against RelaxNG schema --- sfa/managers/aggregate_manager_vini.py | 6 +- sfa/rspecs/aggregates/vini/utils.py | 87 +++++++++++++++++--------- sfa/util/faults.py | 8 +++ 3 files changed, 66 insertions(+), 35 deletions(-) diff --git a/sfa/managers/aggregate_manager_vini.py b/sfa/managers/aggregate_manager_vini.py index e1e7a179..418f034f 100644 --- a/sfa/managers/aggregate_manager_vini.py +++ b/sfa/managers/aggregate_manager_vini.py @@ -1,11 +1,9 @@ from sfa.util.faults import * from sfa.util.namespace import * -from sfa.util.rspec import RSpec from sfa.server.registry import Registries from sfa.plc.nodes import * from sfa.plc.api import * from sfa.rspecs.aggregates.vini.utils import * -from sfa.rspecs.aggregates.vini.rspec import * import sys """ @@ -153,10 +151,8 @@ Hook called via 'sfi.py create' """ def create_slice(api, xrn, xml): hrn = urn_to_hrn(xrn)[0] - rspec = RSpec(xml) topo = Topology(api) - - topo.nodeTopoFromRSpec(rspec) + topo.nodeTopoFromRSpec(xml) # Check request against current allocations topo.verifyNodeTopo(hrn, topo) diff --git a/sfa/rspecs/aggregates/vini/utils.py b/sfa/rspecs/aggregates/vini/utils.py index c9ca7da1..e2fa9538 100644 --- a/sfa/rspecs/aggregates/vini/utils.py +++ b/sfa/rspecs/aggregates/vini/utils.py @@ -4,7 +4,11 @@ import socket from sfa.util.faults import * from sfa.rspecs.aggregates.vini.topology import * from xmlbuilder import XMLBuilder +from lxml import etree import sys +from StringIO import StringIO + +VINI_RELAXNG_SCHEMA = "/var/www/html/schemas/vini.rng" # Taken from bwlimit.py # @@ -481,18 +485,20 @@ class Topology: def __add_vlink(self, vlink, slicenodes, parent = None): n1 = n2 = None - if 'endpoints' in vlink: - end = vlink['endpoints'].split() - n1 = self.lookupNode(end[0]) - n2 = self.lookupNode(end[1]) + endpoints = vlink.get("endpoints") + if endpoints: + (end1, end2) = endpoints.split() + n1 = self.lookupNode(end1) + n2 = self.lookupNode(end2) elif parent: - """ Try to infer the endpoints """ - (n1, n2) = self.__infer_endpoints(parent['endpoints'],slicenodes) + """ Try to infer the endpoints for the virtual link """ + site_endpoints = parent.get("endpoints") + (n1, n2) = self.__infer_endpoints(site_endpoints, slicenodes) else: raise Error("no endpoints given") #print "Added virtual link: %s -- %s" % (n1.tag, n2.tag) - bps = int(vlink['kbps'][0]) * 1000 + bps = int(vlink.findtext("kbps")) * 1000 sitelink = self.lookupSiteLink(n1, n2) if not sitelink: raise PermissionError("nodes %s and %s not adjacent" % @@ -520,38 +526,59 @@ class Topology: #print "Inferred endpoints: %s %s" % (n[0].idtag, n[1].idtag) return n - def nodeTopoFromRSpec(self, rspec): + def nodeTopoFromRSpec(self, xml): if self.nodelinks: raise Error("virtual topology already present") - rspecdict = rspec.toDict() nodedict = {} for node in self.getNodes(): nodedict[node.idtag] = node slicenodes = {} - top = rspecdict['RSpec'] - if ('network' in top): - sites = top['network'][0]['site'] - for site in sites: - for node in site['node']: - if 'sliver' in node: - n = nodedict[node['id']] - slicenodes[n.id] = n - n.add_sliver() - links = top['network'][0]['link'] - for link in links: - if 'vlink' in link: - for vlink in link['vlink']: - self.__add_vlink(vlink, slicenodes, link) - elif ('request' in top): - for sliver in top['request'][0]['sliver']: - n = nodedict[sliver['nodeid']] - slicenodes[n.id] = n - n.add_sliver() - for vlink in top['request'][0]['vlink']: - self.__add_vlink(vlink, slicenodes) + tree = etree.parse(StringIO(xml)) + + # Validate the incoming request against the RelaxNG schema + relaxng_doc = etree.parse(VINI_RELAXNG_SCHEMA) + relaxng = etree.RelaxNG(relaxng_doc) + + if not relaxng(tree): + error = relaxng.error_log.last_error + message = "%s (line %s)" % (error.message, error.line) + raise InvalidRSpec(message) + + rspec = tree.getroot() + + """ + Handle requests where the user has annotated a description of the + physical resources (nodes and links) with virtual ones (slivers + and vlinks). + """ + # Find slivers under node elements + for sliver in rspec.iterfind("./network/site/node/sliver"): + elem = sliver.getparent() + node = nodedict[elem.get("id")] + slicenodes[node.id] = node + node.add_sliver() + + # Find links under link elements + for vlink in rspec.iterfind("./network/link/vlink"): + link = vlink.getparent() + self.__add_vlink(vlink, slicenodes, link) + + """ + Handle requests where the user has listed the virtual resources only + """ + # Find slivers that specify nodeid + for sliver in rspec.iterfind("./request/sliver[@nodeid]"): + node = nodedict[sliver.get("nodeid")] + slicenodes[node.id] = node + node.add_sliver() + + # Find vlinks that specify endpoints + for vlink in rspec.iterfind("./request/vlink[@endpoints]"): + self.__add_vlink(vlink, slicenodes) + return def nodeTopoFromSliceTags(self, slice): diff --git a/sfa/util/faults.py b/sfa/util/faults.py index 5a328856..d1f070ca 100644 --- a/sfa/util/faults.py +++ b/sfa/util/faults.py @@ -255,3 +255,11 @@ class MissingSfaInfo(SfaFault): def __str__(self): return repr(self.value) +class InvalidRSpec(SfaFault): + def __init__(self, value, extra = None): + self.value = value + faultString = "Invalid RSpec: %(value)s" % locals() + SfaFault.__init__(self, 108, faultString, extra) + def __str__(self): + return repr(self.value) + -- 2.43.0