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')