Merge "Addition of XML support to test_quotas.py"
diff --git a/tempest/clients.py b/tempest/clients.py
index 29e83bf..7a7ea13 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -32,7 +32,7 @@
from tempest.services.compute.json.security_groups_client import \
SecurityGroupsClientJSON
from tempest.services.compute.json.keypairs_client import KeyPairsClientJSON
-from tempest.services.compute.json.quotas_client import QuotasClient
+from tempest.services.compute.json.quotas_client import QuotasClientJSON
from tempest.services.compute.json.volumes_extensions_client import \
VolumesExtensionsClientJSON
from tempest.services.compute.json.console_output_client import \
@@ -44,6 +44,7 @@
from tempest.services.compute.xml.images_client import ImagesClientXML
from tempest.services.compute.xml.keypairs_client import KeyPairsClientXML
from tempest.services.compute.xml.limits_client import LimitsClientXML
+from tempest.services.compute.xml.quotas_client import QuotasClientXML
from tempest.services.compute.xml.security_groups_client \
import SecurityGroupsClientXML
from tempest.services.compute.xml.servers_client import ServersClientXML
@@ -79,6 +80,11 @@
"xml": KeyPairsClientXML,
}
+QUOTAS_CLIENTS = {
+ "json": QuotasClientJSON,
+ "xml": QuotasClientXML,
+}
+
SERVERS_CLIENTS = {
"json": ServersClientJSON,
"xml": ServersClientXML,
@@ -180,6 +186,7 @@
self.limits_client = LIMITS_CLIENTS[interface](*client_args)
self.images_client = IMAGES_CLIENTS[interface](*client_args)
self.keypairs_client = KEYPAIRS_CLIENTS[interface](*client_args)
+ self.quotas_client = QUOTAS_CLIENTS[interface](*client_args)
self.flavors_client = FLAVORS_CLIENTS[interface](*client_args)
ext_cli = EXTENSIONS_CLIENTS[interface](*client_args)
self.extensions_client = ext_cli
@@ -196,7 +203,6 @@
except KeyError:
msg = "Unsupported interface type `%s'" % interface
raise exceptions.InvalidConfiguration(msg)
- self.quotas_client = QuotasClient(*client_args)
self.network_client = NetworkClient(*client_args)
self.account_client = AccountClient(*client_args)
self.container_client = ContainerClient(*client_args)
diff --git a/tempest/manager.py b/tempest/manager.py
index 4137ec3..cb1e52d 100644
--- a/tempest/manager.py
+++ b/tempest/manager.py
@@ -55,7 +55,7 @@
VolumesExtensionsClient = volumes_extensions_client.VolumesExtensionsClientJSON
VolumesClient = volumes_client.VolumesClientJSON
ConsoleOutputsClient = console_output_client.ConsoleOutputsClientJSON
-QuotasClient = quotas_client.QuotasClient
+QuotasClient = quotas_client.QuotasClientJSON
LOG = logging.getLogger(__name__)
diff --git a/tempest/services/compute/admin/json/quotas_client.py b/tempest/services/compute/admin/json/quotas_client.py
index 625d4d4..0a4bd72 100644
--- a/tempest/services/compute/admin/json/quotas_client.py
+++ b/tempest/services/compute/admin/json/quotas_client.py
@@ -17,14 +17,14 @@
import json
-from tempest.services.compute.json.quotas_client import QuotasClient
+from tempest.services.compute.json.quotas_client import QuotasClientJSON
-class AdminQuotasClient(QuotasClient):
+class AdminQuotasClientJSON(QuotasClientJSON):
def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(AdminQuotasClient, self).__init__(config, username, password,
- auth_url, tenant_name)
+ super(AdminQuotasClientJSON, self).__init__(config, username, password,
+ auth_url, tenant_name)
def update_quota_set(self, tenant_id, injected_file_content_bytes=None,
metadata_items=None, ram=None, floating_ips=None,
diff --git a/tempest/services/compute/admin/xml/__init__.py b/tempest/services/compute/admin/xml/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/services/compute/admin/xml/__init__.py
diff --git a/tempest/services/compute/admin/xml/quotas_client.py b/tempest/services/compute/admin/xml/quotas_client.py
new file mode 100644
index 0000000..d567a9c
--- /dev/null
+++ b/tempest/services/compute/admin/xml/quotas_client.py
@@ -0,0 +1,88 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2012 NTT Data
+# 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 urllib
+
+from lxml import etree
+
+from tempest.common.rest_client import RestClientXML
+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
+from tempest.services.compute.xml.common import XMLNS_11
+from tempest.services.compute.xml.quotas_client import QuotasClientXML
+
+
+class AdminQuotasClientXML(QuotasClientXML):
+
+ def __init__(self, config, username, password, auth_url, tenant_name=None):
+ super(AdminQuotasClientXML, self).__init__(config, username, password,
+ auth_url, tenant_name)
+
+ def update_quota_set(self, tenant_id, injected_file_content_bytes=None,
+ metadata_items=None, ram=None, floating_ips=None,
+ key_pairs=None, instances=None,
+ security_group_rules=None, injected_files=None,
+ cores=None, injected_file_path_bytes=None,
+ security_groups=None):
+ """
+ Updates the tenant's quota limits for one or more resources
+ """
+ post_body = Element("quota_set",
+ xmlns=XMLNS_11)
+
+ if injected_file_content_bytes is not None:
+ post_body.add_attr('injected_file_content_bytes',
+ injected_file_content_bytes)
+
+ if metadata_items is not None:
+ post_body.add_attr('metadata_items', metadata_items)
+
+ if ram is not None:
+ post_body.add_attr('ram', ram)
+
+ if floating_ips is not None:
+ post_body.add_attr('floating_ips', floating_ips)
+
+ if key_pairs is not None:
+ post_body.add_attr('key_pairs', key_pairs)
+
+ if instances is not None:
+ post_body.add_attr('instances', instances)
+
+ if security_group_rules is not None:
+ post_body.add_attr('security_group_rules', security_group_rules)
+
+ if injected_files is not None:
+ post_body.add_attr('injected_files', injected_files)
+
+ if cores is not None:
+ post_body.add_attr('cores', cores)
+
+ if injected_file_path_bytes is not None:
+ post_body.add_attr('injected_file_path_bytes',
+ injected_file_path_bytes)
+
+ if security_groups is not None:
+ post_body.add_attr('security_groups', security_groups)
+
+ resp, body = self.put('os-quota-sets/%s' % str(tenant_id),
+ str(Document(post_body)),
+ self.headers)
+ body = xml_to_json(etree.fromstring(body))
+ body = self._format_quota(body)
+ return resp, body
diff --git a/tempest/services/compute/json/quotas_client.py b/tempest/services/compute/json/quotas_client.py
index 543b015..a95ff1c 100644
--- a/tempest/services/compute/json/quotas_client.py
+++ b/tempest/services/compute/json/quotas_client.py
@@ -20,11 +20,11 @@
from tempest.common.rest_client import RestClient
-class QuotasClient(RestClient):
+class QuotasClientJSON(RestClient):
def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(QuotasClient, self).__init__(config, username, password,
- auth_url, tenant_name)
+ super(QuotasClientJSON, self).__init__(config, username, password,
+ auth_url, tenant_name)
self.service = self.config.compute.catalog_type
def get_quota_set(self, tenant_id):
diff --git a/tempest/services/compute/xml/quotas_client.py b/tempest/services/compute/xml/quotas_client.py
new file mode 100644
index 0000000..8978214
--- /dev/null
+++ b/tempest/services/compute/xml/quotas_client.py
@@ -0,0 +1,58 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2012 NTT Data
+# 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 urllib
+
+from lxml import etree
+
+from tempest.common.rest_client import RestClientXML
+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
+from tempest.services.compute.xml.common import XMLNS_11
+
+
+class QuotasClientXML(RestClientXML):
+
+ def __init__(self, config, username, password, auth_url, tenant_name=None):
+ super(QuotasClientXML, self).__init__(config, username, password,
+ auth_url, tenant_name)
+ self.service = self.config.compute.catalog_type
+
+ def _format_quota(self, q):
+ quota = {}
+ for k, v in q.items():
+ try:
+ v = int(v)
+ except ValueError:
+ pass
+
+ quota[k] = v
+
+ return quota
+
+ def _parse_array(self, node):
+ return [self._format_quota(xml_to_json(x)) for x in node]
+
+ def get_quota_set(self, tenant_id):
+ """List the quota set for a tenant."""
+
+ url = 'os-quota-sets/%s' % str(tenant_id)
+ resp, body = self.get(url, self.headers)
+ body = xml_to_json(etree.fromstring(body))
+ body = self._format_quota(body)
+ return resp, body
diff --git a/tempest/tests/compute/admin/test_quotas.py b/tempest/tests/compute/admin/test_quotas.py
index 6a7a5ea..b2b515a 100644
--- a/tempest/tests/compute/admin/test_quotas.py
+++ b/tempest/tests/compute/admin/test_quotas.py
@@ -18,23 +18,21 @@
from nose.plugins.attrib import attr
from tempest import exceptions
-from tempest.services.compute.admin.json import quotas_client as adm_quotas
-from tempest.tests.compute.base import BaseComputeTest
+from tempest.services.compute.admin.json \
+ import quotas_client as adm_quotas_json
+from tempest.services.compute.admin.xml import quotas_client as adm_quotas_xml
+from tempest.tests import compute
+from tempest.tests.compute import base
-class QuotasTest(BaseComputeTest):
+class QuotasAdminTestBase(object):
@classmethod
def setUpClass(cls):
- super(QuotasTest, cls).setUpClass()
- c_adm_user = cls.config.compute_admin.username
- c_adm_pass = cls.config.compute_admin.password
- c_adm_tenant = cls.config.compute_admin.tenant_name
- auth_url = cls.config.identity.uri
-
- cls.adm_client = adm_quotas.AdminQuotasClient(cls.config, c_adm_user,
- c_adm_pass, auth_url,
- c_adm_tenant)
+ cls.c_adm_user = cls.config.compute_admin.username
+ cls.c_adm_pass = cls.config.compute_admin.password
+ cls.c_adm_tenant = cls.config.compute_admin.tenant_name
+ cls.auth_url = cls.config.identity.uri
cls.client = cls.os.quotas_client
cls.identity_admin_client = cls._get_identity_admin_client()
resp, tenants = cls.identity_admin_client.list_tenants()
@@ -63,7 +61,6 @@
cls.servers_client.delete_server(server['id'])
except exceptions.NotFound:
continue
- super(QuotasTest, cls).tearDownClass()
@attr(type='smoke')
def test_get_default_quotas(self):
@@ -155,3 +152,43 @@
finally:
self.adm_client.update_quota_set(self.demo_tenant_id,
ram=default_mem_quota)
+
+
+class QuotasAdminTestJSON(QuotasAdminTestBase, base.BaseComputeAdminTestJSON,
+ base.BaseComputeTest):
+
+ @classmethod
+ def setUpClass(cls):
+ base.BaseComputeAdminTestJSON.setUpClass()
+ base.BaseComputeTest.setUpClass()
+ super(QuotasAdminTestJSON, cls).setUpClass()
+
+ cls.adm_client = adm_quotas_json.AdminQuotasClientJSON(
+ cls.config, cls.c_adm_user, cls.c_adm_pass,
+ cls.auth_url, cls.c_adm_tenant)
+
+ @classmethod
+ def tearDownClass(cls):
+ super(QuotasAdminTestJSON, cls).tearDownClass()
+ base.BaseComputeTest.tearDownClass()
+
+
+class QuotasAdminTestXML(QuotasAdminTestBase, base.BaseComputeAdminTestXML,
+ base.BaseComputeTest):
+
+ @classmethod
+ def setUpClass(cls):
+ base.BaseComputeAdminTestXML.setUpClass()
+ base.BaseComputeTest.setUpClass()
+ super(QuotasAdminTestXML, cls).setUpClass()
+
+ cls.adm_client = adm_quotas_xml.AdminQuotasClientXML(cls.config,
+ cls.c_adm_user,
+ cls.c_adm_pass,
+ cls.auth_url,
+ cls.c_adm_tenant)
+
+ @classmethod
+ def tearDownClass(cls):
+ super(QuotasAdminTestXML, cls).tearDownClass()
+ base.BaseComputeTest.tearDownClass()
diff --git a/tempest/tests/compute/test_quotas.py b/tempest/tests/compute/test_quotas.py
index 3dc2515..9306351 100644
--- a/tempest/tests/compute/test_quotas.py
+++ b/tempest/tests/compute/test_quotas.py
@@ -17,14 +17,13 @@
from nose.plugins.attrib import attr
-from tempest.tests.compute.base import BaseComputeTest
+from tempest.tests.compute import base
-class QuotasTest(BaseComputeTest):
+class QuotasTestBase(object):
@classmethod
def setUpClass(cls):
- super(QuotasTest, cls).setUpClass()
cls.client = cls.quotas_client
cls.admin_client = cls._get_identity_admin_client()
resp, tenants = cls.admin_client.list_tenants()
@@ -47,3 +46,19 @@
self.assertSequenceEqual(expected_quota_set, quota_set)
except Exception:
self.fail("Quota set for tenant did not have default limits")
+
+
+class QuotasTestJSON(QuotasTestBase, base.BaseComputeTestJSON):
+
+ @classmethod
+ def setUpClass(cls):
+ base.BaseComputeTestJSON.setUpClass()
+ super(QuotasTestJSON, cls).setUpClass()
+
+
+class QuotasTestXML(QuotasTestBase, base.BaseComputeTestXML):
+
+ @classmethod
+ def setUpClass(cls):
+ base.BaseComputeTestXML.setUpClass()
+ super(QuotasTestXML, cls).setUpClass()