From c74aedee635a67ec0e6a06d61f3d8f047c687c79 Mon Sep 17 00:00:00 2001 From: Attila Fazekas Date: Wed, 11 Sep 2013 13:04:02 +0200 Subject: [PATCH] Add xml support to the floating ip and router Creating xml version for the neutron router and floatingip related operation. The test_floating_ips.py also extended with the XML variant. Change-Id: I5e85cd263828a127ed48db04b19fbf4d145f1d87 --- tempest/api/network/test_floating_ips.py | 10 +- tempest/services/compute/xml/common.py | 18 +++ .../services/network/xml/network_client.py | 111 ++++++++++++++++++ 3 files changed, 136 insertions(+), 3 deletions(-) diff --git a/tempest/api/network/test_floating_ips.py b/tempest/api/network/test_floating_ips.py index 017864fcbe..ca2c879526 100644 --- a/tempest/api/network/test_floating_ips.py +++ b/tempest/api/network/test_floating_ips.py @@ -20,7 +20,7 @@ from tempest.common.utils.data_utils import rand_name from tempest.test import attr -class FloatingIPTest(base.BaseNetworkTest): +class FloatingIPTestJSON(base.BaseNetworkTest): _interface = 'json' """ @@ -41,7 +41,7 @@ class FloatingIPTest(base.BaseNetworkTest): @classmethod def setUpClass(cls): - super(FloatingIPTest, cls).setUpClass() + super(FloatingIPTestJSON, cls).setUpClass() cls.ext_net_id = cls.config.network.public_network_id # Create network, subnet, router and add interface @@ -67,7 +67,7 @@ class FloatingIPTest(base.BaseNetworkTest): for i in range(2): cls.client.delete_port(cls.port[i]['id']) cls.client.delete_router(cls.router['id']) - super(FloatingIPTest, cls).tearDownClass() + super(FloatingIPTestJSON, cls).tearDownClass() def _delete_floating_ip(self, floating_ip_id): # Deletes a floating IP and verifies if it is deleted or not @@ -133,3 +133,7 @@ class FloatingIPTest(base.BaseNetworkTest): self.assertIsNone(update_floating_ip['port_id']) self.assertIsNone(update_floating_ip['fixed_ip_address']) self.assertIsNone(update_floating_ip['router_id']) + + +class FloatingIPTestXML(FloatingIPTestJSON): + _interface = 'xml' diff --git a/tempest/services/compute/xml/common.py b/tempest/services/compute/xml/common.py index cb24917c9d..84b56c28f1 100644 --- a/tempest/services/compute/xml/common.py +++ b/tempest/services/compute/xml/common.py @@ -15,6 +15,8 @@ # License for the specific language governing permissions and limitations # under the License. +import collections + XMLNS_11 = "http://docs.openstack.org/compute/api/v1.1" @@ -110,3 +112,19 @@ def xml_to_json(node): ns, tag = tag.split("}", 1) json[tag] = xml_to_json(child) return json + + +def deep_dict_to_xml(dest, source): + """Populates the ``dest`` xml element with the ``source`` ``Mapping`` + elements, if the source Mapping's value is also a ``Mapping`` + they will be recursively added as a child elements. + :param source: A python ``Mapping`` (dict) + :param dest: XML child element will be added to the ``dest`` + """ + for element, content in source.iteritems(): + if isinstance(content, collections.Mapping): + xml_element = Element(element) + deep_dict_to_xml(xml_element, content) + dest.append(xml_element) + else: + dest.append(Element(element, content)) diff --git a/tempest/services/network/xml/network_client.py b/tempest/services/network/xml/network_client.py index 1523ed04cd..cf8154a7e3 100755 --- a/tempest/services/network/xml/network_client.py +++ b/tempest/services/network/xml/network_client.py @@ -16,6 +16,7 @@ from lxml import etree import xml.etree.ElementTree as ET from tempest.common.rest_client import RestClientXML +from tempest.services.compute.xml.common import deep_dict_to_xml from tempest.services.compute.xml.common import Document from tempest.services.compute.xml.common import Element from tempest.services.compute.xml.common import xml_to_json @@ -441,6 +442,111 @@ class NetworkClientXML(RestClientXML): body = _root_tag_fetcher_and_xml_to_json_parse(body) return resp, body + def create_router(self, name, **kwargs): + uri = '%s/routers' % (self.uri_prefix) + router = Element("router") + router.append(Element("name", name)) + deep_dict_to_xml(router, kwargs) + resp, body = self.post(uri, str(Document(router)), self.headers) + body = _root_tag_fetcher_and_xml_to_json_parse(body) + return resp, body + + def delete_router(self, router_id): + uri = '%s/routers/%s' % (self.uri_prefix, router_id) + resp, body = self.delete(uri, self.headers) + return resp, body + + def show_router(self, router_id): + uri = '%s/routers/%s' % (self.uri_prefix, router_id) + resp, body = self.get(uri, self.headers) + body = _root_tag_fetcher_and_xml_to_json_parse(body) + return resp, body + + def update_router(self, router_id, **kwargs): + uri = '%s/routers/%s' % (self.uri_prefix, router_id) + router = Element("router") + for element, content in kwargs.iteritems(): + router.append(Element(element, content)) + resp, body = self.put(uri, str(Document(router)), self.headers) + body = _root_tag_fetcher_and_xml_to_json_parse(body) + return resp, body + + def add_router_interface_with_subnet_id(self, router_id, subnet_id): + uri = '%s/routers/%s/add_router_interface' % (self.uri_prefix, + router_id) + subnet = Element("subnet_id", subnet_id) + resp, body = self.put(uri, str(Document(subnet)), self.headers) + body = _root_tag_fetcher_and_xml_to_json_parse(body) + return resp, body + + def add_router_interface_with_port_id(self, router_id, port_id): + uri = '%s/routers/%s/add_router_interface' % (self.uri_prefix, + router_id) + port = Element("port_id", port_id) + resp, body = self.put(uri, str(Document(port)), self.headers) + body = _root_tag_fetcher_and_xml_to_json_parse(body) + return resp, body + + def remove_router_interface_with_subnet_id(self, router_id, subnet_id): + uri = '%s/routers/%s/remove_router_interface' % (self.uri_prefix, + router_id) + subnet = Element("subnet_id", subnet_id) + resp, body = self.put(uri, str(Document(subnet)), self.headers) + body = _root_tag_fetcher_and_xml_to_json_parse(body) + return resp, body + + def remove_router_interface_with_port_id(self, router_id, port_id): + uri = '%s/routers/%s/remove_router_interface' % (self.uri_prefix, + router_id) + port = Element("port_id", port_id) + resp, body = self.put(uri, str(Document(port)), self.headers) + body = _root_tag_fetcher_and_xml_to_json_parse(body) + return resp, body + + def create_floating_ip(self, ext_network_id, **kwargs): + uri = '%s/floatingips' % (self.uri_prefix) + floatingip = Element('floatingip') + floatingip.append(Element("floating_network_id", ext_network_id)) + for element, content in kwargs.iteritems(): + floatingip.append(Element(element, content)) + resp, body = self.post(uri, str(Document(floatingip)), self.headers) + body = _root_tag_fetcher_and_xml_to_json_parse(body) + return resp, body + + def show_floating_ip(self, floating_ip_id): + uri = '%s/floatingips/%s' % (self.uri_prefix, floating_ip_id) + resp, body = self.get(uri, self.headers) + body = _root_tag_fetcher_and_xml_to_json_parse(body) + return resp, body + + def list_floating_ips(self): + uri = '%s/floatingips' % (self.uri_prefix) + resp, body = self.get(uri, self.headers) + floatingips = self._parse_array(etree.fromstring(body)) + floatingips = {"floatingips": floatingips} + return resp, floatingips + + def delete_floating_ip(self, floating_ip_id): + uri = '%s/floatingips/%s' % (self.uri_prefix, floating_ip_id) + resp, body = self.delete(uri, self.headers) + return resp, body + + def update_floating_ip(self, floating_ip_id, **kwargs): + uri = '%s/floatingips/%s' % (self.uri_prefix, floating_ip_id) + floatingip = Element('floatingip') + floatingip.add_attr('xmlns:xsi', + 'http://www.w3.org/2001/XMLSchema-instance') + for element, content in kwargs.iteritems(): + if content is None: + xml_elem = Element(element) + xml_elem.add_attr("xsi:nil", "true") + floatingip.append(xml_elem) + else: + floatingip.append(Element(element, content)) + resp, body = self.put(uri, str(Document(floatingip)), self.headers) + body = _root_tag_fetcher_and_xml_to_json_parse(body) + return resp, body + def _root_tag_fetcher_and_xml_to_json_parse(xml_returned_body): body = ET.fromstring(xml_returned_body) @@ -448,5 +554,10 @@ def _root_tag_fetcher_and_xml_to_json_parse(xml_returned_body): if root_tag.startswith("{"): ns, root_tag = root_tag.split("}", 1) body = xml_to_json(etree.fromstring(xml_returned_body)) + nil = '{http://www.w3.org/2001/XMLSchema-instance}nil' + for key, val in body.iteritems(): + if isinstance(val, dict): + if (nil in val and val[nil] == 'true'): + body[key] = None body = {root_tag: body} return body