summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorNaveed Massjouni <naveedm9@gmail.com>2011-08-09 02:07:20 +0000
committerTarmac <>2011-08-09 02:07:20 +0000
commitc8c76cb1e276d242b97b9e540a9831ccaa6d32c8 (patch)
tree92d23ee75262e44ec5c149db5705442f6607cc9b /nova/api
parentd63bfef32d33edca440038c978f61bd303db23aa (diff)
parent72dc7939f4bfd05588b09046cbd25be09413c4eb (diff)
Added xml schema validation for extensions resources.
Added corresponding xml schemas. Added lxml dep, which is needed for doing xml schema validation.
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/openstack/extensions.py31
-rw-r--r--nova/api/openstack/schemas/atom-link.rng141
-rw-r--r--nova/api/openstack/schemas/atom.rng597
-rw-r--r--nova/api/openstack/schemas/v1.1/extension.rng11
-rw-r--r--nova/api/openstack/schemas/v1.1/extensions.rng6
-rw-r--r--nova/api/openstack/xmlutil.py37
6 files changed, 809 insertions, 14 deletions
diff --git a/nova/api/openstack/extensions.py b/nova/api/openstack/extensions.py
index cc889703e..6188e274d 100644
--- a/nova/api/openstack/extensions.py
+++ b/nova/api/openstack/extensions.py
@@ -23,7 +23,7 @@ import sys
import routes
import webob.dec
import webob.exc
-from xml.etree import ElementTree
+from lxml import etree
from nova import exception
from nova import flags
@@ -32,6 +32,7 @@ from nova import wsgi as base_wsgi
from nova.api.openstack import common
from nova.api.openstack import faults
from nova.api.openstack import wsgi
+from nova.api.openstack import xmlutil
LOG = logging.getLogger('extensions')
@@ -470,36 +471,38 @@ class ResourceExtension(object):
class ExtensionsXMLSerializer(wsgi.XMLDictSerializer):
+ NSMAP = {None: xmlutil.XMLNS_V11, 'atom': xmlutil.XMLNS_ATOM}
+
def show(self, ext_dict):
- ext = self._create_ext_elem(ext_dict['extension'])
+ ext = etree.Element('extension', nsmap=self.NSMAP)
+ self._populate_ext(ext, ext_dict['extension'])
return self._to_xml(ext)
def index(self, exts_dict):
- exts = ElementTree.Element('extensions')
+ exts = etree.Element('extensions', nsmap=self.NSMAP)
for ext_dict in exts_dict['extensions']:
- exts.append(self._create_ext_elem(ext_dict))
+ ext = etree.SubElement(exts, 'extension')
+ self._populate_ext(ext, ext_dict)
return self._to_xml(exts)
- def _create_ext_elem(self, ext_dict):
- """Create an extension xml element from a dict."""
- ext_elem = ElementTree.Element('extension')
+ def _populate_ext(self, ext_elem, ext_dict):
+ """Populate an extension xml element from a dict."""
+
ext_elem.set('name', ext_dict['name'])
ext_elem.set('namespace', ext_dict['namespace'])
ext_elem.set('alias', ext_dict['alias'])
ext_elem.set('updated', ext_dict['updated'])
- desc = ElementTree.Element('description')
+ desc = etree.Element('description')
desc.text = ext_dict['description']
ext_elem.append(desc)
for link in ext_dict.get('links', []):
- elem = ElementTree.Element('atom:link')
+ elem = etree.SubElement(ext_elem, '{%s}link' % xmlutil.XMLNS_ATOM)
elem.set('rel', link['rel'])
elem.set('href', link['href'])
elem.set('type', link['type'])
- ext_elem.append(elem)
return ext_elem
def _to_xml(self, root):
- """Convert the xml tree object to an xml string."""
- root.set('xmlns', wsgi.XMLNS_V11)
- root.set('xmlns:atom', wsgi.XMLNS_ATOM)
- return ElementTree.tostring(root, encoding='UTF-8')
+ """Convert the xml object to an xml string."""
+
+ return etree.tostring(root, encoding='UTF-8')
diff --git a/nova/api/openstack/schemas/atom-link.rng b/nova/api/openstack/schemas/atom-link.rng
new file mode 100644
index 000000000..edba5eee6
--- /dev/null
+++ b/nova/api/openstack/schemas/atom-link.rng
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ -*- rnc -*-
+ RELAX NG Compact Syntax Grammar for the
+ Atom Format Specification Version 11
+-->
+<grammar xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:s="http://www.ascc.net/xml/schematron" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+ <start>
+ <choice>
+ <ref name="atomLink"/>
+ </choice>
+ </start>
+ <!-- Common attributes -->
+ <define name="atomCommonAttributes">
+ <optional>
+ <attribute name="xml:base">
+ <ref name="atomUri"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="xml:lang">
+ <ref name="atomLanguageTag"/>
+ </attribute>
+ </optional>
+ <zeroOrMore>
+ <ref name="undefinedAttribute"/>
+ </zeroOrMore>
+ </define>
+ <!-- atom:link -->
+ <define name="atomLink">
+ <element name="atom:link">
+ <ref name="atomCommonAttributes"/>
+ <attribute name="href">
+ <ref name="atomUri"/>
+ </attribute>
+ <optional>
+ <attribute name="rel">
+ <choice>
+ <ref name="atomNCName"/>
+ <ref name="atomUri"/>
+ </choice>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="type">
+ <ref name="atomMediaType"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="hreflang">
+ <ref name="atomLanguageTag"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="title"/>
+ </optional>
+ <optional>
+ <attribute name="length"/>
+ </optional>
+ <ref name="undefinedContent"/>
+ </element>
+ </define>
+ <!-- Low-level simple types -->
+ <define name="atomNCName">
+ <data type="string">
+ <param name="minLength">1</param>
+ <param name="pattern">[^:]*</param>
+ </data>
+ </define>
+ <!-- Whatever a media type is, it contains at least one slash -->
+ <define name="atomMediaType">
+ <data type="string">
+ <param name="pattern">.+/.+</param>
+ </data>
+ </define>
+ <!-- As defined in RFC 3066 -->
+ <define name="atomLanguageTag">
+ <data type="string">
+ <param name="pattern">[A-Za-z]{1,8}(-[A-Za-z0-9]{1,8})*</param>
+ </data>
+ </define>
+ <!--
+ Unconstrained; it's not entirely clear how IRI fit into
+ xsd:anyURI so let's not try to constrain it here
+ -->
+ <define name="atomUri">
+ <text/>
+ </define>
+ <!-- Other Extensibility -->
+ <define name="undefinedAttribute">
+ <attribute>
+ <anyName>
+ <except>
+ <name>xml:base</name>
+ <name>xml:lang</name>
+ <nsName ns=""/>
+ </except>
+ </anyName>
+ </attribute>
+ </define>
+ <define name="undefinedContent">
+ <zeroOrMore>
+ <choice>
+ <text/>
+ <ref name="anyForeignElement"/>
+ </choice>
+ </zeroOrMore>
+ </define>
+ <define name="anyElement">
+ <element>
+ <anyName/>
+ <zeroOrMore>
+ <choice>
+ <attribute>
+ <anyName/>
+ </attribute>
+ <text/>
+ <ref name="anyElement"/>
+ </choice>
+ </zeroOrMore>
+ </element>
+ </define>
+ <define name="anyForeignElement">
+ <element>
+ <anyName>
+ <except>
+ <nsName ns="http://www.w3.org/2005/Atom"/>
+ </except>
+ </anyName>
+ <zeroOrMore>
+ <choice>
+ <attribute>
+ <anyName/>
+ </attribute>
+ <text/>
+ <ref name="anyElement"/>
+ </choice>
+ </zeroOrMore>
+ </element>
+ </define>
+</grammar>
diff --git a/nova/api/openstack/schemas/atom.rng b/nova/api/openstack/schemas/atom.rng
new file mode 100644
index 000000000..c2df4e410
--- /dev/null
+++ b/nova/api/openstack/schemas/atom.rng
@@ -0,0 +1,597 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ -*- rnc -*-
+ RELAX NG Compact Syntax Grammar for the
+ Atom Format Specification Version 11
+-->
+<grammar xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:s="http://www.ascc.net/xml/schematron" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+ <start>
+ <choice>
+ <ref name="atomFeed"/>
+ <ref name="atomEntry"/>
+ </choice>
+ </start>
+ <!-- Common attributes -->
+ <define name="atomCommonAttributes">
+ <optional>
+ <attribute name="xml:base">
+ <ref name="atomUri"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="xml:lang">
+ <ref name="atomLanguageTag"/>
+ </attribute>
+ </optional>
+ <zeroOrMore>
+ <ref name="undefinedAttribute"/>
+ </zeroOrMore>
+ </define>
+ <!-- Text Constructs -->
+ <define name="atomPlainTextConstruct">
+ <ref name="atomCommonAttributes"/>
+ <optional>
+ <attribute name="type">
+ <choice>
+ <value>text</value>
+ <value>html</value>
+ </choice>
+ </attribute>
+ </optional>
+ <text/>
+ </define>
+ <define name="atomXHTMLTextConstruct">
+ <ref name="atomCommonAttributes"/>
+ <attribute name="type">
+ <value>xhtml</value>
+ </attribute>
+ <ref name="xhtmlDiv"/>
+ </define>
+ <define name="atomTextConstruct">
+ <choice>
+ <ref name="atomPlainTextConstruct"/>
+ <ref name="atomXHTMLTextConstruct"/>
+ </choice>
+ </define>
+ <!-- Person Construct -->
+ <define name="atomPersonConstruct">
+ <ref name="atomCommonAttributes"/>
+ <interleave>
+ <element name="atom:name">
+ <text/>
+ </element>
+ <optional>
+ <element name="atom:uri">
+ <ref name="atomUri"/>
+ </element>
+ </optional>
+ <optional>
+ <element name="atom:email">
+ <ref name="atomEmailAddress"/>
+ </element>
+ </optional>
+ <zeroOrMore>
+ <ref name="extensionElement"/>
+ </zeroOrMore>
+ </interleave>
+ </define>
+ <!-- Date Construct -->
+ <define name="atomDateConstruct">
+ <ref name="atomCommonAttributes"/>
+ <data type="dateTime"/>
+ </define>
+ <!-- atom:feed -->
+ <define name="atomFeed">
+ <element name="atom:feed">
+ <s:rule context="atom:feed">
+ <s:assert test="atom:author or not(atom:entry[not(atom:author)])">An atom:feed must have an atom:author unless all of its atom:entry children have an atom:author.</s:assert>
+ </s:rule>
+ <ref name="atomCommonAttributes"/>
+ <interleave>
+ <zeroOrMore>
+ <ref name="atomAuthor"/>
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="atomCategory"/>
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="atomContributor"/>
+ </zeroOrMore>
+ <optional>
+ <ref name="atomGenerator"/>
+ </optional>
+ <optional>
+ <ref name="atomIcon"/>
+ </optional>
+ <ref name="atomId"/>
+ <zeroOrMore>
+ <ref name="atomLink"/>
+ </zeroOrMore>
+ <optional>
+ <ref name="atomLogo"/>
+ </optional>
+ <optional>
+ <ref name="atomRights"/>
+ </optional>
+ <optional>
+ <ref name="atomSubtitle"/>
+ </optional>
+ <ref name="atomTitle"/>
+ <ref name="atomUpdated"/>
+ <zeroOrMore>
+ <ref name="extensionElement"/>
+ </zeroOrMore>
+ </interleave>
+ <zeroOrMore>
+ <ref name="atomEntry"/>
+ </zeroOrMore>
+ </element>
+ </define>
+ <!-- atom:entry -->
+ <define name="atomEntry">
+ <element name="atom:entry">
+ <s:rule context="atom:entry">
+ <s:assert test="atom:link[@rel='alternate'] or atom:link[not(@rel)] or atom:content">An atom:entry must have at least one atom:link element with a rel attribute of 'alternate' or an atom:content.</s:assert>
+ </s:rule>
+ <s:rule context="atom:entry">
+ <s:assert test="atom:author or ../atom:author or atom:source/atom:author">An atom:entry must have an atom:author if its feed does not.</s:assert>
+ </s:rule>
+ <ref name="atomCommonAttributes"/>
+ <interleave>
+ <zeroOrMore>
+ <ref name="atomAuthor"/>
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="atomCategory"/>
+ </zeroOrMore>
+ <optional>
+ <ref name="atomContent"/>
+ </optional>
+ <zeroOrMore>
+ <ref name="atomContributor"/>
+ </zeroOrMore>
+ <ref name="atomId"/>
+ <zeroOrMore>
+ <ref name="atomLink"/>
+ </zeroOrMore>
+ <optional>
+ <ref name="atomPublished"/>
+ </optional>
+ <optional>
+ <ref name="atomRights"/>
+ </optional>
+ <optional>
+ <ref name="atomSource"/>
+ </optional>
+ <optional>
+ <ref name="atomSummary"/>
+ </optional>
+ <ref name="atomTitle"/>
+ <ref name="atomUpdated"/>
+ <zeroOrMore>
+ <ref name="extensionElement"/>
+ </zeroOrMore>
+ </interleave>
+ </element>
+ </define>
+ <!-- atom:content -->
+ <define name="atomInlineTextContent">
+ <element name="atom:content">
+ <ref name="atomCommonAttributes"/>
+ <optional>
+ <attribute name="type">
+ <choice>
+ <value>text</value>
+ <value>html</value>
+ </choice>
+ </attribute>
+ </optional>
+ <zeroOrMore>
+ <text/>
+ </zeroOrMore>
+ </element>
+ </define>
+ <define name="atomInlineXHTMLContent">
+ <element name="atom:content">
+ <ref name="atomCommonAttributes"/>
+ <attribute name="type">
+ <value>xhtml</value>
+ </attribute>
+ <ref name="xhtmlDiv"/>
+ </element>
+ </define>
+ <define name="atomInlineOtherContent">
+ <element name="atom:content">
+ <ref name="atomCommonAttributes"/>
+ <optional>
+ <attribute name="type">
+ <ref name="atomMediaType"/>
+ </attribute>
+ </optional>
+ <zeroOrMore>
+ <choice>
+ <text/>
+ <ref name="anyElement"/>
+ </choice>
+ </zeroOrMore>
+ </element>
+ </define>
+ <define name="atomOutOfLineContent">
+ <element name="atom:content">
+ <ref name="atomCommonAttributes"/>
+ <optional>
+ <attribute name="type">
+ <ref name="atomMediaType"/>
+ </attribute>
+ </optional>
+ <attribute name="src">
+ <ref name="atomUri"/>
+ </attribute>
+ <empty/>
+ </element>
+ </define>
+ <define name="atomContent">
+ <choice>
+ <ref name="atomInlineTextContent"/>
+ <ref name="atomInlineXHTMLContent"/>
+ <ref name="atomInlineOtherContent"/>
+ <ref name="atomOutOfLineContent"/>
+ </choice>
+ </define>
+ <!-- atom:author -->
+ <define name="atomAuthor">
+ <element name="atom:author">
+ <ref name="atomPersonConstruct"/>
+ </element>
+ </define>
+ <!-- atom:category -->
+ <define name="atomCategory">
+ <element name="atom:category">
+ <ref name="atomCommonAttributes"/>
+ <attribute name="term"/>
+ <optional>
+ <attribute name="scheme">
+ <ref name="atomUri"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="label"/>
+ </optional>
+ <ref name="undefinedContent"/>
+ </element>
+ </define>
+ <!-- atom:contributor -->
+ <define name="atomContributor">
+ <element name="atom:contributor">
+ <ref name="atomPersonConstruct"/>
+ </element>
+ </define>
+ <!-- atom:generator -->
+ <define name="atomGenerator">
+ <element name="atom:generator">
+ <ref name="atomCommonAttributes"/>
+ <optional>
+ <attribute name="uri">
+ <ref name="atomUri"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="version"/>
+ </optional>
+ <text/>
+ </element>
+ </define>
+ <!-- atom:icon -->
+ <define name="atomIcon">
+ <element name="atom:icon">
+ <ref name="atomCommonAttributes"/>
+ <ref name="atomUri"/>
+ </element>
+ </define>
+ <!-- atom:id -->
+ <define name="atomId">
+ <element name="atom:id">
+ <ref name="atomCommonAttributes"/>
+ <ref name="atomUri"/>
+ </element>
+ </define>
+ <!-- atom:logo -->
+ <define name="atomLogo">
+ <element name="atom:logo">
+ <ref name="atomCommonAttributes"/>
+ <ref name="atomUri"/>
+ </element>
+ </define>
+ <!-- atom:link -->
+ <define name="atomLink">
+ <element name="atom:link">
+ <ref name="atomCommonAttributes"/>
+ <attribute name="href">
+ <ref name="atomUri"/>
+ </attribute>
+ <optional>
+ <attribute name="rel">
+ <choice>
+ <ref name="atomNCName"/>
+ <ref name="atomUri"/>
+ </choice>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="type">
+ <ref name="atomMediaType"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="hreflang">
+ <ref name="atomLanguageTag"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="title"/>
+ </optional>
+ <optional>
+ <attribute name="length"/>
+ </optional>
+ <ref name="undefinedContent"/>
+ </element>
+ </define>
+ <!-- atom:published -->
+ <define name="atomPublished">
+ <element name="atom:published">
+ <ref name="atomDateConstruct"/>
+ </element>
+ </define>
+ <!-- atom:rights -->
+ <define name="atomRights">
+ <element name="atom:rights">
+ <ref name="atomTextConstruct"/>
+ </element>
+ </define>
+ <!-- atom:source -->
+ <define name="atomSource">
+ <element name="atom:source">
+ <ref name="atomCommonAttributes"/>
+ <interleave>
+ <zeroOrMore>
+ <ref name="atomAuthor"/>
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="atomCategory"/>
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="atomContributor"/>
+ </zeroOrMore>
+ <optional>
+ <ref name="atomGenerator"/>
+ </optional>
+ <optional>
+ <ref name="atomIcon"/>
+ </optional>
+ <optional>
+ <ref name="atomId"/>
+ </optional>
+ <zeroOrMore>
+ <ref name="atomLink"/>
+ </zeroOrMore>
+ <optional>
+ <ref name="atomLogo"/>
+ </optional>
+ <optional>
+ <ref name="atomRights"/>
+ </optional>
+ <optional>
+ <ref name="atomSubtitle"/>
+ </optional>
+ <optional>
+ <ref name="atomTitle"/>
+ </optional>
+ <optional>
+ <ref name="atomUpdated"/>
+ </optional>
+ <zeroOrMore>
+ <ref name="extensionElement"/>
+ </zeroOrMore>
+ </interleave>
+ </element>
+ </define>
+ <!-- atom:subtitle -->
+ <define name="atomSubtitle">
+ <element name="atom:subtitle">
+ <ref name="atomTextConstruct"/>
+ </element>
+ </define>
+ <!-- atom:summary -->
+ <define name="atomSummary">
+ <element name="atom:summary">
+ <ref name="atomTextConstruct"/>
+ </element>
+ </define>
+ <!-- atom:title -->
+ <define name="atomTitle">
+ <element name="atom:title">
+ <ref name="atomTextConstruct"/>
+ </element>
+ </define>
+ <!-- atom:updated -->
+ <define name="atomUpdated">
+ <element name="atom:updated">
+ <ref name="atomDateConstruct"/>
+ </element>
+ </define>
+ <!-- Low-level simple types -->
+ <define name="atomNCName">
+ <data type="string">
+ <param name="minLength">1</param>
+ <param name="pattern">[^:]*</param>
+ </data>
+ </define>
+ <!-- Whatever a media type is, it contains at least one slash -->
+ <define name="atomMediaType">
+ <data type="string">
+ <param name="pattern">.+/.+</param>
+ </data>
+ </define>
+ <!-- As defined in RFC 3066 -->
+ <define name="atomLanguageTag">
+ <data type="string">
+ <param name="pattern">[A-Za-z]{1,8}(-[A-Za-z0-9]{1,8})*</param>
+ </data>
+ </define>
+ <!--
+ Unconstrained; it's not entirely clear how IRI fit into
+ xsd:anyURI so let's not try to constrain it here
+ -->
+ <define name="atomUri">
+ <text/>
+ </define>
+ <!-- Whatever an email address is, it contains at least one @ -->
+ <define name="atomEmailAddress">
+ <data type="string">
+ <param name="pattern">.+@.+</param>
+ </data>
+ </define>
+ <!-- Simple Extension -->
+ <define name="simpleExtensionElement">
+ <element>
+ <anyName>
+ <except>
+ <nsName ns="http://www.w3.org/2005/Atom"/>
+ </except>
+ </anyName>
+ <text/>
+ </element>
+ </define>
+ <!-- Structured Extension -->
+ <define name="structuredExtensionElement">
+ <element>
+ <anyName>
+ <except>
+ <nsName ns="http://www.w3.org/2005/Atom"/>
+ </except>
+ </anyName>
+ <choice>
+ <group>
+ <oneOrMore>
+ <attribute>
+ <anyName/>
+ </attribute>
+ </oneOrMore>
+ <zeroOrMore>
+ <choice>
+ <text/>
+ <ref name="anyElement"/>
+ </choice>
+ </zeroOrMore>
+ </group>
+ <group>
+ <zeroOrMore>
+ <attribute>
+ <anyName/>
+ </attribute>
+ </zeroOrMore>
+ <group>
+ <optional>
+ <text/>
+ </optional>
+ <oneOrMore>
+ <ref name="anyElement"/>
+ </oneOrMore>
+ <zeroOrMore>
+ <choice>
+ <text/>
+ <ref name="anyElement"/>
+ </choice>
+ </zeroOrMore>
+ </group>
+ </group>
+ </choice>
+ </element>
+ </define>
+ <!-- Other Extensibility -->
+ <define name="extensionElement">
+ <choice>
+ <ref name="simpleExtensionElement"/>
+ <ref name="structuredExtensionElement"/>
+ </choice>
+ </define>
+ <define name="undefinedAttribute">
+ <attribute>
+ <anyName>
+ <except>
+ <name>xml:base</name>
+ <name>xml:lang</name>
+ <nsName ns=""/>
+ </except>
+ </anyName>
+ </attribute>
+ </define>
+ <define name="undefinedContent">
+ <zeroOrMore>
+ <choice>
+ <text/>
+ <ref name="anyForeignElement"/>
+ </choice>
+ </zeroOrMore>
+ </define>
+ <define name="anyElement">
+ <element>
+ <anyName/>
+ <zeroOrMore>
+ <choice>
+ <attribute>
+ <anyName/>
+ </attribute>
+ <text/>
+ <ref name="anyElement"/>
+ </choice>
+ </zeroOrMore>
+ </element>
+ </define>
+ <define name="anyForeignElement">
+ <element>
+ <anyName>
+ <except>
+ <nsName ns="http://www.w3.org/2005/Atom"/>
+ </except>
+ </anyName>
+ <zeroOrMore>
+ <choice>
+ <attribute>
+ <anyName/>
+ </attribute>
+ <text/>
+ <ref name="anyElement"/>
+ </choice>
+ </zeroOrMore>
+ </element>
+ </define>
+ <!-- XHTML -->
+ <define name="anyXHTML">
+ <element>
+ <nsName ns="http://www.w3.org/1999/xhtml"/>
+ <zeroOrMore>
+ <choice>
+ <attribute>
+ <anyName/>
+ </attribute>
+ <text/>
+ <ref name="anyXHTML"/>
+ </choice>
+ </zeroOrMore>
+ </element>
+ </define>
+ <define name="xhtmlDiv">
+ <element name="xhtml:div">
+ <zeroOrMore>
+ <choice>
+ <attribute>
+ <anyName/>
+ </attribute>
+ <text/>
+ <ref name="anyXHTML"/>
+ </choice>
+ </zeroOrMore>
+ </element>
+ </define>
+</grammar>
diff --git a/nova/api/openstack/schemas/v1.1/extension.rng b/nova/api/openstack/schemas/v1.1/extension.rng
new file mode 100644
index 000000000..336659755
--- /dev/null
+++ b/nova/api/openstack/schemas/v1.1/extension.rng
@@ -0,0 +1,11 @@
+<element name="extension" ns="http://docs.openstack.org/compute/api/v1.1"
+ xmlns="http://relaxng.org/ns/structure/1.0">
+ <attribute name="alias"> <text/> </attribute>
+ <attribute name="name"> <text/> </attribute>
+ <attribute name="namespace"> <text/> </attribute>
+ <attribute name="updated"> <text/> </attribute>
+ <element name="description"> <text/> </element>
+ <zeroOrMore>
+ <externalRef href="../atom-link.rng"/>
+ </zeroOrMore>
+</element>
diff --git a/nova/api/openstack/schemas/v1.1/extensions.rng b/nova/api/openstack/schemas/v1.1/extensions.rng
new file mode 100644
index 000000000..4d8bff646
--- /dev/null
+++ b/nova/api/openstack/schemas/v1.1/extensions.rng
@@ -0,0 +1,6 @@
+<element name="extensions" xmlns="http://relaxng.org/ns/structure/1.0"
+ ns="http://docs.openstack.org/compute/api/v1.1">
+ <zeroOrMore>
+ <externalRef href="extension.rng"/>
+ </zeroOrMore>
+</element>
diff --git a/nova/api/openstack/xmlutil.py b/nova/api/openstack/xmlutil.py
new file mode 100644
index 000000000..97ad90ada
--- /dev/null
+++ b/nova/api/openstack/xmlutil.py
@@ -0,0 +1,37 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 OpenStack LLC.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import os.path
+
+from lxml import etree
+
+from nova import utils
+
+
+XMLNS_V10 = 'http://docs.rackspacecloud.com/servers/api/v1.0'
+XMLNS_V11 = 'http://docs.openstack.org/compute/api/v1.1'
+XMLNS_ATOM = 'http://www.w3.org/2005/Atom'
+
+
+def validate_schema(xml, schema_name):
+ if type(xml) is str:
+ xml = etree.fromstring(xml)
+ schema_path = os.path.join(utils.novadir(),
+ 'nova/api/openstack/schemas/v1.1/%s.rng' % schema_name)
+ schema_doc = etree.parse(schema_path)
+ relaxng = etree.RelaxNG(schema_doc)
+ relaxng.assertValid(xml)