Merge "Use a compute service type from tempest.conf"
diff --git a/tempest/api/compute/servers/test_server_metadata_negative.py b/tempest/api/compute/servers/test_server_metadata_negative.py
index ad1ec70..8b074fd 100644
--- a/tempest/api/compute/servers/test_server_metadata_negative.py
+++ b/tempest/api/compute/servers/test_server_metadata_negative.py
@@ -40,7 +40,7 @@
         for sz in [256, 257, 511, 1023]:
             key = "k" * sz
             meta = {key: 'data1'}
-            self.assertRaises(exceptions.OverLimit,
+            self.assertRaises((exceptions.BadRequest, exceptions.OverLimit),
                               self.create_test_server,
                               meta=meta)
 
diff --git a/tempest/api/identity/admin/v3/test_policies.py b/tempest/api/identity/admin/v3/test_policies.py
index 9ea61df..ef7d22c 100644
--- a/tempest/api/identity/admin/v3/test_policies.py
+++ b/tempest/api/identity/admin/v3/test_policies.py
@@ -32,8 +32,8 @@
         for _ in range(3):
             blob = data_utils.rand_name('BlobName-')
             policy_type = data_utils.rand_name('PolicyType-')
-            resp, policy = self.policy_client.create_policy(blob,
-                                                            policy_type)
+            policy = self.policy_client.create_policy(blob,
+                                                      policy_type)
             # Delete the Policy at the end of this method
             self.addCleanup(self._delete_policy, policy['id'])
             policy_ids.append(policy['id'])
@@ -49,7 +49,7 @@
         # Test to update policy
         blob = data_utils.rand_name('BlobName-')
         policy_type = data_utils.rand_name('PolicyType-')
-        _, policy = self.policy_client.create_policy(blob, policy_type)
+        policy = self.policy_client.create_policy(blob, policy_type)
         self.addCleanup(self._delete_policy, policy['id'])
         self.assertIn('id', policy)
         self.assertIn('type', policy)
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index 74baba6..76b6f17 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -15,7 +15,7 @@
 import cStringIO as StringIO
 
 from tempest import clients
-from tempest.common import isolated_creds
+from tempest.common import credentials
 from tempest.common.utils import data_utils
 from tempest import config
 from tempest import exceptions
@@ -36,7 +36,7 @@
         super(BaseImageTest, cls).resource_setup()
         cls.created_images = []
         cls._interface = 'json'
-        cls.isolated_creds = isolated_creds.IsolatedCreds(
+        cls.isolated_creds = credentials.get_isolated_credentials(
             cls.__name__, network_resources=cls.network_resources)
         if not CONF.service_available.glance:
             skip_msg = ("%s skipped as glance is not available" % cls.__name__)
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index 2e39cf9..7fabb7d 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -16,8 +16,8 @@
 
 from tempest.api.identity import base
 from tempest import clients
+from tempest.common import credentials
 from tempest.common import custom_matchers
-from tempest.common import isolated_creds
 from tempest import config
 from tempest import exceptions
 import tempest.test
@@ -34,7 +34,7 @@
         if not CONF.service_available.swift:
             skip_msg = ("%s skipped as swift is not available" % cls.__name__)
             raise cls.skipException(skip_msg)
-        cls.isolated_creds = isolated_creds.IsolatedCreds(
+        cls.isolated_creds = credentials.get_isolated_credentials(
             cls.__name__, network_resources=cls.network_resources)
         # Get isolated creds for normal user
         cls.os = clients.Manager(cls.isolated_creds.get_primary_creds())
diff --git a/tempest/api_schema/response/compute/services.py b/tempest/api_schema/response/compute/services.py
index fc42b89..6f361ef 100644
--- a/tempest/api_schema/response/compute/services.py
+++ b/tempest/api_schema/response/compute/services.py
@@ -22,7 +22,8 @@
                 'items': {
                     'type': 'object',
                     'properties': {
-                        'id': {'type': 'integer'},
+                        'id': {'type': ['integer', 'string'],
+                               'pattern': '^[a-zA-Z!]*@[0-9]+$'},
                         'zone': {'type': 'string'},
                         'host': {'type': 'string'},
                         'state': {'type': 'string'},
diff --git a/tempest/cli/simple_read_only/network/test_neutron.py b/tempest/cli/simple_read_only/network/test_neutron.py
index 6090882..6cf0640 100644
--- a/tempest/cli/simple_read_only/network/test_neutron.py
+++ b/tempest/cli/simple_read_only/network/test_neutron.py
@@ -198,6 +198,31 @@
                                             'auth_mode', 'status'])
 
     @test.attr(type='smoke')
+    @test.requires_ext(extension='fwaas', service='network')
+    def test_neutron_firewall_list(self):
+        firewall_list = self.parser.listing(self.neutron
+                                            ('firewall-list'))
+        self.assertTableStruct(firewall_list, ['id', 'name',
+                                               'firewall_policy_id'])
+
+    @test.attr(type='smoke')
+    @test.requires_ext(extension='fwaas', service='network')
+    def test_neutron_firewall_policy_list(self):
+        firewall_policy = self.parser.listing(self.neutron
+                                              ('firewall-policy-list'))
+        self.assertTableStruct(firewall_policy, ['id', 'name',
+                                                 'firewall_rules'])
+
+    @test.attr(type='smoke')
+    @test.requires_ext(extension='fwaas', service='network')
+    def test_neutron_firewall_rule_list(self):
+        firewall_rule = self.parser.listing(self.neutron
+                                            ('firewall-rule-list'))
+        self.assertTableStruct(firewall_rule, ['id', 'name',
+                                               'firewall_policy_id',
+                                               'summary', 'enabled'])
+
+    @test.attr(type='smoke')
     def test_neutron_help(self):
         help_text = self.neutron('help')
         lines = help_text.split('\n')
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index 228e47c..1ce1e39 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -203,9 +203,8 @@
                 if 'overlaps with another subnet' not in str(e):
                     raise
         else:
-            e = exceptions.BuildErrorException()
-            e.message = 'Available CIDR for subnet creation could not be found'
-            raise e
+            message = 'Available CIDR for subnet creation could not be found'
+            raise Exception(message)
         return resp_body['subnet']
 
     def _create_router(self, router_name, tenant_id):
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index c9448a7..f4fe92b 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -52,6 +52,23 @@
         return text
 
 
+class ResponseBody(dict):
+    """Class that wraps an http response and body into a single value.
+
+    Callers that receive this object will normally use it as a dict but
+    can extract the response if needed.
+    """
+
+    def __init__(self, response, body=None):
+        body_data = body or {}
+        self.update(body_data)
+        self.response = response
+
+    def __str__(self):
+        body = super.__str__(self)
+        return "response: %s\nBody: %s" % (self.response, body)
+
+
 class RestClient(object):
 
     TYPE = "json"
diff --git a/tempest/scenario/test_dashboard_basic_ops.py b/tempest/scenario/test_dashboard_basic_ops.py
index 1a10b79..2014293 100644
--- a/tempest/scenario/test_dashboard_basic_ops.py
+++ b/tempest/scenario/test_dashboard_basic_ops.py
@@ -65,7 +65,7 @@
 
     def check_login_page(self):
         response = urllib2.urlopen(CONF.dashboard.dashboard_url)
-        self.assertIn("<h3>Log In</h3>", response.read())
+        self.assertIn("Log In", response.read())
 
     def user_login(self):
         self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor())
diff --git a/tempest/services/compute/json/volumes_extensions_client.py b/tempest/services/compute/json/volumes_extensions_client.py
index 6b27f4a..b23b20b 100644
--- a/tempest/services/compute/json/volumes_extensions_client.py
+++ b/tempest/services/compute/json/volumes_extensions_client.py
@@ -92,7 +92,6 @@
     def wait_for_volume_status(self, volume_id, status):
         """Waits for a Volume to reach a given status."""
         resp, body = self.get_volume(volume_id)
-        volume_name = body['displayName']
         volume_status = body['status']
         start = int(time.time())
 
@@ -106,7 +105,7 @@
             if int(time.time()) - start >= self.build_timeout:
                 message = ('Volume %s failed to reach %s status within '
                            'the required time (%s s).' %
-                           (volume_name, status, self.build_timeout))
+                           (volume_id, status, self.build_timeout))
                 raise exceptions.TimeoutException(message)
 
     def is_resource_deleted(self, id):
diff --git a/tempest/services/identity/v3/json/policy_client.py b/tempest/services/identity/v3/json/policy_client.py
index e093260..41b0b59 100644
--- a/tempest/services/identity/v3/json/policy_client.py
+++ b/tempest/services/identity/v3/json/policy_client.py
@@ -39,7 +39,7 @@
         resp, body = self.post('policies', post_body)
         self.expected_success(201, resp.status)
         body = json.loads(body)
-        return resp, body['policy']
+        return rest_client.ResponseBody(resp, body['policy'])
 
     def list_policies(self):
         """Lists the policies."""