Merge "Switch to using the skip_because decorator from tempest-lib"
diff --git a/tempest/api/baremetal/admin/test_ports.py b/tempest/api/baremetal/admin/test_ports.py
index 4aedaa4..89447e0 100644
--- a/tempest/api/baremetal/admin/test_ports.py
+++ b/tempest/api/baremetal/admin/test_ports.py
@@ -10,6 +10,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib import decorators
+
 from tempest.api.baremetal.admin import base
 from tempest.common.utils import data_utils
 from tempest import exceptions as exc
@@ -57,7 +59,7 @@
         _, body = self.client.show_port(uuid)
         self._assertExpected(port, body)
 
-    @test.skip_because(bug='1398350')
+    @decorators.skip_because(bug='1398350')
     @test.attr(type='smoke')
     def test_create_port_with_extra(self):
         node_id = self.node['uuid']
@@ -231,7 +233,7 @@
         _, body = self.client.show_port(port['uuid'])
         self.assertEqual(extra, body['extra'])
 
-    @test.skip_because(bug='1398350')
+    @decorators.skip_because(bug='1398350')
     @test.attr(type='smoke')
     def test_update_port_mixed_ops(self):
         node_id = self.node['uuid']
diff --git a/tempest/api/compute/admin/test_quotas_negative.py b/tempest/api/compute/admin/test_quotas_negative.py
index b24f316..7cefe90 100644
--- a/tempest/api/compute/admin/test_quotas_negative.py
+++ b/tempest/api/compute/admin/test_quotas_negative.py
@@ -12,6 +12,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib import decorators
+
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
 from tempest import config
@@ -91,8 +93,8 @@
         self.assertRaises((exceptions.Unauthorized, exceptions.OverLimit),
                           self.create_test_server)
 
-    @test.skip_because(bug="1186354",
-                       condition=CONF.service_available.neutron)
+    @decorators.skip_because(bug="1186354",
+                             condition=CONF.service_available.neutron)
     @test.attr(type='gate')
     @test.services('network')
     def test_security_groups_exceed_limit(self):
@@ -118,8 +120,8 @@
                           self.sg_client.create_security_group,
                           "sg-overlimit", "sg-desc")
 
-    @test.skip_because(bug="1186354",
-                       condition=CONF.service_available.neutron)
+    @decorators.skip_because(bug="1186354",
+                             condition=CONF.service_available.neutron)
     @test.attr(type=['negative', 'gate'])
     @test.services('network')
     def test_security_groups_rules_exceed_limit(self):
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index 5210077..cff9a43 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -12,6 +12,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib import decorators
+
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
 from tempest import test
@@ -142,7 +144,7 @@
         self.assertEqual(server['status'], 'ACTIVE')
 
     @test.attr(type='gate')
-    @test.skip_because(bug="1240043")
+    @decorators.skip_because(bug="1240043")
     def test_get_server_diagnostics_by_admin(self):
         # Retrieve server diagnostics by admin user
         resp, diagnostic = self.client.get_server_diagnostics(self.s1_id)
diff --git a/tempest/api/compute/security_groups/test_security_groups_negative.py b/tempest/api/compute/security_groups/test_security_groups_negative.py
index 988482b..ee9f78b 100644
--- a/tempest/api/compute/security_groups/test_security_groups_negative.py
+++ b/tempest/api/compute/security_groups/test_security_groups_negative.py
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib import decorators
 import testtools
 
 from tempest.api.compute.security_groups import base
@@ -55,8 +56,8 @@
         self.assertRaises(exceptions.NotFound, self.client.get_security_group,
                           non_exist_id)
 
-    @test.skip_because(bug="1161411",
-                       condition=CONF.service_available.neutron)
+    @decorators.skip_because(bug="1161411",
+                             condition=CONF.service_available.neutron)
     @test.attr(type=['negative', 'smoke'])
     @test.services('network')
     def test_security_group_create_with_invalid_group_name(self):
@@ -76,8 +77,8 @@
                           self.client.create_security_group, s_name,
                           s_description)
 
-    @test.skip_because(bug="1161411",
-                       condition=CONF.service_available.neutron)
+    @decorators.skip_because(bug="1161411",
+                             condition=CONF.service_available.neutron)
     @test.attr(type=['negative', 'smoke'])
     @test.services('network')
     def test_security_group_create_with_invalid_group_description(self):
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 7964cf7..375f441 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -13,6 +13,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib import decorators
+
 from tempest.api.compute import base
 from tempest.api import utils
 from tempest.common.utils import data_utils
@@ -269,8 +271,8 @@
         self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
         self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
 
-    @test.skip_because(bug="1182883",
-                       condition=CONF.service_available.neutron)
+    @decorators.skip_because(bug="1182883",
+                             condition=CONF.service_available.neutron)
     @test.attr(type='gate')
     def test_list_servers_filtered_by_ip_regex(self):
         # Filter servers by regex ip
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 17e3669..9edaede 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -17,6 +17,7 @@
 import logging
 import urlparse
 
+from tempest_lib import decorators
 import testtools
 
 from tempest.api.compute import base
@@ -100,7 +101,7 @@
         # The server should be power cycled
         self._test_reboot_server('HARD')
 
-    @test.skip_because(bug="1014647")
+    @decorators.skip_because(bug="1014647")
     @test.attr(type='smoke')
     def test_reboot_server_soft(self):
         # The server should be signaled to reboot gracefully
diff --git a/tempest/api/compute/servers/test_server_group.py b/tempest/api/compute/servers/test_server_group.py
index 0af19c0..fe5dca0 100644
--- a/tempest/api/compute/servers/test_server_group.py
+++ b/tempest/api/compute/servers/test_server_group.py
@@ -13,6 +13,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib import decorators
+
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
 from tempest import test
@@ -74,7 +76,7 @@
         policy = ['anti-affinity']
         self._create_delete_server_group(policy)
 
-    @test.skip_because(bug="1324348")
+    @decorators.skip_because(bug="1324348")
     @test.attr(type='gate')
     def test_create_delete_server_group_with_multiple_policies(self):
         # Create and Delete the server-group with multiple policies
diff --git a/tempest/api/compute/servers/test_virtual_interfaces.py b/tempest/api/compute/servers/test_virtual_interfaces.py
index 48af084..e07a7ed 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces.py
@@ -14,6 +14,7 @@
 #    under the License.
 
 import netaddr
+from tempest_lib import decorators
 
 from tempest.api.compute import base
 from tempest import config
@@ -33,8 +34,8 @@
         resp, server = cls.create_test_server(wait_until='ACTIVE')
         cls.server_id = server['id']
 
-    @test.skip_because(bug="1183436",
-                       condition=CONF.service_available.neutron)
+    @decorators.skip_because(bug="1183436",
+                             condition=CONF.service_available.neutron)
     @test.attr(type='gate')
     @test.services('network')
     def test_list_virtual_interfaces(self):
diff --git a/tempest/api/messaging/test_claims.py b/tempest/api/messaging/test_claims.py
index 1b004dd..1aab8d2 100644
--- a/tempest/api/messaging/test_claims.py
+++ b/tempest/api/messaging/test_claims.py
@@ -16,6 +16,8 @@
 import logging
 import urlparse
 
+from tempest_lib import decorators
+
 from tempest.api.messaging import base
 from tempest.common.utils import data_utils
 from tempest import config
@@ -65,7 +67,7 @@
         # Delete Claimed message
         self.client.delete_messages(claimed_message_uri)
 
-    @test.skip_because(bug="1331517")
+    @decorators.skip_because(bug="1331517")
     @test.attr(type='smoke')
     def test_query_claim(self):
         # Post a Claim
@@ -79,7 +81,7 @@
         claimed_message_uri = body[0]['href']
         self.delete_messages(claimed_message_uri)
 
-    @test.skip_because(bug="1328111")
+    @decorators.skip_because(bug="1328111")
     @test.attr(type='smoke')
     def test_update_claim(self):
         # Post a Claim
diff --git a/tempest/api/network/test_load_balancer.py b/tempest/api/network/test_load_balancer.py
index b606115..df76757 100644
--- a/tempest/api/network/test_load_balancer.py
+++ b/tempest/api/network/test_load_balancer.py
@@ -13,6 +13,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib import decorators
+
 from tempest.api.network import base
 from tempest.common.utils import data_utils
 from tempest import test
@@ -422,6 +424,6 @@
         self.assertEqual(2, member['weight'])
 
 
-@test.skip_because(bug="1402007")
+@decorators.skip_because(bug="1402007")
 class LoadBalancerIpV6TestJSON(LoadBalancerTestJSON):
     _ip_version = 6
diff --git a/tempest/api/network/test_service_type_management.py b/tempest/api/network/test_service_type_management.py
index 447c3f3..0492fe3 100644
--- a/tempest/api/network/test_service_type_management.py
+++ b/tempest/api/network/test_service_type_management.py
@@ -10,6 +10,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib import decorators
+
 from tempest.api.network import base
 from tempest import test
 
@@ -24,7 +26,7 @@
             msg = "Neutron Service Type Management not enabled."
             raise cls.skipException(msg)
 
-    @test.skip_because(bug="1400370")
+    @decorators.skip_because(bug="1400370")
     @test.attr(type='smoke')
     def test_service_provider_list(self):
         body = self.client.list_service_providers()
diff --git a/tempest/api/object_storage/test_account_quotas_negative.py b/tempest/api/object_storage/test_account_quotas_negative.py
index a6ea6ee..5a0be54 100644
--- a/tempest/api/object_storage/test_account_quotas_negative.py
+++ b/tempest/api/object_storage/test_account_quotas_negative.py
@@ -14,6 +14,8 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
+from tempest_lib import decorators
+
 from tempest.api.object_storage import base
 from tempest import clients
 from tempest.common.utils import data_utils
@@ -93,7 +95,7 @@
                           {"Quota-Bytes": "100"})
 
     @test.attr(type=["negative", "smoke"])
-    @test.skip_because(bug="1310597")
+    @decorators.skip_because(bug="1310597")
     @test.requires_ext(extension='account_quotas', service='object')
     def test_upload_large_object(self):
         object_name = data_utils.rand_name(name="TestObject")
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index 7f8cb8b..09b0ce0 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib import decorators
 import testtools
 import time
 import urlparse
@@ -112,7 +113,7 @@
                 self.assertEqual(object_content, obj_name[::-1])
 
     @test.attr(type='slow')
-    @test.skip_because(bug='1317133')
+    @decorators.skip_because(bug='1317133')
     @testtools.skipIf(
         not CONF.object_storage_feature_enabled.container_sync,
         'Old-style container sync function is disabled')
diff --git a/tempest/api/telemetry/test_telemetry_notification_api.py b/tempest/api/telemetry/test_telemetry_notification_api.py
index e64cd4a..7e5d6ee 100644
--- a/tempest/api/telemetry/test_telemetry_notification_api.py
+++ b/tempest/api/telemetry/test_telemetry_notification_api.py
@@ -10,6 +10,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib import decorators
 import testtools
 
 from tempest.api.telemetry import base
@@ -46,7 +47,7 @@
     @test.services("image")
     @testtools.skipIf(not CONF.image_feature_enabled.api_v1,
                       "Glance api v1 is disabled")
-    @test.skip_because(bug='1351627')
+    @decorators.skip_because(bug='1351627')
     def test_check_glance_v1_notifications(self):
         body = self.create_image(self.image_client)
         self.image_client.update_image(body['id'], data='data')
@@ -62,7 +63,7 @@
     @test.services("image")
     @testtools.skipIf(not CONF.image_feature_enabled.api_v2,
                       "Glance api v2 is disabled")
-    @test.skip_because(bug='1351627')
+    @decorators.skip_because(bug='1351627')
     def test_check_glance_v2_notifications(self):
         body = self.create_image(self.image_client_v2)
 
diff --git a/tempest/cli/simple_read_only/compute/test_nova.py b/tempest/cli/simple_read_only/compute/test_nova.py
index 5efeb75..aee92fa 100644
--- a/tempest/cli/simple_read_only/compute/test_nova.py
+++ b/tempest/cli/simple_read_only/compute/test_nova.py
@@ -13,13 +13,13 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib import decorators
 from tempest_lib import exceptions
 import testtools
 
 from tempest import cli
 from tempest import config
 from tempest.openstack.common import log as logging
-import tempest.test
 
 CONF = config.CONF
 
@@ -82,7 +82,7 @@
     def test_admin_dns_domains(self):
         self.nova('dns-domains')
 
-    @tempest.test.skip_because(bug="1157349")
+    @decorators.skip_because(bug="1157349")
     def test_admin_dns_list(self):
         self.nova('dns-list')
 
@@ -120,7 +120,7 @@
     def test_admin_image_list(self):
         self.nova('image-list')
 
-    @tempest.test.skip_because(bug="1157349")
+    @decorators.skip_because(bug="1157349")
     def test_admin_interface_list(self):
         self.nova('interface-list')
 
@@ -145,7 +145,7 @@
     def test_admin_secgroup_list(self):
         self.nova('secgroup-list')
 
-    @tempest.test.skip_because(bug="1157349")
+    @decorators.skip_because(bug="1157349")
     def test_admin_secgroup_list_rules(self):
         self.nova('secgroup-list-rules')
 
diff --git a/tempest/scenario/orchestration/test_server_cfn_init.py b/tempest/scenario/orchestration/test_server_cfn_init.py
index 18b759e..6052e0b 100644
--- a/tempest/scenario/orchestration/test_server_cfn_init.py
+++ b/tempest/scenario/orchestration/test_server_cfn_init.py
@@ -12,6 +12,8 @@
 
 import json
 
+from tempest_lib import decorators
+
 from tempest import config
 from tempest import exceptions
 from tempest.openstack.common import log as logging
@@ -123,7 +125,7 @@
                                    log_console_of_servers=[server])
 
     @test.attr(type='slow')
-    @test.skip_because(bug='1374175')
+    @decorators.skip_because(bug='1374175')
     @test.services('orchestration', 'compute')
     def test_server_cfn_init(self):
         self.assign_keypair()
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index 194a0bd..598c6d1 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib import decorators
 import testtools
 
 from tempest.common.utils import data_utils
@@ -92,7 +93,7 @@
         self.servers_client.wait_for_server_status(self.server['id'], 'ACTIVE')
         self._check_network_connectivity()
 
-    @test.skip_because(bug="1323658")
+    @decorators.skip_because(bug="1323658")
     @test.services('compute', 'network')
     def test_server_connectivity_stop_start(self):
         self._setup_network_and_servers()
@@ -140,7 +141,7 @@
         self.servers_client.resume_server(self.server['id'])
         self._wait_server_status_and_check_network_connectivity()
 
-    @test.skip_because(bug="1323658")
+    @decorators.skip_because(bug="1323658")
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize is not available.')
     @test.services('compute', 'network')
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index de211fb..fc174cd 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -16,6 +16,7 @@
 import collections
 import re
 
+from tempest_lib import decorators
 import testtools
 
 from tempest.common.utils import data_utils
@@ -438,7 +439,7 @@
                                  act_serv=servers,
                                  trgt_serv=dns_servers))
 
-    @test.skip_because(bug="1412325")
+    @decorators.skip_because(bug="1412325")
     @testtools.skipUnless(CONF.scenario.dhcp_client,
                           "DHCP client is not available.")
     @test.attr(type='smoke')
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index cfc1d37..16f5283 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -15,6 +15,7 @@
 
 import time
 
+from tempest_lib import decorators
 import testtools
 
 from tempest.common.utils import data_utils
@@ -137,7 +138,7 @@
         got_timestamp = ssh_client.exec_command('sudo cat /mnt/timestamp')
         self.assertEqual(self.timestamp, got_timestamp)
 
-    @tempest.test.skip_because(bug="1205344")
+    @decorators.skip_because(bug="1205344")
     @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
                           'Snapshotting is not available.')
     @tempest.test.services('compute', 'network', 'volume', 'image')
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 910fd79..c8f438e 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -10,6 +10,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib import decorators
+
 from tempest.common.utils import data_utils
 from tempest import config
 from tempest.openstack.common import log
@@ -130,7 +132,7 @@
         actual = self._get_content(ssh_client)
         self.assertEqual(expected, actual)
 
-    @test.skip_because(bug='1373513')
+    @decorators.skip_because(bug='1373513')
     @test.services('compute', 'volume', 'image')
     def test_volume_boot_pattern(self):
         keypair = self.create_keypair()
diff --git a/tempest/test.py b/tempest/test.py
index 281f0f2..28e1e2c 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -137,35 +137,6 @@
     return decorator
 
 
-def skip_because(*args, **kwargs):
-    """A decorator useful to skip tests hitting known bugs
-
-    @param bug: bug number causing the test to skip
-    @param condition: optional condition to be True for the skip to have place
-    @param interface: skip the test if it is the same as self._interface
-    """
-    def decorator(f):
-        @functools.wraps(f)
-        def wrapper(self, *func_args, **func_kwargs):
-            skip = False
-            if "condition" in kwargs:
-                if kwargs["condition"] is True:
-                    skip = True
-            elif "interface" in kwargs:
-                if kwargs["interface"] == self._interface:
-                    skip = True
-            else:
-                skip = True
-            if "bug" in kwargs and skip is True:
-                if not kwargs['bug'].isdigit():
-                    raise ValueError('bug must be a valid bug number')
-                msg = "Skipped until Bug: %s is resolved." % kwargs["bug"]
-                raise testtools.TestCase.skipException(msg)
-            return f(self, *func_args, **func_kwargs)
-        return wrapper
-    return decorator
-
-
 def requires_ext(*args, **kwargs):
     """A decorator to skip tests if an extension is not enabled
 
diff --git a/tempest/tests/test_decorators.py b/tempest/tests/test_decorators.py
index 32cefd0..1f1835e 100644
--- a/tempest/tests/test_decorators.py
+++ b/tempest/tests/test_decorators.py
@@ -150,70 +150,6 @@
                                      allow_inheritance=True)
 
 
-class TestSkipBecauseDecorator(BaseDecoratorsTest):
-    def _test_skip_because_helper(self, expected_to_skip=True,
-                                  **decorator_args):
-        class TestFoo(test.BaseTestCase):
-            _interface = 'json'
-
-            @test.skip_because(**decorator_args)
-            def test_bar(self):
-                return 0
-
-        t = TestFoo('test_bar')
-        if expected_to_skip:
-            self.assertRaises(testtools.TestCase.skipException, t.test_bar)
-        else:
-            # assert that test_bar returned 0
-            self.assertEqual(TestFoo('test_bar').test_bar(), 0)
-
-    def test_skip_because_bug(self):
-        self._test_skip_because_helper(bug='12345')
-
-    def test_skip_because_bug_and_interface_match(self):
-        self._test_skip_because_helper(bug='12346', interface='json')
-
-    def test_skip_because_bug_interface_not_match(self):
-        self._test_skip_because_helper(expected_to_skip=False,
-                                       bug='12347', interface='xml')
-
-    def test_skip_because_bug_and_condition_true(self):
-        self._test_skip_because_helper(bug='12348', condition=True)
-
-    def test_skip_because_bug_and_condition_false(self):
-        self._test_skip_because_helper(expected_to_skip=False,
-                                       bug='12349', condition=False)
-
-    def test_skip_because_bug_condition_false_and_interface_match(self):
-        """
-        Assure that only condition will be evaluated if both parameters are
-        passed.
-        """
-        self._test_skip_because_helper(expected_to_skip=False,
-                                       bug='12350', condition=False,
-                                       interface='json')
-
-    def test_skip_because_bug_condition_true_and_interface_not_match(self):
-        """
-        Assure that only condition will be evaluated if both parameters are
-        passed.
-        """
-        self._test_skip_because_helper(bug='12351', condition=True,
-                                       interface='xml')
-
-    def test_skip_because_bug_without_bug_never_skips(self):
-        """Never skip without a bug parameter."""
-        self._test_skip_because_helper(expected_to_skip=False,
-                                       condition=True)
-        self._test_skip_because_helper(expected_to_skip=False,
-                                       interface='json')
-
-    def test_skip_because_invalid_bug_number(self):
-        """Raise ValueError if with an invalid bug number"""
-        self.assertRaises(ValueError, self._test_skip_because_helper,
-                          bug='critical_bug')
-
-
 class TestRequiresExtDecorator(BaseDecoratorsTest):
     def setUp(self):
         super(TestRequiresExtDecorator, self).setUp()