Merge "Remove unused exceptions"
diff --git a/tempest/api/database/base.py b/tempest/api/database/base.py
index c9f16ca..dd4c684 100644
--- a/tempest/api/database/base.py
+++ b/tempest/api/database/base.py
@@ -41,4 +41,5 @@
         cls.os = os
         cls.database_flavors_client = cls.os.database_flavors_client
         cls.os_flavors_client = cls.os.flavors_client
+        cls.database_limits_client = cls.os.database_limits_client
         cls.database_versions_client = cls.os.database_versions_client
diff --git a/tempest/api/database/limits/__init__.py b/tempest/api/database/limits/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api/database/limits/__init__.py
diff --git a/tempest/api/database/limits/test_limits.py b/tempest/api/database/limits/test_limits.py
new file mode 100644
index 0000000..30d0a77
--- /dev/null
+++ b/tempest/api/database/limits/test_limits.py
@@ -0,0 +1,45 @@
+# Copyright 2014 OpenStack Foundation
+# 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.
+
+from tempest.api.database import base
+from tempest import test
+
+
+class DatabaseLimitsTest(base.BaseDatabaseTest):
+    _interface = 'json'
+
+    @classmethod
+    def resource_setup(cls):
+        super(DatabaseLimitsTest, cls).resource_setup()
+        cls.client = cls.database_limits_client
+
+    @test.attr(type='smoke')
+    def test_absolute_limits(self):
+        # Test to verify if all absolute limit paramaters are
+        # present when verb is ABSOLUTE
+        _, limits = self.client.list_db_limits()
+        expected_abs_limits = ['max_backups', 'max_volumes',
+                               'max_instances', 'verb']
+        absolute_limit = [l for l in limits
+                          if l['verb'] == 'ABSOLUTE']
+        self.assertEqual(1, len(absolute_limit), "One ABSOLUTE limit "
+                         "verb is allowed. Fetched %s"
+                         % len(absolute_limit))
+        actual_abs_limits = absolute_limit[0].keys()
+        missing_abs_limit = set(expected_abs_limits) - set(actual_abs_limits)
+        self.assertEmpty(missing_abs_limit,
+                         "Failed to find the following absolute limit(s)"
+                         " in a fetched list: %s" %
+                         ', '.join(str(a) for a in missing_abs_limit))
diff --git a/tempest/api/identity/admin/v3/test_groups.py b/tempest/api/identity/admin/v3/test_groups.py
index 64dba7d..d8c7063 100644
--- a/tempest/api/identity/admin/v3/test_groups.py
+++ b/tempest/api/identity/admin/v3/test_groups.py
@@ -91,3 +91,22 @@
         user_groups = self.client.list_user_groups(user['id'])
         self.assertEqual(sorted(groups), sorted(user_groups))
         self.assertEqual(2, len(user_groups))
+
+    @test.attr(type='smoke')
+    def test_list_groups(self):
+        # Test to list groups
+        group_ids = list()
+        fetched_ids = list()
+        for _ in range(3):
+            name = data_utils.rand_name('Group')
+            description = data_utils.rand_name('Description')
+            group = self.client.create_group(name,
+                                             description=description)
+            self.addCleanup(self.client.delete_group, group['id'])
+            group_ids.append(group['id'])
+        # List and Verify Groups
+        body = self.client.list_groups()
+        for g in body:
+            fetched_ids.append(g['id'])
+        missing_groups = [g for g in group_ids if g not in fetched_ids]
+        self.assertEqual([], missing_groups)
diff --git a/tempest/clients.py b/tempest/clients.py
index 03cffcb..723e7b5 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -65,6 +65,8 @@
 from tempest.services.data_processing.v1_1.client import DataProcessingClient
 from tempest.services.database.json.flavors_client import \
     DatabaseFlavorsClientJSON
+from tempest.services.database.json.limits_client import \
+    DatabaseLimitsClientJSON
 from tempest.services.database.json.versions_client import \
     DatabaseVersionsClientJSON
 from tempest.services.identity.json.identity_client import IdentityClientJSON
@@ -158,6 +160,7 @@
         super(Manager, self).__init__(credentials=credentials)
 
         self._set_compute_clients()
+        self._set_database_clients()
         self._set_identity_clients()
         self._set_volume_clients()
         self._set_object_storage_clients()
@@ -176,16 +179,6 @@
             build_interval=CONF.network.build_interval,
             build_timeout=CONF.network.build_timeout,
             **self.default_params)
-        self.database_flavors_client = DatabaseFlavorsClientJSON(
-            self.auth_provider,
-            CONF.database.catalog_type,
-            CONF.identity.region,
-            **self.default_params_with_timeout_values)
-        self.database_versions_client = DatabaseVersionsClientJSON(
-            self.auth_provider,
-            CONF.database.catalog_type,
-            CONF.identity.region,
-            **self.default_params_with_timeout_values)
         self.messaging_client = MessagingClientJSON(
             self.auth_provider,
             CONF.messaging.catalog_type,
@@ -281,6 +274,23 @@
         self.volumes_extensions_client = VolumesExtensionsClientJSON(
             self.auth_provider, **params_volume)
 
+    def _set_database_clients(self):
+        self.database_flavors_client = DatabaseFlavorsClientJSON(
+            self.auth_provider,
+            CONF.database.catalog_type,
+            CONF.identity.region,
+            **self.default_params_with_timeout_values)
+        self.database_limits_client = DatabaseLimitsClientJSON(
+            self.auth_provider,
+            CONF.database.catalog_type,
+            CONF.identity.region,
+            **self.default_params_with_timeout_values)
+        self.database_versions_client = DatabaseVersionsClientJSON(
+            self.auth_provider,
+            CONF.database.catalog_type,
+            CONF.identity.region,
+            **self.default_params_with_timeout_values)
+
     def _set_identity_clients(self):
         self.identity_client = IdentityClientJSON(self.auth_provider)
         self.identity_v3_client = IdentityV3ClientJSON(self.auth_provider)
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index ebc6b15..de211fb 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -247,9 +247,11 @@
 
         if not test.call_until_true(check_ports, CONF.network.build_timeout,
                                     CONF.network.build_interval):
-            raise exceptions.TimeoutException("No new port attached to the "
-                                              "server in time (%s sec) !"
-                                              % CONF.network.build_timeout)
+            raise exceptions.TimeoutException(
+                "No new port attached to the server in time (%s sec)! "
+                "Old port: %s. Number of new ports: %d" % (
+                    CONF.network.build_timeout, old_port,
+                    len(self.new_port_list)))
         new_port = net_resources.DeletablePort(client=self.network_client,
                                                **self.new_port_list[0])
 
@@ -485,3 +487,31 @@
         # definitions from subnet
         ssh_client.renew_lease(fixed_ip=floating_ip['fixed_ip_address'])
         self._check_dns_server(ssh_client, [alt_dns_server])
+
+    @test.attr(type='smoke')
+    @test.services('compute', 'network')
+    def test_update_instance_port_admin_state(self):
+        """
+        1. Check public connectivity before updating
+                admin_state_up attribute of instance port to False
+        2. Check public connectivity after updating
+                admin_state_up attribute of instance port to False
+        3. Check public connectivity after updating
+                admin_state_up attribute of instance port to True
+        """
+        self._setup_network_and_servers()
+        floating_ip, server = self.floating_ip_tuple
+        server_id = server['id']
+        port_id = self._list_ports(device_id=server_id)[0]['id']
+        self.check_public_network_connectivity(
+            should_connect=True, msg="before updating "
+            "admin_state_up of instance port to False")
+        self.network_client.update_port(port_id, admin_state_up=False)
+        self.check_public_network_connectivity(
+            should_connect=False, msg="after updating "
+            "admin_state_up of instance port to False",
+            should_check_floating_ip_status=False)
+        self.network_client.update_port(port_id, admin_state_up=True)
+        self.check_public_network_connectivity(
+            should_connect=True, msg="after updating "
+            "admin_state_up of instance port to True")
diff --git a/tempest/services/database/json/limits_client.py b/tempest/services/database/json/limits_client.py
new file mode 100644
index 0000000..4daf028
--- /dev/null
+++ b/tempest/services/database/json/limits_client.py
@@ -0,0 +1,33 @@
+# Copyright 2014 OpenStack Foundation
+# 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 tempest import config
+from tempest_lib.common import rest_client
+
+CONF = config.CONF
+
+
+class DatabaseLimitsClientJSON(rest_client.RestClient):
+
+    def list_db_limits(self, params=None):
+        """List all limits."""
+        url = 'limits'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+        resp, body = self.get(url)
+        self.expected_success(200, resp.status)
+        return resp, self._parse_resp(body)
diff --git a/tempest/services/identity/v3/json/identity_client.py b/tempest/services/identity/v3/json/identity_client.py
index 4d333c0..6010249 100644
--- a/tempest/services/identity/v3/json/identity_client.py
+++ b/tempest/services/identity/v3/json/identity_client.py
@@ -316,6 +316,13 @@
         body = json.loads(body)
         return service_client.ResponseBody(resp, body['group'])
 
+    def list_groups(self):
+        """Lists the groups."""
+        resp, body = self.get('groups')
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBodyList(resp, body['groups'])
+
     def update_group(self, group_id, **kwargs):
         """Updates a group."""
         body = self.get_group(group_id)