Merge "Updated from global requirements"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index f509cb4..13ee8fe 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -78,7 +78,7 @@
 #
 
 # List of logger=LEVEL pairs. (list value)
-#default_log_levels = amqp=WARN,amqplib=WARN,boto=WARN,qpid=WARN,sqlalchemy=WARN,suds=INFO,oslo.messaging=INFO,iso8601=WARN,requests.packages.urllib3.connectionpool=WARN,urllib3.connectionpool=WARN
+#default_log_levels = amqp=WARN,amqplib=WARN,boto=WARN,qpid=WARN,sqlalchemy=WARN,suds=INFO,oslo.messaging=INFO,iso8601=WARN,requests.packages.urllib3.connectionpool=WARN,urllib3.connectionpool=WARN,websocket=WARN,keystonemiddleware=WARN,routes.middleware=WARN,stevedore=WARN
 
 # Enables or disables fatal status of deprecations. (boolean value)
 #fatal_deprecations = false
@@ -260,7 +260,8 @@
 # The endpoint type to use for the compute service. (string value)
 #endpoint_type = publicURL
 
-# Visible fixed network name  (string value)
+# Name of the fixed network that is visible to all test tenants.
+# (string value)
 #fixed_network_name = private
 
 # Valid primary flavor to use in tests. (string value)
@@ -270,7 +271,8 @@
 #flavor_ref_alt = 2
 
 # Unallocated floating IP range, which will be used to test the
-# floating IP bulk feature for CRUD operation. (string value)
+# floating IP bulk feature for CRUD operation. This block must not
+# overlap an existing floating IP pool. (string value)
 #floating_ip_range = 10.0.0.0/29
 
 # Password used to authenticate to an instance using the alternate
@@ -299,7 +301,8 @@
 # IP version used for SSH connections. (integer value)
 #ip_version_for_ssh = 4
 
-# Network used for SSH connections. (string value)
+# Network used for SSH connections. Ignored if
+# use_floatingip_for_ssh=true or run_ssh=false. (string value)
 #network_for_ssh = public
 
 # Path to a private key file for SSH access to remote hosts (string
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions.py b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
index ba66ab9..3bb7d19 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
@@ -130,7 +130,8 @@
 
         # Make sure no longer associated with old server
         self.assertRaises((exceptions.NotFound,
-                           exceptions.UnprocessableEntity),
+                           exceptions.UnprocessableEntity,
+                           exceptions.Conflict),
                           self.client.disassociate_floating_ip_from_server,
                           self.floating_ip, self.server_id)
 
diff --git a/tempest/api/network/test_security_groups.py b/tempest/api/network/test_security_groups.py
index 47f2b52..40cf04f 100644
--- a/tempest/api/network/test_security_groups.py
+++ b/tempest/api/network/test_security_groups.py
@@ -212,6 +212,24 @@
                                                 port_range_max,
                                                 remote_ip_prefix=ip_prefix)
 
+    @test.attr(type='smoke')
+    def test_create_security_group_rule_with_protocol_integer_value(self):
+        # Verify creating security group rule with the
+        # protocol as integer value
+        # arguments : "protocol": 17
+        group_create_body, _ = self._create_security_group()
+        direction = 'ingress'
+        protocol = 17
+        security_group_id = group_create_body['security_group']['id']
+        _, rule_create_body = self.client.create_security_group_rule(
+            security_group_id=security_group_id,
+            direction=direction,
+            protocol=protocol
+        )
+        sec_group_rule = rule_create_body['security_group_rule']
+        self.assertEqual(sec_group_rule['direction'], direction)
+        self.assertEqual(int(sec_group_rule['protocol']), protocol)
+
 
 class SecGroupTestXML(SecGroupTest):
     _interface = 'xml'
diff --git a/tempest/api/volume/admin/test_volumes_backup.py b/tempest/api/volume/admin/test_volumes_backup.py
index bf014a8..1357d31 100644
--- a/tempest/api/volume/admin/test_volumes_backup.py
+++ b/tempest/api/volume/admin/test_volumes_backup.py
@@ -23,17 +23,16 @@
 LOG = logging.getLogger(__name__)
 
 
-class VolumesBackupsTest(base.BaseVolumeV1AdminTest):
+class VolumesBackupsV2Test(base.BaseVolumeAdminTest):
     _interface = "json"
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesBackupsTest, cls).resource_setup()
+        super(VolumesBackupsV2Test, cls).resource_setup()
 
         if not CONF.volume_feature_enabled.backup:
             raise cls.skipException("Cinder backup feature disabled")
 
-        cls.backups_adm_client = cls.os_adm.backups_client
         cls.volume = cls.create_volume()
 
     @test.attr(type='smoke')
@@ -71,3 +70,7 @@
                                                        'available')
         self.admin_volume_client.wait_for_volume_status(
             restore['volume_id'], 'available')
+
+
+class VolumesBackupsV1Test(VolumesBackupsV2Test):
+    _api_version = 1
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index f9f03ac..5d99123 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -176,6 +176,7 @@
             cls.admin_volume_client = cls.os_adm.volumes_client
             cls.hosts_client = cls.os_adm.volume_hosts_client
             cls.admin_snapshots_client = cls.os_adm.snapshots_client
+            cls.backups_adm_client = cls.os_adm.backups_client
         elif cls._api_version == 2:
             if not CONF.volume_feature_enabled.api_v2:
                 msg = "Volume API v2 is disabled"
@@ -185,6 +186,7 @@
             cls.admin_volume_client = cls.os_adm.volumes_v2_client
             cls.hosts_client = cls.os_adm.volume_hosts_v2_client
             cls.admin_snapshots_client = cls.os_adm.snapshots_v2_client
+            cls.backups_adm_client = cls.os_adm.backups_v2_client
 
     @classmethod
     def resource_cleanup(cls):
diff --git a/tempest/clients.py b/tempest/clients.py
index 9546502..756614d 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -187,6 +187,7 @@
     VolumeTypesV2ClientJSON
 from tempest.services.volume.v2.json.availability_zone_client import \
     VolumeV2AvailabilityZoneClientJSON
+from tempest.services.volume.v2.json.backups_client import BackupsClientV2JSON
 from tempest.services.volume.v2.json.extensions_client import \
     ExtensionsV2ClientJSON as VolumeV2ExtensionClientJSON
 from tempest.services.volume.v2.json.qos_client import QosSpecsV2ClientJSON
@@ -436,6 +437,7 @@
 
     def _set_volume_json_clients(self):
         self.backups_client = BackupsClientJSON(self.auth_provider)
+        self.backups_v2_client = BackupsClientV2JSON(self.auth_provider)
         self.snapshots_client = SnapshotsClientJSON(self.auth_provider)
         self.snapshots_v2_client = SnapshotsV2ClientJSON(self.auth_provider)
         self.volumes_client = VolumesClientJSON(self.auth_provider)
diff --git a/tempest/config.py b/tempest/config.py
index 63a7226..616a476 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -222,10 +222,12 @@
                     "channel."),
     cfg.StrOpt('fixed_network_name',
                default='private',
-               help="Visible fixed network name "),
+               help="Name of the fixed network that is visible to all test "
+                    "tenants."),
     cfg.StrOpt('network_for_ssh',
                default='public',
-               help="Network used for SSH connections."),
+               help="Network used for SSH connections. Ignored if "
+                    "use_floatingip_for_ssh=true or run_ssh=false."),
     cfg.IntOpt('ip_version_for_ssh',
                default=4,
                help="IP version used for SSH connections."),
@@ -266,7 +268,9 @@
     cfg.StrOpt('floating_ip_range',
                default='10.0.0.0/29',
                help='Unallocated floating IP range, which will be used to '
-                    'test the floating IP bulk feature for CRUD operation.')
+                    'test the floating IP bulk feature for CRUD operation. '
+                    'This block must not overlap an existing floating IP '
+                    'pool.')
 ]
 
 compute_features_group = cfg.OptGroup(name='compute-feature-enabled',
@@ -975,7 +979,14 @@
 
 
 baremetal_group = cfg.OptGroup(name='baremetal',
-                               title='Baremetal provisioning service options')
+                               title='Baremetal provisioning service options',
+                               help='When enabling baremetal tests, Nova '
+                                    'must be configured to use the Ironic '
+                                    'driver. The following paremeters for the '
+                                    '[compute] section must be disabled: '
+                                    'console_output, interface_attach, '
+                                    'live_migration, pause, rescue, resize '
+                                    'shelve, snapshot, and suspend')
 
 BaremetalGroup = [
     cfg.StrOpt('catalog_type',
diff --git a/tempest/openstack/common/__init__.py b/tempest/openstack/common/__init__.py
index d1223ea..e69de29 100644
--- a/tempest/openstack/common/__init__.py
+++ b/tempest/openstack/common/__init__.py
@@ -1,17 +0,0 @@
-#
-#    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 six
-
-
-six.add_move(six.MovedModule('mox', 'mox', 'mox3.mox'))
diff --git a/tempest/openstack/common/_i18n.py b/tempest/openstack/common/_i18n.py
new file mode 100644
index 0000000..fdc8327
--- /dev/null
+++ b/tempest/openstack/common/_i18n.py
@@ -0,0 +1,45 @@
+#    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.
+
+"""oslo.i18n integration module.
+
+See http://docs.openstack.org/developer/oslo.i18n/usage.html
+
+"""
+
+try:
+    import oslo.i18n
+
+    # NOTE(dhellmann): This reference to o-s-l-o will be replaced by the
+    # application name when this module is synced into the separate
+    # repository. It is OK to have more than one translation function
+    # using the same domain, since there will still only be one message
+    # catalog.
+    _translators = oslo.i18n.TranslatorFactory(domain='tempest')
+
+    # The primary translation function using the well-known name "_"
+    _ = _translators.primary
+
+    # Translators for log levels.
+    #
+    # The abbreviated names are meant to reflect the usual use of a short
+    # name like '_'. The "L" is for "log" and the other letter comes from
+    # the level.
+    _LI = _translators.log_info
+    _LW = _translators.log_warning
+    _LE = _translators.log_error
+    _LC = _translators.log_critical
+except ImportError:
+    # NOTE(dims): Support for cases where a project wants to use
+    # code from tempest-incubator, but is not ready to be internationalized
+    # (like tempest)
+    _ = _LI = _LW = _LE = _LC = lambda x: x
diff --git a/tempest/openstack/common/log.py b/tempest/openstack/common/log.py
index 44102c0..26cd6ad 100644
--- a/tempest/openstack/common/log.py
+++ b/tempest/openstack/common/log.py
@@ -33,20 +33,20 @@
 import logging.config
 import logging.handlers
 import os
+import socket
 import sys
 import traceback
 
 from oslo.config import cfg
+from oslo.serialization import jsonutils
+from oslo.utils import importutils
 import six
 from six import moves
 
-from tempest.openstack.common.gettextutils import _
-from tempest.openstack.common import importutils
-from tempest.openstack.common import jsonutils
+_PY26 = sys.version_info[0:2] == (2, 6)
+
+from tempest.openstack.common._i18n import _
 from tempest.openstack.common import local
-# NOTE(flaper87): Pls, remove when graduating this module
-# from the incubator.
-from tempest.openstack.common.strutils import mask_password  # noqa
 
 
 _DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
@@ -124,7 +124,9 @@
                       'qpid=WARN', 'sqlalchemy=WARN', 'suds=INFO',
                       'oslo.messaging=INFO', 'iso8601=WARN',
                       'requests.packages.urllib3.connectionpool=WARN',
-                      'urllib3.connectionpool=WARN']
+                      'urllib3.connectionpool=WARN', 'websocket=WARN',
+                      "keystonemiddleware=WARN", "routes.middleware=WARN",
+                      "stevedore=WARN"]
 
 log_opts = [
     cfg.StrOpt('logging_context_format_string',
@@ -227,6 +229,15 @@
     def audit(self, msg, *args, **kwargs):
         self.log(logging.AUDIT, msg, *args, **kwargs)
 
+    def isEnabledFor(self, level):
+        if _PY26:
+            # This method was added in python 2.7 (and it does the exact
+            # same logic, so we need to do the exact same logic so that
+            # python 2.6 has this capability as well).
+            return self.logger.isEnabledFor(level)
+        else:
+            return super(BaseLoggerAdapter, self).isEnabledFor(level)
+
 
 class LazyAdapter(BaseLoggerAdapter):
     def __init__(self, name='unknown', version='unknown'):
@@ -289,11 +300,10 @@
         self.warn(stdmsg, *args, **kwargs)
 
     def process(self, msg, kwargs):
-        # NOTE(mrodden): catch any Message/other object and
-        #                coerce to unicode before they can get
-        #                to the python logging and possibly
-        #                cause string encoding trouble
-        if not isinstance(msg, six.string_types):
+        # NOTE(jecarey): If msg is not unicode, coerce it into unicode
+        #                before it can get to the python logging and
+        #                possibly cause string encoding trouble
+        if not isinstance(msg, six.text_type):
             msg = six.text_type(msg)
 
         if 'extra' not in kwargs:
@@ -410,18 +420,20 @@
     sys.excepthook = _create_logging_excepthook(product_name)
 
 
-def set_defaults(logging_context_format_string,
+def set_defaults(logging_context_format_string=None,
                  default_log_levels=None):
     # Just in case the caller is not setting the
     # default_log_level. This is insurance because
     # we introduced the default_log_level parameter
     # later in a backwards in-compatible change
-    if default_log_levels is None:
-        default_log_levels = DEFAULT_LOG_LEVELS
-    cfg.set_defaults(
+    if default_log_levels is not None:
+        cfg.set_defaults(
             log_opts,
-            logging_context_format_string=logging_context_format_string,
             default_log_levels=default_log_levels)
+    if logging_context_format_string is not None:
+        cfg.set_defaults(
+            log_opts,
+            logging_context_format_string=logging_context_format_string)
 
 
 def _find_facility_from_conf():
@@ -470,18 +482,6 @@
     for handler in log_root.handlers:
         log_root.removeHandler(handler)
 
-    if CONF.use_syslog:
-        facility = _find_facility_from_conf()
-        # TODO(bogdando) use the format provided by RFCSysLogHandler
-        #   after existing syslog format deprecation in J
-        if CONF.use_syslog_rfc_format:
-            syslog = RFCSysLogHandler(address='/dev/log',
-                                      facility=facility)
-        else:
-            syslog = logging.handlers.SysLogHandler(address='/dev/log',
-                                                    facility=facility)
-        log_root.addHandler(syslog)
-
     logpath = _get_log_file_path()
     if logpath:
         filelog = logging.handlers.WatchedFileHandler(logpath)
@@ -540,6 +540,20 @@
         else:
             logger.setLevel(level_name)
 
+    if CONF.use_syslog:
+        try:
+            facility = _find_facility_from_conf()
+            # TODO(bogdando) use the format provided by RFCSysLogHandler
+            #   after existing syslog format deprecation in J
+            if CONF.use_syslog_rfc_format:
+                syslog = RFCSysLogHandler(facility=facility)
+            else:
+                syslog = logging.handlers.SysLogHandler(facility=facility)
+            log_root.addHandler(syslog)
+        except socket.error:
+            log_root.error('Unable to add syslog handler. Verify that syslog '
+                           'is running.')
+
 
 _loggers = {}
 
@@ -609,6 +623,12 @@
     def format(self, record):
         """Uses contextstring if request_id is set, otherwise default."""
 
+        # NOTE(jecarey): If msg is not unicode, coerce it into unicode
+        #                before it can get to the python logging and
+        #                possibly cause string encoding trouble
+        if not isinstance(record.msg, six.text_type):
+            record.msg = six.text_type(record.msg)
+
         # store project info
         record.project = self.project
         record.version = self.version
diff --git a/tempest/services/volume/json/backups_client.py b/tempest/services/volume/json/backups_client.py
index 63fc646..da47639 100644
--- a/tempest/services/volume/json/backups_client.py
+++ b/tempest/services/volume/json/backups_client.py
@@ -23,13 +23,13 @@
 CONF = config.CONF
 
 
-class BackupsClientJSON(rest_client.RestClient):
+class BaseBackupsClientJSON(rest_client.RestClient):
     """
     Client class to send CRUD Volume backup API requests to a Cinder endpoint
     """
 
     def __init__(self, auth_provider):
-        super(BackupsClientJSON, self).__init__(auth_provider)
+        super(BaseBackupsClientJSON, self).__init__(auth_provider)
         self.service = CONF.volume.catalog_type
         self.build_interval = CONF.volume.build_interval
         self.build_timeout = CONF.volume.build_timeout
@@ -99,3 +99,7 @@
                            'the required time (%s s).' %
                            (backup_id, status, self.build_timeout))
                 raise exceptions.TimeoutException(message)
+
+
+class BackupsClientJSON(BaseBackupsClientJSON):
+    """Volume V1 Backups client"""
diff --git a/tempest/services/volume/v2/json/backups_client.py b/tempest/services/volume/v2/json/backups_client.py
new file mode 100644
index 0000000..9698075
--- /dev/null
+++ b/tempest/services/volume/v2/json/backups_client.py
@@ -0,0 +1,26 @@
+# 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.services.volume.json import backups_client
+
+
+class BackupsClientV2JSON(backups_client.BaseBackupsClientJSON):
+    """
+    Client class to send CRUD Volume V2 API requests to a Cinder endpoint
+    """
+
+    def __init__(self, auth_provider):
+        super(BackupsClientV2JSON, self).__init__(auth_provider)
+        self.api_version = "v2"
diff --git a/tempest/thirdparty/boto/test_ec2_instance_run.py b/tempest/thirdparty/boto/test_ec2_instance_run.py
index f3f11fd..00b17d9 100644
--- a/tempest/thirdparty/boto/test_ec2_instance_run.py
+++ b/tempest/thirdparty/boto/test_ec2_instance_run.py
@@ -306,8 +306,7 @@
 
         volume.detach()
 
-        self.assertVolumeStatusWait(_volume_state, "available")
-        wait.re_search_wait(_volume_state, "available")
+        self.assertVolumeStatusWait(volume, "available")
 
         wait.state_wait(_part_state, 'DECREASE')