Xml Support for Image Test scripts
Added/Modified required support functions in images_client.py
XML interface script.Added required logic to below scripts
inorder to support both JSON and XML interfaces
* tests/compute/images/test_image_metadata.py
* tests/compute/images/test_list_image_filters.py
* tests/compute/images/test_list_images.py
* tests/compute/test_authorization.py
Change-Id: Ibcce0d81024b46c1b031bc348ca8e8d62e005d8d
Implements: blueprint add-xml-support
diff --git a/tempest/services/compute/xml/images_client.py b/tempest/services/compute/xml/images_client.py
index 3b01efb..27bb979 100644
--- a/tempest/services/compute/xml/images_client.py
+++ b/tempest/services/compute/xml/images_client.py
@@ -77,6 +77,19 @@
data['images'].append(self._parse_image(image))
return data
+ def _parse_key_value(self, node):
+ """Parse <foo key='key'>value</foo> data into {'key': 'value'}."""
+ data = {}
+ for node in node.getchildren():
+ data[node.get('key')] = node.text
+ return data
+
+ def _parse_metadata(self, node):
+ """Parse the response body without children."""
+ data = {}
+ data[node.get('key')] = node.text
+ return data
+
def create_image(self, server_id, name, meta=None):
"""Creates an image of the original server."""
post_body = Element('createImage', name=name)
@@ -153,51 +166,53 @@
if int(time.time()) - start >= self.build_timeout:
raise exceptions.TimeoutException
+ def _metadata_body(self, meta):
+ post_body = Element('metadata')
+ for k, v in meta.items():
+ data = Element('meta', key=k)
+ data.append(Text(v))
+ post_body.append(data)
+ return post_body
+
def list_image_metadata(self, image_id):
"""Lists all metadata items for an image."""
resp, body = self.get("images/%s/metadata" % str(image_id),
self.headers)
- body = xml_to_json(etree.fromstring(body))
- return resp, body['metadata']
-
- def _metadata_body(image_id, meta):
- post_body = Document('metadata')
- for k, v in meta:
- text = Text(v)
- metadata = Element('meta', text, key=k)
- post_body.append(metadata)
- return post_body
+ body = self._parse_key_value(etree.fromstring(body))
+ return resp, body
def set_image_metadata(self, image_id, meta):
"""Sets the metadata for an image."""
- post_body = self._metadata_body(image_id, meta)
- resp, body = self.put('images/%s/metadata' % str(image_id),
- post_body, self.headers)
- body = xml_to_json(etree.fromstring(body))
- return resp, body['metadata']
+ post_body = self._metadata_body(meta)
+ resp, body = self.put('images/%s/metadata' % image_id,
+ str(Document(post_body)), self.headers)
+ body = self._parse_key_value(etree.fromstring(body))
+ return resp, body
def update_image_metadata(self, image_id, meta):
"""Updates the metadata for an image."""
- post_body = self._metadata_body(image_id, meta)
+ post_body = self._metadata_body(meta)
resp, body = self.post('images/%s/metadata' % str(image_id),
- post_body, self.headers)
- body = xml_to_json(etree.fromstring(body))
- return resp, body['metadata']
+ str(Document(post_body)), self.headers)
+ body = self._parse_key_value(etree.fromstring(body))
+ return resp, body
def get_image_metadata_item(self, image_id, key):
"""Returns the value for a specific image metadata key."""
resp, body = self.get("images/%s/metadata/%s.xml" %
(str(image_id), key), self.headers)
- body = xml_to_json(etree.fromstring(body))
- return resp, body['meta']
+ body = self._parse_metadata(etree.fromstring(body))
+ return resp, body
def set_image_metadata_item(self, image_id, key, meta):
"""Sets the value for a specific image metadata key."""
- post_body = Document('meta', Text(meta), key=key)
- resp, body = self.post('images/%s/metadata/%s' % (str(image_id), key),
- post_body, self.headers)
+ for k, v in meta.items():
+ post_body = Element('meta', key=key)
+ post_body.append(Text(v))
+ resp, body = self.put('images/%s/metadata/%s' % (str(image_id), key),
+ str(Document(post_body)), self.headers)
body = xml_to_json(etree.fromstring(body))
- return resp, body['meta']
+ return resp, body
def update_image_metadata_item(self, image_id, key, meta):
"""Sets the value for a specific image metadata key."""
@@ -209,6 +224,5 @@
def delete_image_metadata_item(self, image_id, key):
"""Deletes a single image metadata key/value pair."""
- resp, body = self.delete("images/%s/metadata/%s" % (str(image_id), key,
- self.headers))
- return resp, body
+ return self.delete("images/%s/metadata/%s" % (str(image_id), key),
+ self.headers)
diff --git a/tempest/tests/compute/images/test_image_metadata.py b/tempest/tests/compute/images/test_image_metadata.py
index 918075c..5d6439b 100644
--- a/tempest/tests/compute/images/test_image_metadata.py
+++ b/tempest/tests/compute/images/test_image_metadata.py
@@ -21,12 +21,12 @@
from tempest.tests.compute import base
-class ImagesMetadataTest(base.BaseComputeTest):
+class ImagesMetadataTestJSON(base.BaseComputeTest):
_interface = 'json'
@classmethod
def setUpClass(cls):
- super(ImagesMetadataTest, cls).setUpClass()
+ super(ImagesMetadataTestJSON, cls).setUpClass()
cls.servers_client = cls.servers_client
cls.client = cls.images_client
@@ -44,10 +44,10 @@
@classmethod
def tearDownClass(cls):
cls.client.delete_image(cls.image_id)
- super(ImagesMetadataTest, cls).tearDownClass()
+ super(ImagesMetadataTestJSON, cls).tearDownClass()
def setUp(self):
- super(ImagesMetadataTest, self).setUp()
+ super(ImagesMetadataTestJSON, self).setUp()
meta = {'key1': 'value1', 'key2': 'value2'}
resp, _ = self.client.set_image_metadata(self.image_id, meta)
self.assertEqual(resp.status, 200)
@@ -143,3 +143,7 @@
# item from nonexistant image
self.assertRaises(exceptions.NotFound,
self.client.delete_image_metadata_item, 999, 'key1')
+
+
+class ImagesMetadataTestXML(ImagesMetadataTestJSON):
+ _interface = 'xml'
diff --git a/tempest/tests/compute/images/test_list_image_filters.py b/tempest/tests/compute/images/test_list_image_filters.py
index 472f7fb..e668aca 100644
--- a/tempest/tests/compute/images/test_list_image_filters.py
+++ b/tempest/tests/compute/images/test_list_image_filters.py
@@ -22,12 +22,12 @@
from tempest.tests.compute import base
-class ListImageFiltersTest(base.BaseComputeTest):
+class ListImageFiltersTestJSON(base.BaseComputeTest):
_interface = 'json'
@classmethod
def setUpClass(cls):
- super(ListImageFiltersTest, cls).setUpClass()
+ super(ListImageFiltersTestJSON, cls).setUpClass()
cls.client = cls.images_client
resp, cls.server1 = cls.create_server()
@@ -65,7 +65,7 @@
cls.client.delete_image(cls.image1_id)
cls.client.delete_image(cls.image2_id)
cls.client.delete_image(cls.image3_id)
- super(ListImageFiltersTest, cls).tearDownClass()
+ super(ListImageFiltersTestJSON, cls).tearDownClass()
@attr(type='negative')
def test_get_image_not_existing(self):
@@ -140,7 +140,9 @@
# Verify only the expected number of results are returned
params = {'limit': '1'}
resp, images = self.client.list_images(params)
- self.assertEqual(1, len(images))
+ #when _interface='xml', one element for images_links in images
+ #ref: Question #224349
+ self.assertEqual(1, len([x for x in images if 'id' in x]))
@attr(type='positive')
def test_list_images_filter_by_changes_since(self):
@@ -226,3 +228,7 @@
def test_get_nonexistant_image(self):
# Negative test: GET on non existant image should fail
self.assertRaises(exceptions.NotFound, self.client.get_image, 999)
+
+
+class ListImageFiltersTestXML(ListImageFiltersTestJSON):
+ _interface = 'xml'
diff --git a/tempest/tests/compute/images/test_list_images.py b/tempest/tests/compute/images/test_list_images.py
index d583a95..ec9e7bc 100644
--- a/tempest/tests/compute/images/test_list_images.py
+++ b/tempest/tests/compute/images/test_list_images.py
@@ -19,17 +19,17 @@
from tempest.tests.compute import base
-class ListImagesTest(base.BaseComputeTest):
+class ListImagesTestJSON(base.BaseComputeTest):
_interface = 'json'
@classmethod
def setUpClass(cls):
- super(ListImagesTest, cls).setUpClass()
+ super(ListImagesTestJSON, cls).setUpClass()
cls.client = cls.images_client
@classmethod
def tearDownClass(cls):
- super(ListImagesTest, cls).tearDownClass()
+ super(ListImagesTestJSON, cls).tearDownClass()
@attr(type='smoke')
def test_get_image(self):
@@ -50,3 +50,7 @@
resp, images = self.client.list_images_with_detail()
found = any([i for i in images if i['id'] == self.image_ref])
self.assertTrue(found)
+
+
+class ListImagesTestXML(ListImagesTestJSON):
+ _interface = 'xml'
diff --git a/tempest/tests/compute/test_authorization.py b/tempest/tests/compute/test_authorization.py
index 4ca197a..e7dfaa8 100644
--- a/tempest/tests/compute/test_authorization.py
+++ b/tempest/tests/compute/test_authorization.py
@@ -25,7 +25,7 @@
from tempest.tests.compute import base
-class AuthorizationTest(base.BaseComputeTest):
+class AuthorizationTestJSON(base.BaseComputeTest):
_interface = 'json'
@classmethod
@@ -34,7 +34,7 @@
msg = "Need >1 user"
raise cls.skipException(msg)
- super(AuthorizationTest, cls).setUpClass()
+ super(AuthorizationTestJSON, cls).setUpClass()
cls.client = cls.os.servers_client
cls.images_client = cls.os.images_client
@@ -73,18 +73,15 @@
name = rand_name('security')
description = rand_name('description')
- resp, cls.security_group = \
- cls.security_client.create_security_group(name, description)
+ resp, cls.security_group = cls.security_client.create_security_group(
+ name, description)
parent_group_id = cls.security_group['id']
ip_protocol = 'tcp'
from_port = 22
to_port = 22
- resp, cls.rule =\
- cls.security_client.create_security_group_rule(
- parent_group_id,
- ip_protocol, from_port,
- to_port)
+ resp, cls.rule = cls.security_client.create_security_group_rule(
+ parent_group_id, ip_protocol, from_port, to_port)
@classmethod
def tearDownClass(cls):
@@ -92,7 +89,7 @@
cls.images_client.delete_image(cls.image['id'])
cls.keypairs_client.delete_keypair(cls.keypairname)
cls.security_client.delete_security_group(cls.security_group['id'])
- super(AuthorizationTest, cls).tearDownClass()
+ super(AuthorizationTestJSON, cls).tearDownClass()
def test_get_server_for_alt_account_fails(self):
# A GET request for a server on another user's account should fail
@@ -280,7 +277,7 @@
self.alt_security_client.base_url = self.saved_base_url
if resp['status'] is not None:
self.alt_security_client.delete_security_group_rule(
- body['id']) # BUG
+ body['id']) # BUG
self.fail("Create security group rule request should not "
"happen if the tenant id does not match the"
" current user")
@@ -354,3 +351,7 @@
self.assertRaises(exceptions.NotFound,
self.alt_client.get_console_output,
self.server['id'], 10)
+
+
+class AuthorizationTestXML(AuthorizationTestJSON):
+ _interface = 'xml'