diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample index 7ece127c2c..0246488806 100644 --- a/etc/tempest.conf.sample +++ b/etc/tempest.conf.sample @@ -1,17 +1,7 @@ [DEFAULT] # -# From tempest.config -# - -# Whether to disable inter-process locks (boolean value) -#disable_process_locking = false - -# Directory to use for lock files. (string value) -#lock_path = - -# -# From tempest.config +# From oslo.log # # Print debugging output (set logging level to DEBUG instead of @@ -22,10 +12,6 @@ # default WARNING level). (boolean value) #verbose = false -# -# From tempest.config -# - # The name of a logging configuration file. This file is appended to # any existing logging configuration files. For details about logging # configuration files, see the Python logging module documentation. @@ -66,17 +52,9 @@ # Syslog facility to receive log lines. (string value) #syslog_log_facility = LOG_USER -# -# From tempest.config -# - # Log output to standard error. (boolean value) #use_stderr = true -# -# From tempest.config -# - # Format string to use for log messages with context. (string value) #logging_context_format_string = %(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [%(request_id)s %(user_identity)s] %(instance)s%(message)s @@ -92,7 +70,7 @@ #logging_exception_prefix = %(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s # 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,websocket=WARN,keystonemiddleware=WARN,routes.middleware=WARN,stevedore=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,requests.packages.urllib3.util.retry=WARN,urllib3.util.retry=WARN,keystonemiddleware=WARN,routes.middleware=WARN,stevedore=WARN # Enables or disables publication of error events. (boolean value) #publish_errors = false @@ -917,6 +895,24 @@ #max_resources_per_stack = 1000 +[oslo_concurrency] + +# +# From oslo.concurrency +# + +# Enables or disables inter-process locks. (boolean value) +# Deprecated group/name - [DEFAULT]/disable_process_locking +#disable_process_locking = false + +# Directory to use for lock files. For security, the specified +# directory should only be writable by the user running the processes +# that need locking. Defaults to environment variable OSLO_LOCK_PATH. +# If external locks are used, a lock path must be set. (string value) +# Deprecated group/name - [DEFAULT]/lock_path +#lock_path = + + [scenario] # diff --git a/openstack-common.conf b/openstack-common.conf index 5ae2089366..1920295774 100644 --- a/openstack-common.conf +++ b/openstack-common.conf @@ -2,10 +2,6 @@ # The list of modules to copy from openstack-common module=install_venv_common -module=lockutils -module=log -module=importlib -module=fixture module=versionutils # The base module to hold the copy of openstack.common diff --git a/requirements.txt b/requirements.txt index b14af9dffd..f6e30ce5ff 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,7 +19,12 @@ python-ironicclient>=0.2.1 python-saharaclient>=0.7.6 python-swiftclient>=2.2.0 testrepository>=0.0.18 +oslo.concurrency>=1.4.1 # Apache-2.0 oslo.config>=1.6.0 # Apache-2.0 +oslo.i18n>=1.3.0 # Apache-2.0 +oslo.log>=0.4.0 # Apache-2.0 +oslo.serialization>=1.2.0 # Apache-2.0 +oslo.utils>=1.2.0 # Apache-2.0 six>=1.9.0 iso8601>=0.1.9 fixtures>=0.3.14 diff --git a/tempest/api/baremetal/admin/test_nodestates.py b/tempest/api/baremetal/admin/test_nodestates.py index bcb8b7895c..e7b6081246 100644 --- a/tempest/api/baremetal/admin/test_nodestates.py +++ b/tempest/api/baremetal/admin/test_nodestates.py @@ -12,9 +12,10 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_utils import timeutils + from tempest.api.baremetal.admin import base from tempest import exceptions -from tempest.openstack.common import timeutils from tempest import test diff --git a/tempest/api/compute/admin/test_agents.py b/tempest/api/compute/admin/test_agents.py index f801f8a17b..aa29b36639 100644 --- a/tempest/api/compute/admin/test_agents.py +++ b/tempest/api/compute/admin/test_agents.py @@ -12,11 +12,11 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log from tempest_lib.common.utils import data_utils from tempest_lib import exceptions as lib_exc from tempest.api.compute import base -from tempest.openstack.common import log from tempest import test LOG = log.getLogger(__name__) diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py index 773f23e291..bbd47b65a5 100644 --- a/tempest/api/compute/admin/test_quotas.py +++ b/tempest/api/compute/admin/test_quotas.py @@ -13,13 +13,13 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging import six from tempest_lib.common.utils import data_utils from testtools import matchers from tempest.api.compute import base from tempest.common import tempest_fixtures as fixtures -from tempest.openstack.common import log as logging from tempest import test LOG = logging.getLogger(__name__) diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py index 18401f01d8..ddfe6de4c4 100644 --- a/tempest/api/compute/base.py +++ b/tempest/api/compute/base.py @@ -15,6 +15,8 @@ import time +from oslo_log import log as logging +from oslo_utils import excutils from tempest_lib.common.utils import data_utils from tempest_lib import exceptions as lib_exc @@ -22,8 +24,6 @@ from tempest import clients from tempest.common import credentials from tempest import config from tempest import exceptions -from tempest.openstack.common import excutils -from tempest.openstack.common import log as logging import tempest.test CONF = config.CONF diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py index b5edc1d32f..1d26a00c8c 100644 --- a/tempest/api/compute/images/test_images_oneserver.py +++ b/tempest/api/compute/images/test_images_oneserver.py @@ -13,11 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest.api.compute import base from tempest import config -from tempest.openstack.common import log as logging from tempest import test CONF = config.CONF diff --git a/tempest/api/compute/images/test_images_oneserver_negative.py b/tempest/api/compute/images/test_images_oneserver_negative.py index f1de3204be..c75d1dc714 100644 --- a/tempest/api/compute/images/test_images_oneserver_negative.py +++ b/tempest/api/compute/images/test_images_oneserver_negative.py @@ -14,12 +14,12 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest_lib import exceptions as lib_exc from tempest.api.compute import base from tempest import config -from tempest.openstack.common import log as logging from tempest import test CONF = config.CONF diff --git a/tempest/api/compute/images/test_list_image_filters.py b/tempest/api/compute/images/test_list_image_filters.py index f5a98ce473..2c6d2dfa4f 100644 --- a/tempest/api/compute/images/test_list_image_filters.py +++ b/tempest/api/compute/images/test_list_image_filters.py @@ -16,12 +16,12 @@ import StringIO import time +from oslo_log import log as logging from tempest_lib.common.utils import data_utils import testtools from tempest.api.compute import base from tempest import config -from tempest.openstack.common import log as logging from tempest import test CONF = config.CONF diff --git a/tempest/api/compute/test_authorization.py b/tempest/api/compute/test_authorization.py index 6502e70674..2094d83e02 100644 --- a/tempest/api/compute/test_authorization.py +++ b/tempest/api/compute/test_authorization.py @@ -15,13 +15,13 @@ import StringIO +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest_lib import exceptions as lib_exc from tempest.api.compute import base from tempest import clients from tempest import config -from tempest.openstack.common import log as logging from tempest import test CONF = config.CONF diff --git a/tempest/api/compute/test_extensions.py b/tempest/api/compute/test_extensions.py index 1063f90833..5b14071958 100644 --- a/tempest/api/compute/test_extensions.py +++ b/tempest/api/compute/test_extensions.py @@ -13,10 +13,10 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging from tempest.api.compute import base from tempest import config -from tempest.openstack.common import log as logging from tempest import test CONF = config.CONF diff --git a/tempest/api/database/base.py b/tempest/api/database/base.py index 31c5d2a84f..1868f2326c 100644 --- a/tempest/api/database/base.py +++ b/tempest/api/database/base.py @@ -13,8 +13,9 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging + from tempest import config -from tempest.openstack.common import log as logging import tempest.test CONF = config.CONF diff --git a/tempest/api/identity/__init__.py b/tempest/api/identity/__init__.py index 9614b4962d..17efdcc375 100644 --- a/tempest/api/identity/__init__.py +++ b/tempest/api/identity/__init__.py @@ -13,7 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. -from tempest.openstack.common import log as logging +from oslo_log import log as logging LOG = logging.getLogger(__name__) diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py index d9346e9139..9d3d0bc40e 100644 --- a/tempest/api/identity/admin/v3/test_trusts.py +++ b/tempest/api/identity/admin/v3/test_trusts.py @@ -13,6 +13,7 @@ import datetime import re +from oslo_utils import timeutils from tempest_lib.common.utils import data_utils from tempest_lib import exceptions as lib_exc @@ -20,7 +21,6 @@ from tempest.api.identity import base from tempest import clients from tempest.common import cred_provider from tempest import config -from tempest.openstack.common import timeutils from tempest import test CONF = config.CONF diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py index 72a4cbd787..543dea14b1 100644 --- a/tempest/api/identity/base.py +++ b/tempest/api/identity/base.py @@ -13,13 +13,13 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest_lib import exceptions as lib_exc from tempest import clients from tempest.common import cred_provider from tempest import config -from tempest.openstack.common import log as logging import tempest.test CONF = config.CONF diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py index 58d0003d9e..728d0772fc 100644 --- a/tempest/api/image/base.py +++ b/tempest/api/image/base.py @@ -14,13 +14,13 @@ import cStringIO as StringIO +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest_lib import exceptions as lib_exc from tempest import clients from tempest.common import credentials from tempest import config -from tempest.openstack.common import log as logging import tempest.test CONF = config.CONF diff --git a/tempest/api/messaging/base.py b/tempest/api/messaging/base.py index f193e32834..b3ed94182b 100644 --- a/tempest/api/messaging/base.py +++ b/tempest/api/messaging/base.py @@ -13,10 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest import config -from tempest.openstack.common import log as logging from tempest import test CONF = config.CONF diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py index 270f5dd9e8..e057bb8052 100644 --- a/tempest/api/network/base.py +++ b/tempest/api/network/base.py @@ -14,13 +14,13 @@ # under the License. import netaddr +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest_lib import exceptions as lib_exc from tempest import clients from tempest import config from tempest import exceptions -from tempest.openstack.common import log as logging import tempest.test CONF = config.CONF diff --git a/tempest/api/network/test_metering_extensions.py b/tempest/api/network/test_metering_extensions.py index 68aed27282..c712af253f 100644 --- a/tempest/api/network/test_metering_extensions.py +++ b/tempest/api/network/test_metering_extensions.py @@ -12,10 +12,10 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest.api.network import base -from tempest.openstack.common import log as logging from tempest import test diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py index 08fddb5f86..1877bbf5e1 100644 --- a/tempest/api/orchestration/base.py +++ b/tempest/api/orchestration/base.py @@ -12,13 +12,13 @@ import os.path +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest_lib import exceptions as lib_exc import yaml from tempest import clients from tempest import config -from tempest.openstack.common import log as logging import tempest.test CONF = config.CONF diff --git a/tempest/api/orchestration/stacks/test_soft_conf.py b/tempest/api/orchestration/stacks/test_soft_conf.py index 697c6ee86c..649bf470b2 100644 --- a/tempest/api/orchestration/stacks/test_soft_conf.py +++ b/tempest/api/orchestration/stacks/test_soft_conf.py @@ -10,12 +10,12 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest_lib import exceptions as lib_exc from tempest.api.orchestration import base from tempest import config -from tempest.openstack.common import log as logging from tempest import test LOG = logging.getLogger(__name__) diff --git a/tempest/api/orchestration/stacks/test_stacks.py b/tempest/api/orchestration/stacks/test_stacks.py index 3e61de4a6f..147f456bde 100644 --- a/tempest/api/orchestration/stacks/test_stacks.py +++ b/tempest/api/orchestration/stacks/test_stacks.py @@ -10,10 +10,10 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest.api.orchestration import base -from tempest.openstack.common import log as logging from tempest import test diff --git a/tempest/api/telemetry/base.py b/tempest/api/telemetry/base.py index fff04fb7e0..336e2d41c7 100644 --- a/tempest/api/telemetry/base.py +++ b/tempest/api/telemetry/base.py @@ -12,12 +12,12 @@ import time +from oslo_utils import timeutils from tempest_lib.common.utils import data_utils from tempest_lib import exceptions as lib_exc from tempest import config from tempest import exceptions -from tempest.openstack.common import timeutils import tempest.test CONF = config.CONF diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py index 09ec075c2b..ad5eb7db70 100644 --- a/tempest/api/volume/admin/test_multi_backend.py +++ b/tempest/api/volume/admin/test_multi_backend.py @@ -10,11 +10,11 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest.api.volume import base from tempest import config -from tempest.openstack.common import log as logging from tempest import test CONF = config.CONF diff --git a/tempest/api/volume/admin/test_volumes_backup.py b/tempest/api/volume/admin/test_volumes_backup.py index 986e9862ed..6fd2a5ea28 100644 --- a/tempest/api/volume/admin/test_volumes_backup.py +++ b/tempest/api/volume/admin/test_volumes_backup.py @@ -13,11 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest.api.volume import base from tempest import config -from tempest.openstack.common import log as logging from tempest import test CONF = config.CONF diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py index e5cff23e0e..8f3f1a3a28 100644 --- a/tempest/api/volume/base.py +++ b/tempest/api/volume/base.py @@ -13,13 +13,13 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest_lib import exceptions as lib_exc from tempest import clients from tempest import config from tempest import exceptions -from tempest.openstack.common import log as logging import tempest.test CONF = config.CONF diff --git a/tempest/api/volume/test_extensions.py b/tempest/api/volume/test_extensions.py index e5fe3c847b..e8ff5e012d 100644 --- a/tempest/api/volume/test_extensions.py +++ b/tempest/api/volume/test_extensions.py @@ -13,10 +13,10 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging from tempest.api.volume import base from tempest import config -from tempest.openstack.common import log as logging from tempest import test CONF = config.CONF diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py index b5bf362b5f..29e3324dda 100644 --- a/tempest/api/volume/test_volumes_list.py +++ b/tempest/api/volume/test_volumes_list.py @@ -15,11 +15,11 @@ # under the License. import operator +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from testtools import matchers from tempest.api.volume import base -from tempest.openstack.common import log as logging from tempest import test LOG = logging.getLogger(__name__) diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py index 9a72e9011e..955fbcf3a6 100644 --- a/tempest/api/volume/test_volumes_snapshots.py +++ b/tempest/api/volume/test_volumes_snapshots.py @@ -10,11 +10,11 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest.api.volume import base from tempest import config -from tempest.openstack.common import log as logging from tempest import test LOG = logging.getLogger(__name__) diff --git a/tempest/auth.py b/tempest/auth.py index 9d8341cd9c..d7f9adbb35 100644 --- a/tempest/auth.py +++ b/tempest/auth.py @@ -22,7 +22,7 @@ import urlparse import six -from tempest.openstack.common import log as logging +from oslo_log import log as logging from tempest.services.identity.v2.json import token_client as json_v2id from tempest.services.identity.v3.json import token_client as json_v3id diff --git a/tempest/cli/simple_read_only/image/test_glance.py b/tempest/cli/simple_read_only/image/test_glance.py index 3d7126b37b..e38ca483e7 100644 --- a/tempest/cli/simple_read_only/image/test_glance.py +++ b/tempest/cli/simple_read_only/image/test_glance.py @@ -15,11 +15,11 @@ import re +from oslo_log import log as logging from tempest_lib import exceptions from tempest import cli from tempest import config -from tempest.openstack.common import log as logging from tempest import test CONF = config.CONF diff --git a/tempest/cli/simple_read_only/network/test_neutron.py b/tempest/cli/simple_read_only/network/test_neutron.py index 8af8ada556..e8b3554075 100644 --- a/tempest/cli/simple_read_only/network/test_neutron.py +++ b/tempest/cli/simple_read_only/network/test_neutron.py @@ -15,11 +15,11 @@ import re +from oslo_log import log as logging from tempest_lib import exceptions from tempest import cli from tempest import config -from tempest.openstack.common import log as logging from tempest import test CONF = config.CONF diff --git a/tempest/cli/simple_read_only/orchestration/test_heat.py b/tempest/cli/simple_read_only/orchestration/test_heat.py index 7751e2cc52..8defe51a24 100644 --- a/tempest/cli/simple_read_only/orchestration/test_heat.py +++ b/tempest/cli/simple_read_only/orchestration/test_heat.py @@ -13,11 +13,11 @@ import json import os +from oslo_log import log as logging import yaml import tempest.cli from tempest import config -from tempest.openstack.common import log as logging from tempest import test CONF = config.CONF diff --git a/tempest/cli/simple_read_only/telemetry/test_ceilometer.py b/tempest/cli/simple_read_only/telemetry/test_ceilometer.py index 85db596009..b5e570bbf6 100644 --- a/tempest/cli/simple_read_only/telemetry/test_ceilometer.py +++ b/tempest/cli/simple_read_only/telemetry/test_ceilometer.py @@ -13,9 +13,10 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging + from tempest import cli from tempest import config -from tempest.openstack.common import log as logging from tempest import test CONF = config.CONF diff --git a/tempest/clients.py b/tempest/clients.py index e5f41ebbf4..9bd5738839 100644 --- a/tempest/clients.py +++ b/tempest/clients.py @@ -15,11 +15,12 @@ import copy +from oslo_log import log as logging + from tempest.common import cred_provider from tempest.common import negative_rest_client from tempest import config from tempest import manager -from tempest.openstack.common import log as logging from tempest.services.baremetal.v1.json.baremetal_client import \ BaremetalClientJSON from tempest.services import botoclients diff --git a/tempest/cmd/cleanup.py b/tempest/cmd/cleanup.py index 669f506a5d..ed6716e488 100755 --- a/tempest/cmd/cleanup.py +++ b/tempest/cmd/cleanup.py @@ -54,11 +54,12 @@ import argparse import json import sys +from oslo_log import log as logging + from tempest import clients from tempest.cmd import cleanup_service from tempest.common import cred_provider from tempest import config -from tempest.openstack.common import log as logging SAVED_STATE_JSON = "saved_state.json" DRY_RUN_JSON = "dry_run.json" diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py index 7b217bb290..1ad12ebb9a 100644 --- a/tempest/cmd/cleanup_service.py +++ b/tempest/cmd/cleanup_service.py @@ -14,9 +14,10 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging + from tempest import clients from tempest import config -from tempest.openstack.common import log as logging from tempest import test LOG = logging.getLogger(__name__) diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py index 4c09bd2c30..0735eeb0da 100755 --- a/tempest/cmd/javelin.py +++ b/tempest/cmd/javelin.py @@ -110,13 +110,13 @@ import sys import unittest import netaddr +from oslo_log import log as logging +from oslo_utils import timeutils from tempest_lib import exceptions as lib_exc import yaml import tempest.auth from tempest import config -from tempest.openstack.common import log as logging -from tempest.openstack.common import timeutils from tempest.services.compute.json import flavors_client from tempest.services.compute.json import security_groups_client from tempest.services.compute.json import servers_client @@ -1038,7 +1038,7 @@ def get_options(): def setup_logging(): global LOG - logging.setup(__name__) + logging.setup(CONF, __name__) LOG = logging.getLogger(__name__) diff --git a/tempest/cmd/run_stress.py b/tempest/cmd/run_stress.py index d21a4413bc..2bed355a95 100755 --- a/tempest/cmd/run_stress.py +++ b/tempest/cmd/run_stress.py @@ -26,7 +26,7 @@ except ImportError: from testtools import testsuite -from tempest.openstack.common import log as logging +from oslo_log import log as logging from tempest.stress import driver LOG = logging.getLogger(__name__) diff --git a/tempest/common/accounts.py b/tempest/common/accounts.py index 8766e7d122..c8b2b930b0 100644 --- a/tempest/common/accounts.py +++ b/tempest/common/accounts.py @@ -15,13 +15,13 @@ import hashlib import os +from oslo_concurrency import lockutils +from oslo_log import log as logging import yaml from tempest.common import cred_provider from tempest import config from tempest import exceptions -from tempest.openstack.common import lockutils -from tempest.openstack.common import log as logging CONF = config.CONF LOG = logging.getLogger(__name__) @@ -45,7 +45,14 @@ class Accounts(cred_provider.CredentialProvider): accounts = {} self.use_default_creds = True self.hash_dict = self.get_hash_dict(accounts) - self.accounts_dir = os.path.join(CONF.lock_path, 'test_accounts') + # FIXME(dhellmann): The configuration option is not part of + # the API of the library, because if we change the option name + # or group it will break this use. Tempest needs to set this + # value somewhere that it owns, and then use + # lockutils.set_defaults() to tell oslo.concurrency what value + # to use. + self.accounts_dir = os.path.join(CONF.oslo_concurrency.lock_path, + 'test_accounts') self.isolated_creds = {} @classmethod diff --git a/tempest/common/commands.py b/tempest/common/commands.py index e68c20e4b3..392c9d0650 100644 --- a/tempest/common/commands.py +++ b/tempest/common/commands.py @@ -15,7 +15,7 @@ import shlex import subprocess -from tempest.openstack.common import log as logging +from oslo_log import log as logging LOG = logging.getLogger(__name__) diff --git a/tempest/common/cred_provider.py b/tempest/common/cred_provider.py index ea628f6516..6be1b6b056 100644 --- a/tempest/common/cred_provider.py +++ b/tempest/common/cred_provider.py @@ -14,12 +14,12 @@ import abc +from oslo_log import log as logging import six from tempest import auth from tempest import config from tempest import exceptions -from tempest.openstack.common import log as logging CONF = config.CONF LOG = logging.getLogger(__name__) diff --git a/tempest/common/generator/base_generator.py b/tempest/common/generator/base_generator.py index 3f405b1710..f81f4055d6 100644 --- a/tempest/common/generator/base_generator.py +++ b/tempest/common/generator/base_generator.py @@ -18,7 +18,7 @@ import functools import jsonschema -from tempest.openstack.common import log as logging +from oslo_log import log as logging LOG = logging.getLogger(__name__) diff --git a/tempest/common/generator/negative_generator.py b/tempest/common/generator/negative_generator.py index 1d5ed43928..17997a520b 100644 --- a/tempest/common/generator/negative_generator.py +++ b/tempest/common/generator/negative_generator.py @@ -15,9 +15,10 @@ import copy +from oslo_log import log as logging + import tempest.common.generator.base_generator as base import tempest.common.generator.valid_generator as valid -from tempest.openstack.common import log as logging LOG = logging.getLogger(__name__) diff --git a/tempest/common/generator/valid_generator.py b/tempest/common/generator/valid_generator.py index 7b80afc6c2..0c63bf517f 100644 --- a/tempest/common/generator/valid_generator.py +++ b/tempest/common/generator/valid_generator.py @@ -13,8 +13,9 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging + import tempest.common.generator.base_generator as base -from tempest.openstack.common import log as logging LOG = logging.getLogger(__name__) diff --git a/tempest/common/glance_http.py b/tempest/common/glance_http.py index dd1448adaa..c6b8ba3f86 100644 --- a/tempest/common/glance_http.py +++ b/tempest/common/glance_http.py @@ -28,11 +28,11 @@ import urlparse import OpenSSL +from oslo_log import log as logging from six import moves from tempest_lib import exceptions as lib_exc from tempest import exceptions as exc -from tempest.openstack.common import log as logging LOG = logging.getLogger(__name__) USER_AGENT = 'tempest' diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py index ca2bd653a6..5f582c1bfd 100644 --- a/tempest/common/isolated_creds.py +++ b/tempest/common/isolated_creds.py @@ -13,6 +13,7 @@ # under the License. import netaddr +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest_lib import exceptions as lib_exc @@ -20,7 +21,6 @@ from tempest import clients from tempest.common import cred_provider from tempest import config from tempest import exceptions -from tempest.openstack.common import log as logging CONF = config.CONF LOG = logging.getLogger(__name__) diff --git a/tempest/common/ssh.py b/tempest/common/ssh.py index c06ce3b110..fe67ff802c 100644 --- a/tempest/common/ssh.py +++ b/tempest/common/ssh.py @@ -20,10 +20,10 @@ import socket import time import warnings +from oslo_log import log as logging import six from tempest import exceptions -from tempest.openstack.common import log as logging with warnings.catch_warnings(): diff --git a/tempest/common/tempest_fixtures.py b/tempest/common/tempest_fixtures.py index b33f354429..d416857ae6 100644 --- a/tempest/common/tempest_fixtures.py +++ b/tempest/common/tempest_fixtures.py @@ -13,7 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. -from tempest.openstack.common.fixture import lockutils +from oslo_concurrency.fixture import lockutils class LockFixture(lockutils.LockFixture): diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py index 6d50b67a0d..64ff7f2c30 100644 --- a/tempest/common/waiters.py +++ b/tempest/common/waiters.py @@ -13,11 +13,11 @@ import time +from oslo_log import log as logging from tempest_lib.common.utils import misc as misc_utils from tempest import config from tempest import exceptions -from tempest.openstack.common import log as logging CONF = config.CONF LOG = logging.getLogger(__name__) diff --git a/tempest/config.py b/tempest/config.py index 0ff7ba72c1..c459d76afd 100644 --- a/tempest/config.py +++ b/tempest/config.py @@ -18,10 +18,9 @@ from __future__ import print_function import logging as std_logging import os -from oslo.config import cfg +from oslo_config import cfg -from tempest.openstack.common import lockutils -from tempest.openstack.common import log as logging +from oslo_log import log as logging def register_opt_group(conf, opt_group, options): @@ -1102,16 +1101,7 @@ def list_opts(): The purpose of this is to allow tools like the Oslo sample config file generator to discover the options exposed to users. """ - optlist = [(g.name, o) for g, o in _opts] - - # NOTE(jgrimm): Can be removed once oslo-incubator/oslo changes happen. - optlist.append((None, lockutils.util_opts)) - optlist.append((None, logging.common_cli_opts)) - optlist.append((None, logging.logging_cli_opts)) - optlist.append((None, logging.generic_log_opts)) - optlist.append((None, logging.log_opts)) - - return optlist + return [(g.name, o) for g, o in _opts] # this should never be called outside of this class @@ -1190,11 +1180,12 @@ class TempestConfigPrivate(object): # to remove an issue with the config file up to date checker. if parse_conf: config_files.append(path) + logging.register_options(cfg.CONF) if os.path.isfile(path): cfg.CONF([], project='tempest', default_config_files=config_files) else: cfg.CONF([], project='tempest') - logging.setup('tempest') + logging.setup(cfg.CONF, 'tempest') LOG = logging.getLogger('tempest') LOG.info("Using tempest config file %s" % path) register_opts() @@ -1208,16 +1199,15 @@ class TempestConfigProxy(object): _path = None _extra_log_defaults = [ - 'keystoneclient.session=INFO', - 'paramiko.transport=INFO', - 'requests.packages.urllib3.connectionpool=WARN' + ('keystoneclient.session', std_logging.INFO), + ('paramiko.transport', std_logging.INFO), + ('requests.packages.urllib3.connectionpool', std_logging.WARN), ] def _fix_log_levels(self): """Tweak the oslo log defaults.""" - for opt in logging.log_opts: - if opt.dest == 'default_log_levels': - opt.default.extend(self._extra_log_defaults) + for name, level in self._extra_log_defaults: + std_logging.getLogger(name).setLevel(level) def __getattr__(self, attr): if not self._config: diff --git a/tempest/openstack/common/_i18n.py b/tempest/openstack/common/_i18n.py index fdc8327adc..5bbc77d3b3 100644 --- a/tempest/openstack/common/_i18n.py +++ b/tempest/openstack/common/_i18n.py @@ -17,14 +17,14 @@ See http://docs.openstack.org/developer/oslo.i18n/usage.html """ try: - import oslo.i18n + 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') + _translators = oslo_i18n.TranslatorFactory(domain='tempest') # The primary translation function using the well-known name "_" _ = _translators.primary @@ -40,6 +40,6 @@ try: _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 + # code from oslo-incubator, but is not ready to be internationalized # (like tempest) _ = _LI = _LW = _LE = _LC = lambda x: x diff --git a/tempest/openstack/common/excutils.py b/tempest/openstack/common/excutils.py deleted file mode 100644 index dc365da5ac..0000000000 --- a/tempest/openstack/common/excutils.py +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# Copyright 2012, Red Hat, Inc. -# -# 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. - -""" -Exception related utilities. -""" - -import logging -import sys -import time -import traceback - -import six - -from tempest.openstack.common.gettextutils import _ - - -class save_and_reraise_exception(object): - """Save current exception, run some code and then re-raise. - - In some cases the exception context can be cleared, resulting in None - being attempted to be re-raised after an exception handler is run. This - can happen when eventlet switches greenthreads or when running an - exception handler, code raises and catches an exception. In both - cases the exception context will be cleared. - - To work around this, we save the exception state, run handler code, and - then re-raise the original exception. If another exception occurs, the - saved exception is logged and the new exception is re-raised. - - In some cases the caller may not want to re-raise the exception, and - for those circumstances this context provides a reraise flag that - can be used to suppress the exception. For example:: - - except Exception: - with save_and_reraise_exception() as ctxt: - decide_if_need_reraise() - if not should_be_reraised: - ctxt.reraise = False - """ - def __init__(self): - self.reraise = True - - def __enter__(self): - self.type_, self.value, self.tb, = sys.exc_info() - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - if exc_type is not None: - logging.error(_('Original exception being dropped: %s'), - traceback.format_exception(self.type_, - self.value, - self.tb)) - return False - if self.reraise: - six.reraise(self.type_, self.value, self.tb) - - -def forever_retry_uncaught_exceptions(infunc): - def inner_func(*args, **kwargs): - last_log_time = 0 - last_exc_message = None - exc_count = 0 - while True: - try: - return infunc(*args, **kwargs) - except Exception as exc: - this_exc_message = six.u(str(exc)) - if this_exc_message == last_exc_message: - exc_count += 1 - else: - exc_count = 1 - # Do not log any more frequently than once a minute unless - # the exception message changes - cur_time = int(time.time()) - if (cur_time - last_log_time > 60 or - this_exc_message != last_exc_message): - logging.exception( - _('Unexpected exception occurred %d time(s)... ' - 'retrying.') % exc_count) - last_log_time = cur_time - last_exc_message = this_exc_message - exc_count = 0 - # This should be a very rare event. In case it isn't, do - # a sleep. - time.sleep(1) - return inner_func diff --git a/tempest/openstack/common/fileutils.py b/tempest/openstack/common/fileutils.py deleted file mode 100644 index 1845ed2a85..0000000000 --- a/tempest/openstack/common/fileutils.py +++ /dev/null @@ -1,137 +0,0 @@ -# Copyright 2011 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 contextlib -import errno -import os -import tempfile - -from tempest.openstack.common import excutils -from tempest.openstack.common.gettextutils import _ -from tempest.openstack.common import log as logging - -LOG = logging.getLogger(__name__) - -_FILE_CACHE = {} - - -def ensure_tree(path): - """Create a directory (and any ancestor directories required) - - :param path: Directory to create - """ - try: - os.makedirs(path) - except OSError as exc: - if exc.errno == errno.EEXIST: - if not os.path.isdir(path): - raise - else: - raise - - -def read_cached_file(filename, force_reload=False): - """Read from a file if it has been modified. - - :param force_reload: Whether to reload the file. - :returns: A tuple with a boolean specifying if the data is fresh - or not. - """ - global _FILE_CACHE - - if force_reload and filename in _FILE_CACHE: - del _FILE_CACHE[filename] - - reloaded = False - mtime = os.path.getmtime(filename) - cache_info = _FILE_CACHE.setdefault(filename, {}) - - if not cache_info or mtime > cache_info.get('mtime', 0): - LOG.debug(_("Reloading cached file %s") % filename) - with open(filename) as fap: - cache_info['data'] = fap.read() - cache_info['mtime'] = mtime - reloaded = True - return (reloaded, cache_info['data']) - - -def delete_if_exists(path, remove=os.unlink): - """Delete a file, but ignore file not found error. - - :param path: File to delete - :param remove: Optional function to remove passed path - """ - - try: - remove(path) - except OSError as e: - if e.errno != errno.ENOENT: - raise - - -@contextlib.contextmanager -def remove_path_on_error(path, remove=delete_if_exists): - """Protect code that wants to operate on PATH atomically. - Any exception will cause PATH to be removed. - - :param path: File to work with - :param remove: Optional function to remove passed path - """ - - try: - yield - except Exception: - with excutils.save_and_reraise_exception(): - remove(path) - - -def file_open(*args, **kwargs): - """Open file - - see built-in file() documentation for more details - - Note: The reason this is kept in a separate module is to easily - be able to provide a stub module that doesn't alter system - state at all (for unit tests) - """ - return file(*args, **kwargs) - - -def write_to_tempfile(content, path=None, suffix='', prefix='tmp'): - """Create temporary file or use existing file. - - This util is needed for creating temporary file with - specified content, suffix and prefix. If path is not None, - it will be used for writing content. If the path doesn't - exist it'll be created. - - :param content: content for temporary file. - :param path: same as parameter 'dir' for mkstemp - :param suffix: same as parameter 'suffix' for mkstemp - :param prefix: same as parameter 'prefix' for mkstemp - - For example: it can be used in database tests for creating - configuration files. - """ - if path: - ensure_tree(path) - - (fd, path) = tempfile.mkstemp(suffix=suffix, dir=path, prefix=prefix) - try: - os.write(fd, content) - finally: - os.close(fd) - return path diff --git a/tempest/openstack/common/fixture/__init__.py b/tempest/openstack/common/fixture/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tempest/openstack/common/fixture/config.py b/tempest/openstack/common/fixture/config.py deleted file mode 100644 index 0bf90ff7a0..0000000000 --- a/tempest/openstack/common/fixture/config.py +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright 2013 Mirantis, Inc. -# Copyright 2013 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 fixtures -from oslo.config import cfg -import six - - -class Config(fixtures.Fixture): - """Override some configuration values. - - The keyword arguments are the names of configuration options to - override and their values. - - If a group argument is supplied, the overrides are applied to - the specified configuration option group. - - All overrides are automatically cleared at the end of the current - test by the reset() method, which is registered by addCleanup(). - """ - - def __init__(self, conf=cfg.CONF): - self.conf = conf - - def setUp(self): - super(Config, self).setUp() - self.addCleanup(self.conf.reset) - - def config(self, **kw): - group = kw.pop('group', None) - for k, v in six.iteritems(kw): - self.conf.set_override(k, v, group) diff --git a/tempest/openstack/common/fixture/lockutils.py b/tempest/openstack/common/fixture/lockutils.py deleted file mode 100644 index 593668734c..0000000000 --- a/tempest/openstack/common/fixture/lockutils.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2011 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 fixtures - -from tempest.openstack.common import lockutils - - -class LockFixture(fixtures.Fixture): - """External locking fixture. - - This fixture is basically an alternative to the synchronized decorator with - the external flag so that tearDowns and addCleanups will be included in - the lock context for locking between tests. The fixture is recommended to - be the first line in a test method, like so:: - - def test_method(self): - self.useFixture(LockFixture) - ... - - or the first line in setUp if all the test methods in the class are - required to be serialized. Something like:: - - class TestCase(testtools.testcase): - def setUp(self): - self.useFixture(LockFixture) - super(TestCase, self).setUp() - ... - - This is because addCleanups are put on a LIFO queue that gets run after the - test method exits. (either by completing or raising an exception) - """ - def __init__(self, name, lock_file_prefix=None): - self.mgr = lockutils.lock(name, lock_file_prefix, True) - - def setUp(self): - super(LockFixture, self).setUp() - self.addCleanup(self.mgr.__exit__, None, None, None) - self.mgr.__enter__() diff --git a/tempest/openstack/common/fixture/mockpatch.py b/tempest/openstack/common/fixture/mockpatch.py deleted file mode 100644 index d7dcc117ba..0000000000 --- a/tempest/openstack/common/fixture/mockpatch.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# Copyright 2013 Hewlett-Packard Development Company, L.P. -# 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 fixtures -import mock - - -class PatchObject(fixtures.Fixture): - """Deal with code around mock.""" - - def __init__(self, obj, attr, new=mock.DEFAULT, **kwargs): - self.obj = obj - self.attr = attr - self.kwargs = kwargs - self.new = new - - def setUp(self): - super(PatchObject, self).setUp() - _p = mock.patch.object(self.obj, self.attr, self.new, **self.kwargs) - self.mock = _p.start() - self.addCleanup(_p.stop) - - -class Patch(fixtures.Fixture): - - """Deal with code around mock.patch.""" - - def __init__(self, obj, **kwargs): - self.obj = obj - self.kwargs = kwargs - - def setUp(self): - super(Patch, self).setUp() - _p = mock.patch(self.obj, **self.kwargs) - self.mock = _p.start() - self.addCleanup(_p.stop) diff --git a/tempest/openstack/common/fixture/moxstubout.py b/tempest/openstack/common/fixture/moxstubout.py deleted file mode 100644 index e8c031f08a..0000000000 --- a/tempest/openstack/common/fixture/moxstubout.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# Copyright 2013 Hewlett-Packard Development Company, L.P. -# 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 fixtures -import mox - - -class MoxStubout(fixtures.Fixture): - """Deal with code around mox and stubout as a fixture.""" - - def setUp(self): - super(MoxStubout, self).setUp() - # emulate some of the mox stuff, we can't use the metaclass - # because it screws with our generators - self.mox = mox.Mox() - self.stubs = self.mox.stubs - self.addCleanup(self.mox.UnsetStubs) - self.addCleanup(self.mox.VerifyAll) diff --git a/tempest/openstack/common/gettextutils.py b/tempest/openstack/common/gettextutils.py deleted file mode 100644 index 872d58ea51..0000000000 --- a/tempest/openstack/common/gettextutils.py +++ /dev/null @@ -1,479 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# 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. - -""" -gettext for openstack-common modules. - -Usual usage in an openstack.common module: - - from tempest.openstack.common.gettextutils import _ -""" - -import copy -import gettext -import locale -from logging import handlers -import os - -from babel import localedata -import six - -_AVAILABLE_LANGUAGES = {} - -# FIXME(dhellmann): Remove this when moving to oslo.i18n. -USE_LAZY = False - - -class TranslatorFactory(object): - """Create translator functions - """ - - def __init__(self, domain, localedir=None): - """Establish a set of translation functions for the domain. - - :param domain: Name of translation domain, - specifying a message catalog. - :type domain: str - :param lazy: Delays translation until a message is emitted. - Defaults to False. - :type lazy: Boolean - :param localedir: Directory with translation catalogs. - :type localedir: str - """ - self.domain = domain - if localedir is None: - localedir = os.environ.get(domain.upper() + '_LOCALEDIR') - self.localedir = localedir - - def _make_translation_func(self, domain=None): - """Return a new translation function ready for use. - - Takes into account whether or not lazy translation is being - done. - - The domain can be specified to override the default from the - factory, but the localedir from the factory is always used - because we assume the log-level translation catalogs are - installed in the same directory as the main application - catalog. - - """ - if domain is None: - domain = self.domain - t = gettext.translation(domain, - localedir=self.localedir, - fallback=True) - # Use the appropriate method of the translation object based - # on the python version. - m = t.gettext if six.PY3 else t.ugettext - - def f(msg): - """oslo.i18n.gettextutils translation function.""" - if USE_LAZY: - return Message(msg, domain=domain) - return m(msg) - return f - - @property - def primary(self): - "The default translation function." - return self._make_translation_func() - - def _make_log_translation_func(self, level): - return self._make_translation_func(self.domain + '-log-' + level) - - @property - def log_info(self): - "Translate info-level log messages." - return self._make_log_translation_func('info') - - @property - def log_warning(self): - "Translate warning-level log messages." - return self._make_log_translation_func('warning') - - @property - def log_error(self): - "Translate error-level log messages." - return self._make_log_translation_func('error') - - @property - def log_critical(self): - "Translate critical-level log messages." - return self._make_log_translation_func('critical') - - -# NOTE(dhellmann): When this module moves out of the incubator into -# oslo.i18n, these global variables can be moved to an integration -# module within each application. - -# Create the global translation functions. -_translators = TranslatorFactory('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 - -# NOTE(dhellmann): End of globals that will move to the application's -# integration module. - - -def enable_lazy(): - """Convenience function for configuring _() to use lazy gettext - - Call this at the start of execution to enable the gettextutils._ - function to use lazy gettext functionality. This is useful if - your project is importing _ directly instead of using the - gettextutils.install() way of importing the _ function. - """ - global USE_LAZY - USE_LAZY = True - - -def install(domain): - """Install a _() function using the given translation domain. - - Given a translation domain, install a _() function using gettext's - install() function. - - The main difference from gettext.install() is that we allow - overriding the default localedir (e.g. /usr/share/locale) using - a translation-domain-specific environment variable (e.g. - NOVA_LOCALEDIR). - - Note that to enable lazy translation, enable_lazy must be - called. - - :param domain: the translation domain - """ - from six import moves - tf = TranslatorFactory(domain) - moves.builtins.__dict__['_'] = tf.primary - - -class Message(six.text_type): - """A Message object is a unicode object that can be translated. - - Translation of Message is done explicitly using the translate() method. - For all non-translation intents and purposes, a Message is simply unicode, - and can be treated as such. - """ - - def __new__(cls, msgid, msgtext=None, params=None, - domain='tempest', *args): - """Create a new Message object. - - In order for translation to work gettext requires a message ID, this - msgid will be used as the base unicode text. It is also possible - for the msgid and the base unicode text to be different by passing - the msgtext parameter. - """ - # If the base msgtext is not given, we use the default translation - # of the msgid (which is in English) just in case the system locale is - # not English, so that the base text will be in that locale by default. - if not msgtext: - msgtext = Message._translate_msgid(msgid, domain) - # We want to initialize the parent unicode with the actual object that - # would have been plain unicode if 'Message' was not enabled. - msg = super(Message, cls).__new__(cls, msgtext) - msg.msgid = msgid - msg.domain = domain - msg.params = params - return msg - - def translate(self, desired_locale=None): - """Translate this message to the desired locale. - - :param desired_locale: The desired locale to translate the message to, - if no locale is provided the message will be - translated to the system's default locale. - - :returns: the translated message in unicode - """ - - translated_message = Message._translate_msgid(self.msgid, - self.domain, - desired_locale) - if self.params is None: - # No need for more translation - return translated_message - - # This Message object may have been formatted with one or more - # Message objects as substitution arguments, given either as a single - # argument, part of a tuple, or as one or more values in a dictionary. - # When translating this Message we need to translate those Messages too - translated_params = _translate_args(self.params, desired_locale) - - translated_message = translated_message % translated_params - - return translated_message - - @staticmethod - def _translate_msgid(msgid, domain, desired_locale=None): - if not desired_locale: - system_locale = locale.getdefaultlocale() - # If the system locale is not available to the runtime use English - if not system_locale[0]: - desired_locale = 'en_US' - else: - desired_locale = system_locale[0] - - locale_dir = os.environ.get(domain.upper() + '_LOCALEDIR') - lang = gettext.translation(domain, - localedir=locale_dir, - languages=[desired_locale], - fallback=True) - if six.PY3: - translator = lang.gettext - else: - translator = lang.ugettext - - translated_message = translator(msgid) - return translated_message - - def __mod__(self, other): - # When we mod a Message we want the actual operation to be performed - # by the parent class (i.e. unicode()), the only thing we do here is - # save the original msgid and the parameters in case of a translation - params = self._sanitize_mod_params(other) - unicode_mod = super(Message, self).__mod__(params) - modded = Message(self.msgid, - msgtext=unicode_mod, - params=params, - domain=self.domain) - return modded - - def _sanitize_mod_params(self, other): - """Sanitize the object being modded with this Message. - - - Add support for modding 'None' so translation supports it - - Trim the modded object, which can be a large dictionary, to only - those keys that would actually be used in a translation - - Snapshot the object being modded, in case the message is - translated, it will be used as it was when the Message was created - """ - if other is None: - params = (other,) - elif isinstance(other, dict): - # Merge the dictionaries - # Copy each item in case one does not support deep copy. - params = {} - if isinstance(self.params, dict): - for key, val in self.params.items(): - params[key] = self._copy_param(val) - for key, val in other.items(): - params[key] = self._copy_param(val) - else: - params = self._copy_param(other) - return params - - def _copy_param(self, param): - try: - return copy.deepcopy(param) - except Exception: - # Fallback to casting to unicode this will handle the - # python code-like objects that can't be deep-copied - return six.text_type(param) - - def __add__(self, other): - msg = _('Message objects do not support addition.') - raise TypeError(msg) - - def __radd__(self, other): - return self.__add__(other) - - if six.PY2: - def __str__(self): - # NOTE(luisg): Logging in python 2.6 tries to str() log records, - # and it expects specifically a UnicodeError in order to proceed. - msg = _('Message objects do not support str() because they may ' - 'contain non-ascii characters. ' - 'Please use unicode() or translate() instead.') - raise UnicodeError(msg) - - -def get_available_languages(domain): - """Lists the available languages for the given translation domain. - - :param domain: the domain to get languages for - """ - if domain in _AVAILABLE_LANGUAGES: - return copy.copy(_AVAILABLE_LANGUAGES[domain]) - - localedir = '%s_LOCALEDIR' % domain.upper() - find = lambda x: gettext.find(domain, - localedir=os.environ.get(localedir), - languages=[x]) - - # NOTE(mrodden): en_US should always be available (and first in case - # order matters) since our in-line message strings are en_US - language_list = ['en_US'] - # NOTE(luisg): Babel <1.0 used a function called list(), which was - # renamed to locale_identifiers() in >=1.0, the requirements master list - # requires >=0.9.6, uncapped, so defensively work with both. We can remove - # this check when the master list updates to >=1.0, and update all projects - list_identifiers = (getattr(localedata, 'list', None) or - getattr(localedata, 'locale_identifiers')) - locale_identifiers = list_identifiers() - - for i in locale_identifiers: - if find(i) is not None: - language_list.append(i) - - # NOTE(luisg): Babel>=1.0,<1.3 has a bug where some OpenStack supported - # locales (e.g. 'zh_CN', and 'zh_TW') aren't supported even though they - # are perfectly legitimate locales: - # https://github.com/mitsuhiko/babel/issues/37 - # In Babel 1.3 they fixed the bug and they support these locales, but - # they are still not explicitly "listed" by locale_identifiers(). - # That is why we add the locales here explicitly if necessary so that - # they are listed as supported. - aliases = {'zh': 'zh_CN', - 'zh_Hant_HK': 'zh_HK', - 'zh_Hant': 'zh_TW', - 'fil': 'tl_PH'} - for (locale_, alias) in six.iteritems(aliases): - if locale_ in language_list and alias not in language_list: - language_list.append(alias) - - _AVAILABLE_LANGUAGES[domain] = language_list - return copy.copy(language_list) - - -def translate(obj, desired_locale=None): - """Gets the translated unicode representation of the given object. - - If the object is not translatable it is returned as-is. - If the locale is None the object is translated to the system locale. - - :param obj: the object to translate - :param desired_locale: the locale to translate the message to, if None the - default system locale will be used - :returns: the translated object in unicode, or the original object if - it could not be translated - """ - message = obj - if not isinstance(message, Message): - # If the object to translate is not already translatable, - # let's first get its unicode representation - message = six.text_type(obj) - if isinstance(message, Message): - # Even after unicoding() we still need to check if we are - # running with translatable unicode before translating - return message.translate(desired_locale) - return obj - - -def _translate_args(args, desired_locale=None): - """Translates all the translatable elements of the given arguments object. - - This method is used for translating the translatable values in method - arguments which include values of tuples or dictionaries. - If the object is not a tuple or a dictionary the object itself is - translated if it is translatable. - - If the locale is None the object is translated to the system locale. - - :param args: the args to translate - :param desired_locale: the locale to translate the args to, if None the - default system locale will be used - :returns: a new args object with the translated contents of the original - """ - if isinstance(args, tuple): - return tuple(translate(v, desired_locale) for v in args) - if isinstance(args, dict): - translated_dict = {} - for (k, v) in six.iteritems(args): - translated_v = translate(v, desired_locale) - translated_dict[k] = translated_v - return translated_dict - return translate(args, desired_locale) - - -class TranslationHandler(handlers.MemoryHandler): - """Handler that translates records before logging them. - - The TranslationHandler takes a locale and a target logging.Handler object - to forward LogRecord objects to after translating them. This handler - depends on Message objects being logged, instead of regular strings. - - The handler can be configured declaratively in the logging.conf as follows: - - [handlers] - keys = translatedlog, translator - - [handler_translatedlog] - class = handlers.WatchedFileHandler - args = ('/var/log/api-localized.log',) - formatter = context - - [handler_translator] - class = openstack.common.log.TranslationHandler - target = translatedlog - args = ('zh_CN',) - - If the specified locale is not available in the system, the handler will - log in the default locale. - """ - - def __init__(self, locale=None, target=None): - """Initialize a TranslationHandler - - :param locale: locale to use for translating messages - :param target: logging.Handler object to forward - LogRecord objects to after translation - """ - # NOTE(luisg): In order to allow this handler to be a wrapper for - # other handlers, such as a FileHandler, and still be able to - # configure it using logging.conf, this handler has to extend - # MemoryHandler because only the MemoryHandlers' logging.conf - # parsing is implemented such that it accepts a target handler. - handlers.MemoryHandler.__init__(self, capacity=0, target=target) - self.locale = locale - - def setFormatter(self, fmt): - self.target.setFormatter(fmt) - - def emit(self, record): - # We save the message from the original record to restore it - # after translation, so other handlers are not affected by this - original_msg = record.msg - original_args = record.args - - try: - self._translate_and_log_record(record) - finally: - record.msg = original_msg - record.args = original_args - - def _translate_and_log_record(self, record): - record.msg = translate(record.msg, self.locale) - - # In addition to translating the message, we also need to translate - # arguments that were passed to the log method that were not part - # of the main message e.g., log.info(_('Some message %s'), this_one)) - record.args = _translate_args(record.args, self.locale) - - self.target.emit(record) diff --git a/tempest/openstack/common/importutils.py b/tempest/openstack/common/importutils.py deleted file mode 100644 index d5dd22f628..0000000000 --- a/tempest/openstack/common/importutils.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright 2011 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 related utilities and helper functions. -""" - -import sys -import traceback - - -def import_class(import_str): - """Returns a class from a string including module and class.""" - mod_str, _sep, class_str = import_str.rpartition('.') - __import__(mod_str) - try: - return getattr(sys.modules[mod_str], class_str) - except AttributeError: - raise ImportError('Class %s cannot be found (%s)' % - (class_str, - traceback.format_exception(*sys.exc_info()))) - - -def import_object(import_str, *args, **kwargs): - """Import a class and return an instance of it.""" - return import_class(import_str)(*args, **kwargs) - - -def import_object_ns(name_space, import_str, *args, **kwargs): - """Tries to import object from default namespace. - - Imports a class and return an instance of it, first by trying - to find the class in a default namespace, then failing back to - a full path if not found in the default namespace. - """ - import_value = "%s.%s" % (name_space, import_str) - try: - return import_class(import_value)(*args, **kwargs) - except ImportError: - return import_class(import_str)(*args, **kwargs) - - -def import_module(import_str): - """Import a module.""" - __import__(import_str) - return sys.modules[import_str] - - -def import_versioned_module(version, submodule=None): - module = 'tempest.v%s' % version - if submodule: - module = '.'.join((module, submodule)) - return import_module(module) - - -def try_import(import_str, default=None): - """Try to import a module and if it fails return default.""" - try: - return import_module(import_str) - except ImportError: - return default diff --git a/tempest/openstack/common/jsonutils.py b/tempest/openstack/common/jsonutils.py deleted file mode 100644 index cb83557fee..0000000000 --- a/tempest/openstack/common/jsonutils.py +++ /dev/null @@ -1,190 +0,0 @@ -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# Copyright 2011 Justin Santa Barbara -# 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. - -''' -JSON related utilities. - -This module provides a few things: - - 1) A handy function for getting an object down to something that can be - JSON serialized. See to_primitive(). - - 2) Wrappers around loads() and dumps(). The dumps() wrapper will - automatically use to_primitive() for you if needed. - - 3) This sets up anyjson to use the loads() and dumps() wrappers if anyjson - is available. -''' - - -import codecs -import datetime -import functools -import inspect -import itertools -import sys - -if sys.version_info < (2, 7): - # On Python <= 2.6, json module is not C boosted, so try to use - # simplejson module if available - try: - import simplejson as json - except ImportError: - import json -else: - import json - -import six -import six.moves.xmlrpc_client as xmlrpclib - -from tempest.openstack.common import gettextutils -from tempest.openstack.common import importutils -from tempest.openstack.common import strutils -from tempest.openstack.common import timeutils - -netaddr = importutils.try_import("netaddr") - -_nasty_type_tests = [inspect.ismodule, inspect.isclass, inspect.ismethod, - inspect.isfunction, inspect.isgeneratorfunction, - inspect.isgenerator, inspect.istraceback, inspect.isframe, - inspect.iscode, inspect.isbuiltin, inspect.isroutine, - inspect.isabstract] - -_simple_types = (six.string_types + six.integer_types - + (type(None), bool, float)) - - -def to_primitive(value, convert_instances=False, convert_datetime=True, - level=0, max_depth=3): - """Convert a complex object into primitives. - - Handy for JSON serialization. We can optionally handle instances, - but since this is a recursive function, we could have cyclical - data structures. - - To handle cyclical data structures we could track the actual objects - visited in a set, but not all objects are hashable. Instead we just - track the depth of the object inspections and don't go too deep. - - Therefore, convert_instances=True is lossy ... be aware. - - """ - # handle obvious types first - order of basic types determined by running - # full tests on nova project, resulting in the following counts: - # 572754 - # 460353 - # 379632 - # 274610 - # 199918 - # 114200 - # 51817 - # 26164 - # 6491 - # 283 - # 19 - if isinstance(value, _simple_types): - return value - - if isinstance(value, datetime.datetime): - if convert_datetime: - return timeutils.strtime(value) - else: - return value - - # value of itertools.count doesn't get caught by nasty_type_tests - # and results in infinite loop when list(value) is called. - if type(value) == itertools.count: - return six.text_type(value) - - # FIXME(vish): Workaround for LP bug 852095. Without this workaround, - # tests that raise an exception in a mocked method that - # has a @wrap_exception with a notifier will fail. If - # we up the dependency to 0.5.4 (when it is released) we - # can remove this workaround. - if getattr(value, '__module__', None) == 'mox': - return 'mock' - - if level > max_depth: - return '?' - - # The try block may not be necessary after the class check above, - # but just in case ... - try: - recursive = functools.partial(to_primitive, - convert_instances=convert_instances, - convert_datetime=convert_datetime, - level=level, - max_depth=max_depth) - if isinstance(value, dict): - return dict((k, recursive(v)) for k, v in six.iteritems(value)) - elif isinstance(value, (list, tuple)): - return [recursive(lv) for lv in value] - - # It's not clear why xmlrpclib created their own DateTime type, but - # for our purposes, make it a datetime type which is explicitly - # handled - if isinstance(value, xmlrpclib.DateTime): - value = datetime.datetime(*tuple(value.timetuple())[:6]) - - if convert_datetime and isinstance(value, datetime.datetime): - return timeutils.strtime(value) - elif isinstance(value, gettextutils.Message): - return value.data - elif hasattr(value, 'iteritems'): - return recursive(dict(value.iteritems()), level=level + 1) - elif hasattr(value, '__iter__'): - return recursive(list(value)) - elif convert_instances and hasattr(value, '__dict__'): - # Likely an instance of something. Watch for cycles. - # Ignore class member vars. - return recursive(value.__dict__, level=level + 1) - elif netaddr and isinstance(value, netaddr.IPAddress): - return six.text_type(value) - else: - if any(test(value) for test in _nasty_type_tests): - return six.text_type(value) - return value - except TypeError: - # Class objects are tricky since they may define something like - # __iter__ defined but it isn't callable as list(). - return six.text_type(value) - - -def dumps(value, default=to_primitive, **kwargs): - return json.dumps(value, default=default, **kwargs) - - -def dump(obj, fp, *args, **kwargs): - return json.dump(obj, fp, *args, **kwargs) - - -def loads(s, encoding='utf-8', **kwargs): - return json.loads(strutils.safe_decode(s, encoding), **kwargs) - - -def load(fp, encoding='utf-8', **kwargs): - return json.load(codecs.getreader(encoding)(fp), **kwargs) - - -try: - import anyjson -except ImportError: - pass -else: - anyjson._modules.append((__name__, 'dumps', TypeError, - 'loads', ValueError, 'load')) - anyjson.force_implementation(__name__) diff --git a/tempest/openstack/common/local.py b/tempest/openstack/common/local.py deleted file mode 100644 index 0819d5b97c..0000000000 --- a/tempest/openstack/common/local.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2011 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. - -"""Local storage of variables using weak references""" - -import threading -import weakref - - -class WeakLocal(threading.local): - def __getattribute__(self, attr): - rval = super(WeakLocal, self).__getattribute__(attr) - if rval: - # NOTE(mikal): this bit is confusing. What is stored is a weak - # reference, not the value itself. We therefore need to lookup - # the weak reference and return the inner value here. - rval = rval() - return rval - - def __setattr__(self, attr, value): - value = weakref.ref(value) - return super(WeakLocal, self).__setattr__(attr, value) - - -# NOTE(mikal): the name "store" should be deprecated in the future -store = WeakLocal() - -# A "weak" store uses weak references and allows an object to fall out of scope -# when it falls out of scope in the code that uses the thread local storage. A -# "strong" store will hold a reference to the object so that it never falls out -# of scope. -weak_store = WeakLocal() -strong_store = threading.local() diff --git a/tempest/openstack/common/lockutils.py b/tempest/openstack/common/lockutils.py deleted file mode 100644 index 53cada1b0c..0000000000 --- a/tempest/openstack/common/lockutils.py +++ /dev/null @@ -1,303 +0,0 @@ -# Copyright 2011 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 contextlib -import errno -import functools -import os -import shutil -import subprocess -import sys -import tempfile -import threading -import time -import weakref - -from oslo.config import cfg - -from tempest.openstack.common import fileutils -from tempest.openstack.common.gettextutils import _ -from tempest.openstack.common import local -from tempest.openstack.common import log as logging - - -LOG = logging.getLogger(__name__) - - -util_opts = [ - cfg.BoolOpt('disable_process_locking', default=False, - help='Whether to disable inter-process locks'), - cfg.StrOpt('lock_path', - default=os.environ.get("TEMPEST_LOCK_PATH"), - help=('Directory to use for lock files.')) -] - - -CONF = cfg.CONF -CONF.register_opts(util_opts) - - -def set_defaults(lock_path): - cfg.set_defaults(util_opts, lock_path=lock_path) - - -class _InterProcessLock(object): - """Lock implementation which allows multiple locks, working around - issues like bugs.debian.org/cgi-bin/bugreport.cgi?bug=632857 and does - not require any cleanup. Since the lock is always held on a file - descriptor rather than outside of the process, the lock gets dropped - automatically if the process crashes, even if __exit__ is not executed. - - There are no guarantees regarding usage by multiple green threads in a - single process here. This lock works only between processes. Exclusive - access between local threads should be achieved using the semaphores - in the @synchronized decorator. - - Note these locks are released when the descriptor is closed, so it's not - safe to close the file descriptor while another green thread holds the - lock. Just opening and closing the lock file can break synchronisation, - so lock files must be accessed only using this abstraction. - """ - - def __init__(self, name): - self.lockfile = None - self.fname = name - - def __enter__(self): - self.lockfile = open(self.fname, 'w') - - while True: - try: - # Using non-blocking locks since green threads are not - # patched to deal with blocking locking calls. - # Also upon reading the MSDN docs for locking(), it seems - # to have a laughable 10 attempts "blocking" mechanism. - self.trylock() - return self - except IOError as e: - if e.errno in (errno.EACCES, errno.EAGAIN): - # external locks synchronise things like iptables - # updates - give it some time to prevent busy spinning - time.sleep(0.01) - else: - raise - - def __exit__(self, exc_type, exc_val, exc_tb): - try: - self.unlock() - self.lockfile.close() - except IOError: - LOG.exception(_("Could not release the acquired lock `%s`"), - self.fname) - - def trylock(self): - raise NotImplementedError() - - def unlock(self): - raise NotImplementedError() - - -class _WindowsLock(_InterProcessLock): - def trylock(self): - msvcrt.locking(self.lockfile.fileno(), msvcrt.LK_NBLCK, 1) - - def unlock(self): - msvcrt.locking(self.lockfile.fileno(), msvcrt.LK_UNLCK, 1) - - -class _PosixLock(_InterProcessLock): - def trylock(self): - fcntl.lockf(self.lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB) - - def unlock(self): - fcntl.lockf(self.lockfile, fcntl.LOCK_UN) - - -if os.name == 'nt': - import msvcrt - InterProcessLock = _WindowsLock -else: - import fcntl - InterProcessLock = _PosixLock - -_semaphores = weakref.WeakValueDictionary() -_semaphores_lock = threading.Lock() - - -@contextlib.contextmanager -def lock(name, lock_file_prefix=None, external=False, lock_path=None): - """Context based lock - - This function yields a `threading.Semaphore` instance (if we don't use - eventlet.monkey_patch(), else `semaphore.Semaphore`) unless external is - True, in which case, it'll yield an InterProcessLock instance. - - :param lock_file_prefix: The lock_file_prefix argument is used to provide - lock files on disk with a meaningful prefix. - - :param external: The external keyword argument denotes whether this lock - should work across multiple processes. This means that if two different - workers both run a a method decorated with @synchronized('mylock', - external=True), only one of them will execute at a time. - - :param lock_path: The lock_path keyword argument is used to specify a - special location for external lock files to live. If nothing is set, then - CONF.lock_path is used as a default. - """ - with _semaphores_lock: - try: - sem = _semaphores[name] - except KeyError: - sem = threading.Semaphore() - _semaphores[name] = sem - - with sem: - LOG.debug(_('Got semaphore "%(lock)s"'), {'lock': name}) - - # NOTE(mikal): I know this looks odd - if not hasattr(local.strong_store, 'locks_held'): - local.strong_store.locks_held = [] - local.strong_store.locks_held.append(name) - - try: - if external and not CONF.disable_process_locking: - LOG.debug(_('Attempting to grab file lock "%(lock)s"'), - {'lock': name}) - - # We need a copy of lock_path because it is non-local - local_lock_path = lock_path or CONF.lock_path - if not local_lock_path: - raise cfg.RequiredOptError('lock_path') - - if not os.path.exists(local_lock_path): - fileutils.ensure_tree(local_lock_path) - LOG.info(_('Created lock path: %s'), local_lock_path) - - def add_prefix(name, prefix): - if not prefix: - return name - sep = '' if prefix.endswith('-') else '-' - return '%s%s%s' % (prefix, sep, name) - - # NOTE(mikal): the lock name cannot contain directory - # separators - lock_file_name = add_prefix(name.replace(os.sep, '_'), - lock_file_prefix) - - lock_file_path = os.path.join(local_lock_path, lock_file_name) - - try: - lock = InterProcessLock(lock_file_path) - with lock as lock: - LOG.debug(_('Got file lock "%(lock)s" at %(path)s'), - {'lock': name, 'path': lock_file_path}) - yield lock - finally: - LOG.debug(_('Released file lock "%(lock)s" at %(path)s'), - {'lock': name, 'path': lock_file_path}) - else: - yield sem - - finally: - local.strong_store.locks_held.remove(name) - - -def synchronized(name, lock_file_prefix=None, external=False, lock_path=None): - """Synchronization decorator. - - Decorating a method like so:: - - @synchronized('mylock') - def foo(self, *args): - ... - - ensures that only one thread will execute the foo method at a time. - - Different methods can share the same lock:: - - @synchronized('mylock') - def foo(self, *args): - ... - - @synchronized('mylock') - def bar(self, *args): - ... - - This way only one of either foo or bar can be executing at a time. - """ - - def wrap(f): - @functools.wraps(f) - def inner(*args, **kwargs): - try: - with lock(name, lock_file_prefix, external, lock_path): - LOG.debug(_('Got semaphore / lock "%(function)s"'), - {'function': f.__name__}) - return f(*args, **kwargs) - finally: - LOG.debug(_('Semaphore / lock released "%(function)s"'), - {'function': f.__name__}) - return inner - return wrap - - -def synchronized_with_prefix(lock_file_prefix): - """Partial object generator for the synchronization decorator. - - Redefine @synchronized in each project like so:: - - (in nova/utils.py) - from nova.openstack.common import lockutils - - synchronized = lockutils.synchronized_with_prefix('nova-') - - - (in nova/foo.py) - from nova import utils - - @utils.synchronized('mylock') - def bar(self, *args): - ... - - The lock_file_prefix argument is used to provide lock files on disk with a - meaningful prefix. - """ - - return functools.partial(synchronized, lock_file_prefix=lock_file_prefix) - - -def main(argv): - """Create a dir for locks and pass it to command from arguments - - If you run this: - python -m openstack.common.lockutils python setup.py testr - - a temporary directory will be created for all your locks and passed to all - your tests in an environment variable. The temporary dir will be deleted - afterwards and the return value will be preserved. - """ - - lock_dir = tempfile.mkdtemp() - os.environ["TEMPEST_LOCK_PATH"] = lock_dir - try: - ret_val = subprocess.call(argv[1:]) - finally: - shutil.rmtree(lock_dir, ignore_errors=True) - return ret_val - - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/tempest/openstack/common/log.py b/tempest/openstack/common/log.py deleted file mode 100644 index 26cd6ad0b4..0000000000 --- a/tempest/openstack/common/log.py +++ /dev/null @@ -1,710 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# 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. - -"""OpenStack logging handler. - -This module adds to logging functionality by adding the option to specify -a context object when calling the various log methods. If the context object -is not specified, default formatting is used. Additionally, an instance uuid -may be passed as part of the log message, which is intended to make it easier -for admins to find messages related to a specific instance. - -It also allows setting of formatting information through conf. - -""" - -import inspect -import itertools -import logging -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 - -_PY26 = sys.version_info[0:2] == (2, 6) - -from tempest.openstack.common._i18n import _ -from tempest.openstack.common import local - - -_DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S" - - -common_cli_opts = [ - cfg.BoolOpt('debug', - short='d', - default=False, - help='Print debugging output (set logging level to ' - 'DEBUG instead of default WARNING level).'), - cfg.BoolOpt('verbose', - short='v', - default=False, - help='Print more verbose output (set logging level to ' - 'INFO instead of default WARNING level).'), -] - -logging_cli_opts = [ - cfg.StrOpt('log-config-append', - metavar='PATH', - deprecated_name='log-config', - help='The name of a logging configuration file. This file ' - 'is appended to any existing logging configuration ' - 'files. For details about logging configuration files, ' - 'see the Python logging module documentation.'), - cfg.StrOpt('log-format', - metavar='FORMAT', - help='DEPRECATED. ' - 'A logging.Formatter log message format string which may ' - 'use any of the available logging.LogRecord attributes. ' - 'This option is deprecated. Please use ' - 'logging_context_format_string and ' - 'logging_default_format_string instead.'), - cfg.StrOpt('log-date-format', - default=_DEFAULT_LOG_DATE_FORMAT, - metavar='DATE_FORMAT', - help='Format string for %%(asctime)s in log records. ' - 'Default: %(default)s .'), - cfg.StrOpt('log-file', - metavar='PATH', - deprecated_name='logfile', - help='(Optional) Name of log file to output to. ' - 'If no default is set, logging will go to stdout.'), - cfg.StrOpt('log-dir', - deprecated_name='logdir', - help='(Optional) The base directory used for relative ' - '--log-file paths.'), - cfg.BoolOpt('use-syslog', - default=False, - help='Use syslog for logging. ' - 'Existing syslog format is DEPRECATED during I, ' - 'and will change in J to honor RFC5424.'), - cfg.BoolOpt('use-syslog-rfc-format', - # TODO(bogdando) remove or use True after existing - # syslog format deprecation in J - default=False, - help='(Optional) Enables or disables syslog rfc5424 format ' - 'for logging. If enabled, prefixes the MSG part of the ' - 'syslog message with APP-NAME (RFC5424). The ' - 'format without the APP-NAME is deprecated in I, ' - 'and will be removed in J.'), - cfg.StrOpt('syslog-log-facility', - default='LOG_USER', - help='Syslog facility to receive log lines.') -] - -generic_log_opts = [ - cfg.BoolOpt('use_stderr', - default=True, - help='Log output to standard error.') -] - -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"] - -log_opts = [ - cfg.StrOpt('logging_context_format_string', - default='%(asctime)s.%(msecs)03d %(process)d %(levelname)s ' - '%(name)s [%(request_id)s %(user_identity)s] ' - '%(instance)s%(message)s', - help='Format string to use for log messages with context.'), - cfg.StrOpt('logging_default_format_string', - default='%(asctime)s.%(msecs)03d %(process)d %(levelname)s ' - '%(name)s [-] %(instance)s%(message)s', - help='Format string to use for log messages without context.'), - cfg.StrOpt('logging_debug_format_suffix', - default='%(funcName)s %(pathname)s:%(lineno)d', - help='Data to append to log format when level is DEBUG.'), - cfg.StrOpt('logging_exception_prefix', - default='%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s ' - '%(instance)s', - help='Prefix each line of exception output with this format.'), - cfg.ListOpt('default_log_levels', - default=DEFAULT_LOG_LEVELS, - help='List of logger=LEVEL pairs.'), - cfg.BoolOpt('publish_errors', - default=False, - help='Enables or disables publication of error events.'), - cfg.BoolOpt('fatal_deprecations', - default=False, - help='Enables or disables fatal status of deprecations.'), - - # NOTE(mikal): there are two options here because sometimes we are handed - # a full instance (and could include more information), and other times we - # are just handed a UUID for the instance. - cfg.StrOpt('instance_format', - default='[instance: %(uuid)s] ', - help='The format for an instance that is passed with the log ' - 'message.'), - cfg.StrOpt('instance_uuid_format', - default='[instance: %(uuid)s] ', - help='The format for an instance UUID that is passed with the ' - 'log message.'), -] - -CONF = cfg.CONF -CONF.register_cli_opts(common_cli_opts) -CONF.register_cli_opts(logging_cli_opts) -CONF.register_opts(generic_log_opts) -CONF.register_opts(log_opts) - -# our new audit level -# NOTE(jkoelker) Since we synthesized an audit level, make the logging -# module aware of it so it acts like other levels. -logging.AUDIT = logging.INFO + 1 -logging.addLevelName(logging.AUDIT, 'AUDIT') - - -try: - NullHandler = logging.NullHandler -except AttributeError: # NOTE(jkoelker) NullHandler added in Python 2.7 - class NullHandler(logging.Handler): - def handle(self, record): - pass - - def emit(self, record): - pass - - def createLock(self): - self.lock = None - - -def _dictify_context(context): - if context is None: - return None - if not isinstance(context, dict) and getattr(context, 'to_dict', None): - context = context.to_dict() - return context - - -def _get_binary_name(): - return os.path.basename(inspect.stack()[-1][1]) - - -def _get_log_file_path(binary=None): - logfile = CONF.log_file - logdir = CONF.log_dir - - if logfile and not logdir: - return logfile - - if logfile and logdir: - return os.path.join(logdir, logfile) - - if logdir: - binary = binary or _get_binary_name() - return '%s.log' % (os.path.join(logdir, binary),) - - return None - - -class BaseLoggerAdapter(logging.LoggerAdapter): - - 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'): - self._logger = None - self.extra = {} - self.name = name - self.version = version - - @property - def logger(self): - if not self._logger: - self._logger = getLogger(self.name, self.version) - if six.PY3: - # In Python 3, the code fails because the 'manager' attribute - # cannot be found when using a LoggerAdapter as the - # underlying logger. Work around this issue. - self._logger.manager = self._logger.logger.manager - return self._logger - - -class ContextAdapter(BaseLoggerAdapter): - warn = logging.LoggerAdapter.warning - - def __init__(self, logger, project_name, version_string): - self.logger = logger - self.project = project_name - self.version = version_string - self._deprecated_messages_sent = dict() - - @property - def handlers(self): - return self.logger.handlers - - def deprecated(self, msg, *args, **kwargs): - """Call this method when a deprecated feature is used. - - If the system is configured for fatal deprecations then the message - is logged at the 'critical' level and :class:`DeprecatedConfig` will - be raised. - - Otherwise, the message will be logged (once) at the 'warn' level. - - :raises: :class:`DeprecatedConfig` if the system is configured for - fatal deprecations. - - """ - stdmsg = _("Deprecated: %s") % msg - if CONF.fatal_deprecations: - self.critical(stdmsg, *args, **kwargs) - raise DeprecatedConfig(msg=stdmsg) - - # Using a list because a tuple with dict can't be stored in a set. - sent_args = self._deprecated_messages_sent.setdefault(msg, list()) - - if args in sent_args: - # Already logged this message, so don't log it again. - return - - sent_args.append(args) - self.warn(stdmsg, *args, **kwargs) - - def process(self, msg, kwargs): - # 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: - kwargs['extra'] = {} - extra = kwargs['extra'] - - context = kwargs.pop('context', None) - if not context: - context = getattr(local.store, 'context', None) - if context: - extra.update(_dictify_context(context)) - - instance = kwargs.pop('instance', None) - instance_uuid = (extra.get('instance_uuid') or - kwargs.pop('instance_uuid', None)) - instance_extra = '' - if instance: - instance_extra = CONF.instance_format % instance - elif instance_uuid: - instance_extra = (CONF.instance_uuid_format - % {'uuid': instance_uuid}) - extra['instance'] = instance_extra - - extra.setdefault('user_identity', kwargs.pop('user_identity', None)) - - extra['project'] = self.project - extra['version'] = self.version - extra['extra'] = extra.copy() - return msg, kwargs - - -class JSONFormatter(logging.Formatter): - def __init__(self, fmt=None, datefmt=None): - # NOTE(jkoelker) we ignore the fmt argument, but its still there - # since logging.config.fileConfig passes it. - self.datefmt = datefmt - - def formatException(self, ei, strip_newlines=True): - lines = traceback.format_exception(*ei) - if strip_newlines: - lines = [moves.filter( - lambda x: x, - line.rstrip().splitlines()) for line in lines] - lines = list(itertools.chain(*lines)) - return lines - - def format(self, record): - message = {'message': record.getMessage(), - 'asctime': self.formatTime(record, self.datefmt), - 'name': record.name, - 'msg': record.msg, - 'args': record.args, - 'levelname': record.levelname, - 'levelno': record.levelno, - 'pathname': record.pathname, - 'filename': record.filename, - 'module': record.module, - 'lineno': record.lineno, - 'funcname': record.funcName, - 'created': record.created, - 'msecs': record.msecs, - 'relative_created': record.relativeCreated, - 'thread': record.thread, - 'thread_name': record.threadName, - 'process_name': record.processName, - 'process': record.process, - 'traceback': None} - - if hasattr(record, 'extra'): - message['extra'] = record.extra - - if record.exc_info: - message['traceback'] = self.formatException(record.exc_info) - - return jsonutils.dumps(message) - - -def _create_logging_excepthook(product_name): - def logging_excepthook(exc_type, value, tb): - extra = {'exc_info': (exc_type, value, tb)} - getLogger(product_name).critical( - "".join(traceback.format_exception_only(exc_type, value)), - **extra) - return logging_excepthook - - -class LogConfigError(Exception): - - message = _('Error loading logging config %(log_config)s: %(err_msg)s') - - def __init__(self, log_config, err_msg): - self.log_config = log_config - self.err_msg = err_msg - - def __str__(self): - return self.message % dict(log_config=self.log_config, - err_msg=self.err_msg) - - -def _load_log_config(log_config_append): - try: - logging.config.fileConfig(log_config_append, - disable_existing_loggers=False) - except (moves.configparser.Error, KeyError) as exc: - raise LogConfigError(log_config_append, six.text_type(exc)) - - -def setup(product_name, version='unknown'): - """Setup logging.""" - if CONF.log_config_append: - _load_log_config(CONF.log_config_append) - else: - _setup_logging_from_conf(product_name, version) - sys.excepthook = _create_logging_excepthook(product_name) - - -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 not None: - cfg.set_defaults( - log_opts, - 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(): - facility_names = logging.handlers.SysLogHandler.facility_names - facility = getattr(logging.handlers.SysLogHandler, - CONF.syslog_log_facility, - None) - - if facility is None and CONF.syslog_log_facility in facility_names: - facility = facility_names.get(CONF.syslog_log_facility) - - if facility is None: - valid_facilities = facility_names.keys() - consts = ['LOG_AUTH', 'LOG_AUTHPRIV', 'LOG_CRON', 'LOG_DAEMON', - 'LOG_FTP', 'LOG_KERN', 'LOG_LPR', 'LOG_MAIL', 'LOG_NEWS', - 'LOG_AUTH', 'LOG_SYSLOG', 'LOG_USER', 'LOG_UUCP', - 'LOG_LOCAL0', 'LOG_LOCAL1', 'LOG_LOCAL2', 'LOG_LOCAL3', - 'LOG_LOCAL4', 'LOG_LOCAL5', 'LOG_LOCAL6', 'LOG_LOCAL7'] - valid_facilities.extend(consts) - raise TypeError(_('syslog facility must be one of: %s') % - ', '.join("'%s'" % fac - for fac in valid_facilities)) - - return facility - - -class RFCSysLogHandler(logging.handlers.SysLogHandler): - def __init__(self, *args, **kwargs): - self.binary_name = _get_binary_name() - # Do not use super() unless type(logging.handlers.SysLogHandler) - # is 'type' (Python 2.7). - # Use old style calls, if the type is 'classobj' (Python 2.6) - logging.handlers.SysLogHandler.__init__(self, *args, **kwargs) - - def format(self, record): - # Do not use super() unless type(logging.handlers.SysLogHandler) - # is 'type' (Python 2.7). - # Use old style calls, if the type is 'classobj' (Python 2.6) - msg = logging.handlers.SysLogHandler.format(self, record) - msg = self.binary_name + ' ' + msg - return msg - - -def _setup_logging_from_conf(project, version): - log_root = getLogger(None).logger - for handler in log_root.handlers: - log_root.removeHandler(handler) - - logpath = _get_log_file_path() - if logpath: - filelog = logging.handlers.WatchedFileHandler(logpath) - log_root.addHandler(filelog) - - if CONF.use_stderr: - streamlog = ColorHandler() - log_root.addHandler(streamlog) - - elif not logpath: - # pass sys.stdout as a positional argument - # python2.6 calls the argument strm, in 2.7 it's stream - streamlog = logging.StreamHandler(sys.stdout) - log_root.addHandler(streamlog) - - if CONF.publish_errors: - try: - handler = importutils.import_object( - "tempest.openstack.common.log_handler.PublishErrorsHandler", - logging.ERROR) - except ImportError: - handler = importutils.import_object( - "oslo.messaging.notify.log_handler.PublishErrorsHandler", - logging.ERROR) - log_root.addHandler(handler) - - datefmt = CONF.log_date_format - for handler in log_root.handlers: - # NOTE(alaski): CONF.log_format overrides everything currently. This - # should be deprecated in favor of context aware formatting. - if CONF.log_format: - handler.setFormatter(logging.Formatter(fmt=CONF.log_format, - datefmt=datefmt)) - log_root.info('Deprecated: log_format is now deprecated and will ' - 'be removed in the next release') - else: - handler.setFormatter(ContextFormatter(project=project, - version=version, - datefmt=datefmt)) - - if CONF.debug: - log_root.setLevel(logging.DEBUG) - elif CONF.verbose: - log_root.setLevel(logging.INFO) - else: - log_root.setLevel(logging.WARNING) - - for pair in CONF.default_log_levels: - mod, _sep, level_name = pair.partition('=') - logger = logging.getLogger(mod) - # NOTE(AAzza) in python2.6 Logger.setLevel doesn't convert string name - # to integer code. - if sys.version_info < (2, 7): - level = logging.getLevelName(level_name) - logger.setLevel(level) - 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 = {} - - -def getLogger(name='unknown', version='unknown'): - if name not in _loggers: - _loggers[name] = ContextAdapter(logging.getLogger(name), - name, - version) - return _loggers[name] - - -def getLazyLogger(name='unknown', version='unknown'): - """Returns lazy logger. - - Creates a pass-through logger that does not create the real logger - until it is really needed and delegates all calls to the real logger - once it is created. - """ - return LazyAdapter(name, version) - - -class WritableLogger(object): - """A thin wrapper that responds to `write` and logs.""" - - def __init__(self, logger, level=logging.INFO): - self.logger = logger - self.level = level - - def write(self, msg): - self.logger.log(self.level, msg.rstrip()) - - -class ContextFormatter(logging.Formatter): - """A context.RequestContext aware formatter configured through flags. - - The flags used to set format strings are: logging_context_format_string - and logging_default_format_string. You can also specify - logging_debug_format_suffix to append extra formatting if the log level is - debug. - - For information about what variables are available for the formatter see: - http://docs.python.org/library/logging.html#formatter - - If available, uses the context value stored in TLS - local.store.context - - """ - - def __init__(self, *args, **kwargs): - """Initialize ContextFormatter instance - - Takes additional keyword arguments which can be used in the message - format string. - - :keyword project: project name - :type project: string - :keyword version: project version - :type version: string - - """ - - self.project = kwargs.pop('project', 'unknown') - self.version = kwargs.pop('version', 'unknown') - - logging.Formatter.__init__(self, *args, **kwargs) - - 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 - - # store request info - context = getattr(local.store, 'context', None) - if context: - d = _dictify_context(context) - for k, v in d.items(): - setattr(record, k, v) - - # NOTE(sdague): default the fancier formatting params - # to an empty string so we don't throw an exception if - # they get used - for key in ('instance', 'color', 'user_identity'): - if key not in record.__dict__: - record.__dict__[key] = '' - - if record.__dict__.get('request_id'): - fmt = CONF.logging_context_format_string - else: - fmt = CONF.logging_default_format_string - - if (record.levelno == logging.DEBUG and - CONF.logging_debug_format_suffix): - fmt += " " + CONF.logging_debug_format_suffix - - if sys.version_info < (3, 2): - self._fmt = fmt - else: - self._style = logging.PercentStyle(fmt) - self._fmt = self._style._fmt - # Cache this on the record, Logger will respect our formatted copy - if record.exc_info: - record.exc_text = self.formatException(record.exc_info, record) - return logging.Formatter.format(self, record) - - def formatException(self, exc_info, record=None): - """Format exception output with CONF.logging_exception_prefix.""" - if not record: - return logging.Formatter.formatException(self, exc_info) - - stringbuffer = moves.StringIO() - traceback.print_exception(exc_info[0], exc_info[1], exc_info[2], - None, stringbuffer) - lines = stringbuffer.getvalue().split('\n') - stringbuffer.close() - - if CONF.logging_exception_prefix.find('%(asctime)') != -1: - record.asctime = self.formatTime(record, self.datefmt) - - formatted_lines = [] - for line in lines: - pl = CONF.logging_exception_prefix % record.__dict__ - fl = '%s%s' % (pl, line) - formatted_lines.append(fl) - return '\n'.join(formatted_lines) - - -class ColorHandler(logging.StreamHandler): - LEVEL_COLORS = { - logging.DEBUG: '\033[00;32m', # GREEN - logging.INFO: '\033[00;36m', # CYAN - logging.AUDIT: '\033[01;36m', # BOLD CYAN - logging.WARN: '\033[01;33m', # BOLD YELLOW - logging.ERROR: '\033[01;31m', # BOLD RED - logging.CRITICAL: '\033[01;31m', # BOLD RED - } - - def format(self, record): - record.color = self.LEVEL_COLORS[record.levelno] - return logging.StreamHandler.format(self, record) - - -class DeprecatedConfig(Exception): - message = _("Fatal call to deprecated config: %(msg)s") - - def __init__(self, msg): - super(Exception, self).__init__(self.message % dict(msg=msg)) diff --git a/tempest/openstack/common/strutils.py b/tempest/openstack/common/strutils.py deleted file mode 100644 index 605cc029e9..0000000000 --- a/tempest/openstack/common/strutils.py +++ /dev/null @@ -1,295 +0,0 @@ -# Copyright 2011 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. - -""" -System-level utilities and helper functions. -""" - -import math -import re -import sys -import unicodedata - -import six - -from tempest.openstack.common.gettextutils import _ - - -UNIT_PREFIX_EXPONENT = { - 'k': 1, - 'K': 1, - 'Ki': 1, - 'M': 2, - 'Mi': 2, - 'G': 3, - 'Gi': 3, - 'T': 4, - 'Ti': 4, -} -UNIT_SYSTEM_INFO = { - 'IEC': (1024, re.compile(r'(^[-+]?\d*\.?\d+)([KMGT]i?)?(b|bit|B)$')), - 'SI': (1000, re.compile(r'(^[-+]?\d*\.?\d+)([kMGT])?(b|bit|B)$')), -} - -TRUE_STRINGS = ('1', 't', 'true', 'on', 'y', 'yes') -FALSE_STRINGS = ('0', 'f', 'false', 'off', 'n', 'no') - -SLUGIFY_STRIP_RE = re.compile(r"[^\w\s-]") -SLUGIFY_HYPHENATE_RE = re.compile(r"[-\s]+") - - -# NOTE(flaper87): The following 3 globals are used by `mask_password` -_SANITIZE_KEYS = ['adminPass', 'admin_pass', 'password', 'admin_password'] - -# NOTE(ldbragst): Let's build a list of regex objects using the list of -# _SANITIZE_KEYS we already have. This way, we only have to add the new key -# to the list of _SANITIZE_KEYS and we can generate regular expressions -# for XML and JSON automatically. -_SANITIZE_PATTERNS = [] -_FORMAT_PATTERNS = [r'(%(key)s\s*[=]\s*[\"\']).*?([\"\'])', - r'(<%(key)s>).*?()', - r'([\"\']%(key)s[\"\']\s*:\s*[\"\']).*?([\"\'])', - r'([\'"].*?%(key)s[\'"]\s*:\s*u?[\'"]).*?([\'"])', - r'([\'"].*?%(key)s[\'"]\s*,\s*\'--?[A-z]+\'\s*,\s*u?[\'"])' - '.*?([\'"])', - r'(%(key)s\s*--?[A-z]+\s*)\S+(\s*)'] - -for key in _SANITIZE_KEYS: - for pattern in _FORMAT_PATTERNS: - reg_ex = re.compile(pattern % {'key': key}, re.DOTALL) - _SANITIZE_PATTERNS.append(reg_ex) - - -def int_from_bool_as_string(subject): - """Interpret a string as a boolean and return either 1 or 0. - - Any string value in: - - ('True', 'true', 'On', 'on', '1') - - is interpreted as a boolean True. - - Useful for JSON-decoded stuff and config file parsing - """ - return bool_from_string(subject) and 1 or 0 - - -def bool_from_string(subject, strict=False, default=False): - """Interpret a string as a boolean. - - A case-insensitive match is performed such that strings matching 't', - 'true', 'on', 'y', 'yes', or '1' are considered True and, when - `strict=False`, anything else returns the value specified by 'default'. - - Useful for JSON-decoded stuff and config file parsing. - - If `strict=True`, unrecognized values, including None, will raise a - ValueError which is useful when parsing values passed in from an API call. - Strings yielding False are 'f', 'false', 'off', 'n', 'no', or '0'. - """ - if not isinstance(subject, six.string_types): - subject = six.text_type(subject) - - lowered = subject.strip().lower() - - if lowered in TRUE_STRINGS: - return True - elif lowered in FALSE_STRINGS: - return False - elif strict: - acceptable = ', '.join( - "'%s'" % s for s in sorted(TRUE_STRINGS + FALSE_STRINGS)) - msg = _("Unrecognized value '%(val)s', acceptable values are:" - " %(acceptable)s") % {'val': subject, - 'acceptable': acceptable} - raise ValueError(msg) - else: - return default - - -def safe_decode(text, incoming=None, errors='strict'): - """Decodes incoming text/bytes string using `incoming` if they're not - already unicode. - - :param incoming: Text's current encoding - :param errors: Errors handling policy. See here for valid - values http://docs.python.org/2/library/codecs.html - :returns: text or a unicode `incoming` encoded - representation of it. - :raises TypeError: If text is not an instance of str - """ - if not isinstance(text, (six.string_types, six.binary_type)): - raise TypeError("%s can't be decoded" % type(text)) - - if isinstance(text, six.text_type): - return text - - if not incoming: - incoming = (sys.stdin.encoding or - sys.getdefaultencoding()) - - try: - return text.decode(incoming, errors) - except UnicodeDecodeError: - # Note(flaper87) If we get here, it means that - # sys.stdin.encoding / sys.getdefaultencoding - # didn't return a suitable encoding to decode - # text. This happens mostly when global LANG - # var is not set correctly and there's no - # default encoding. In this case, most likely - # python will use ASCII or ANSI encoders as - # default encodings but they won't be capable - # of decoding non-ASCII characters. - # - # Also, UTF-8 is being used since it's an ASCII - # extension. - return text.decode('utf-8', errors) - - -def safe_encode(text, incoming=None, - encoding='utf-8', errors='strict'): - """Encodes incoming text/bytes string using `encoding`. - - If incoming is not specified, text is expected to be encoded with - current python's default encoding. (`sys.getdefaultencoding`) - - :param incoming: Text's current encoding - :param encoding: Expected encoding for text (Default UTF-8) - :param errors: Errors handling policy. See here for valid - values http://docs.python.org/2/library/codecs.html - :returns: text or a bytestring `encoding` encoded - representation of it. - :raises TypeError: If text is not an instance of str - """ - if not isinstance(text, (six.string_types, six.binary_type)): - raise TypeError("%s can't be encoded" % type(text)) - - if not incoming: - incoming = (sys.stdin.encoding or - sys.getdefaultencoding()) - - if isinstance(text, six.text_type): - return text.encode(encoding, errors) - elif text and encoding != incoming: - # Decode text before encoding it with `encoding` - text = safe_decode(text, incoming, errors) - return text.encode(encoding, errors) - else: - return text - - -def string_to_bytes(text, unit_system='IEC', return_int=False): - """Converts a string into an float representation of bytes. - - The units supported for IEC :: - - Kb(it), Kib(it), Mb(it), Mib(it), Gb(it), Gib(it), Tb(it), Tib(it) - KB, KiB, MB, MiB, GB, GiB, TB, TiB - - The units supported for SI :: - - kb(it), Mb(it), Gb(it), Tb(it) - kB, MB, GB, TB - - Note that the SI unit system does not support capital letter 'K' - - :param text: String input for bytes size conversion. - :param unit_system: Unit system for byte size conversion. - :param return_int: If True, returns integer representation of text - in bytes. (default: decimal) - :returns: Numerical representation of text in bytes. - :raises ValueError: If text has an invalid value. - - """ - try: - base, reg_ex = UNIT_SYSTEM_INFO[unit_system] - except KeyError: - msg = _('Invalid unit system: "%s"') % unit_system - raise ValueError(msg) - match = reg_ex.match(text) - if match: - magnitude = float(match.group(1)) - unit_prefix = match.group(2) - if match.group(3) in ['b', 'bit']: - magnitude /= 8 - else: - msg = _('Invalid string format: %s') % text - raise ValueError(msg) - if not unit_prefix: - res = magnitude - else: - res = magnitude * pow(base, UNIT_PREFIX_EXPONENT[unit_prefix]) - if return_int: - return int(math.ceil(res)) - return res - - -def to_slug(value, incoming=None, errors="strict"): - """Normalize string. - - Convert to lowercase, remove non-word characters, and convert spaces - to hyphens. - - Inspired by Django's `slugify` filter. - - :param value: Text to slugify - :param incoming: Text's current encoding - :param errors: Errors handling policy. See here for valid - values http://docs.python.org/2/library/codecs.html - :returns: slugified unicode representation of `value` - :raises TypeError: If text is not an instance of str - """ - value = safe_decode(value, incoming, errors) - # NOTE(aababilov): no need to use safe_(encode|decode) here: - # encodings are always "ascii", error handling is always "ignore" - # and types are always known (first: unicode; second: str) - value = unicodedata.normalize("NFKD", value).encode( - "ascii", "ignore").decode("ascii") - value = SLUGIFY_STRIP_RE.sub("", value).strip().lower() - return SLUGIFY_HYPHENATE_RE.sub("-", value) - - -def mask_password(message, secret="***"): - """Replace password with 'secret' in message. - - :param message: The string which includes security information. - :param secret: value with which to replace passwords. - :returns: The unicode value of message with the password fields masked. - - For example: - - >>> mask_password("'adminPass' : 'aaaaa'") - "'adminPass' : '***'" - >>> mask_password("'admin_pass' : 'aaaaa'") - "'admin_pass' : '***'" - >>> mask_password('"password" : "aaaaa"') - '"password" : "***"' - >>> mask_password("'original_password' : 'aaaaa'") - "'original_password' : '***'" - >>> mask_password("u'original_password' : u'aaaaa'") - "u'original_password' : u'***'" - """ - message = six.text_type(message) - - # NOTE(ldbragst): Check to see if anything in message contains any key - # specified in _SANITIZE_KEYS, if not then just return the message since - # we don't have to mask any passwords. - if not any(key in message for key in _SANITIZE_KEYS): - return message - - secret = r'\g<1>' + secret + r'\g<2>' - for pattern in _SANITIZE_PATTERNS: - message = re.sub(pattern, secret, message) - return message diff --git a/tempest/openstack/common/timeutils.py b/tempest/openstack/common/timeutils.py deleted file mode 100644 index c48da95f12..0000000000 --- a/tempest/openstack/common/timeutils.py +++ /dev/null @@ -1,210 +0,0 @@ -# Copyright 2011 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. - -""" -Time related utilities and helper functions. -""" - -import calendar -import datetime -import time - -import iso8601 -import six - - -# ISO 8601 extended time format with microseconds -_ISO8601_TIME_FORMAT_SUBSECOND = '%Y-%m-%dT%H:%M:%S.%f' -_ISO8601_TIME_FORMAT = '%Y-%m-%dT%H:%M:%S' -PERFECT_TIME_FORMAT = _ISO8601_TIME_FORMAT_SUBSECOND - - -def isotime(at=None, subsecond=False): - """Stringify time in ISO 8601 format.""" - if not at: - at = utcnow() - st = at.strftime(_ISO8601_TIME_FORMAT - if not subsecond - else _ISO8601_TIME_FORMAT_SUBSECOND) - tz = at.tzinfo.tzname(None) if at.tzinfo else 'UTC' - st += ('Z' if tz == 'UTC' else tz) - return st - - -def parse_isotime(timestr): - """Parse time from ISO 8601 format.""" - try: - return iso8601.parse_date(timestr) - except iso8601.ParseError as e: - raise ValueError(six.text_type(e)) - except TypeError as e: - raise ValueError(six.text_type(e)) - - -def strtime(at=None, fmt=PERFECT_TIME_FORMAT): - """Returns formatted utcnow.""" - if not at: - at = utcnow() - return at.strftime(fmt) - - -def parse_strtime(timestr, fmt=PERFECT_TIME_FORMAT): - """Turn a formatted time back into a datetime.""" - return datetime.datetime.strptime(timestr, fmt) - - -def normalize_time(timestamp): - """Normalize time in arbitrary timezone to UTC naive object.""" - offset = timestamp.utcoffset() - if offset is None: - return timestamp - return timestamp.replace(tzinfo=None) - offset - - -def is_older_than(before, seconds): - """Return True if before is older than seconds.""" - if isinstance(before, six.string_types): - before = parse_strtime(before).replace(tzinfo=None) - else: - before = before.replace(tzinfo=None) - - return utcnow() - before > datetime.timedelta(seconds=seconds) - - -def is_newer_than(after, seconds): - """Return True if after is newer than seconds.""" - if isinstance(after, six.string_types): - after = parse_strtime(after).replace(tzinfo=None) - else: - after = after.replace(tzinfo=None) - - return after - utcnow() > datetime.timedelta(seconds=seconds) - - -def utcnow_ts(): - """Timestamp version of our utcnow function.""" - if utcnow.override_time is None: - # NOTE(kgriffs): This is several times faster - # than going through calendar.timegm(...) - return int(time.time()) - - return calendar.timegm(utcnow().timetuple()) - - -def utcnow(): - """Overridable version of utils.utcnow.""" - if utcnow.override_time: - try: - return utcnow.override_time.pop(0) - except AttributeError: - return utcnow.override_time - return datetime.datetime.utcnow() - - -def iso8601_from_timestamp(timestamp): - """Returns an iso8601 formatted date from timestamp.""" - return isotime(datetime.datetime.utcfromtimestamp(timestamp)) - - -utcnow.override_time = None - - -def set_time_override(override_time=None): - """Overrides utils.utcnow. - - Make it return a constant time or a list thereof, one at a time. - - :param override_time: datetime instance or list thereof. If not - given, defaults to the current UTC time. - """ - utcnow.override_time = override_time or datetime.datetime.utcnow() - - -def advance_time_delta(timedelta): - """Advance overridden time using a datetime.timedelta.""" - assert utcnow.override_time is not None - try: - for dt in utcnow.override_time: - dt += timedelta - except TypeError: - utcnow.override_time += timedelta - - -def advance_time_seconds(seconds): - """Advance overridden time by seconds.""" - advance_time_delta(datetime.timedelta(0, seconds)) - - -def clear_time_override(): - """Remove the overridden time.""" - utcnow.override_time = None - - -def marshall_now(now=None): - """Make an rpc-safe datetime with microseconds. - - Note: tzinfo is stripped, but not required for relative times. - """ - if not now: - now = utcnow() - return dict(day=now.day, month=now.month, year=now.year, hour=now.hour, - minute=now.minute, second=now.second, - microsecond=now.microsecond) - - -def unmarshall_time(tyme): - """Unmarshall a datetime dict.""" - return datetime.datetime(day=tyme['day'], - month=tyme['month'], - year=tyme['year'], - hour=tyme['hour'], - minute=tyme['minute'], - second=tyme['second'], - microsecond=tyme['microsecond']) - - -def delta_seconds(before, after): - """Return the difference between two timing objects. - - Compute the difference in seconds between two date, time, or - datetime objects (as a float, to microsecond resolution). - """ - delta = after - before - return total_seconds(delta) - - -def total_seconds(delta): - """Return the total seconds of datetime.timedelta object. - - Compute total seconds of datetime.timedelta, datetime.timedelta - doesn't have method total_seconds in Python2.6, calculate it manually. - """ - try: - return delta.total_seconds() - except AttributeError: - return ((delta.days * 24 * 3600) + delta.seconds + - float(delta.microseconds) / (10 ** 6)) - - -def is_soon(dt, window): - """Determines if time is going to happen in the next window seconds. - - :param dt: the time - :param window: minimum seconds to remain to consider the time not soon - - :return: True if expiration is within the given duration - """ - soon = (utcnow() + datetime.timedelta(seconds=window)) - return normalize_time(dt) <= soon diff --git a/tempest/openstack/common/versionutils.py b/tempest/openstack/common/versionutils.py index 131046e0a5..12d2e147a0 100644 --- a/tempest/openstack/common/versionutils.py +++ b/tempest/openstack/common/versionutils.py @@ -17,14 +17,34 @@ Helpers for comparing version strings. """ +import copy import functools -import pkg_resources +import inspect +import logging -from tempest.openstack.common.gettextutils import _ -from tempest.openstack.common import log as logging +from oslo_config import cfg +import pkg_resources +import six + +from tempest.openstack.common._i18n import _ +from oslo_log import log as logging LOG = logging.getLogger(__name__) +CONF = cfg.CONF + + +deprecated_opts = [ + cfg.BoolOpt('fatal_deprecations', + default=False, + help='Enables or disables fatal status of deprecations.'), +] + + +def list_opts(): + """Entry point for oslo.config-generator. + """ + return [(None, copy.deepcopy(deprecated_opts))] class deprecated(object): @@ -52,18 +72,38 @@ class deprecated(object): >>> @deprecated(as_of=deprecated.ICEHOUSE, remove_in=+1) ... def c(): pass + 4. Specifying the deprecated functionality will not be removed: + >>> @deprecated(as_of=deprecated.ICEHOUSE, remove_in=0) + ... def d(): pass + + 5. Specifying a replacement, deprecated functionality will not be removed: + >>> @deprecated(as_of=deprecated.ICEHOUSE, in_favor_of='f()', remove_in=0) + ... def e(): pass + """ + # NOTE(morganfainberg): Bexar is used for unit test purposes, it is + # expected we maintain a gap between Bexar and Folsom in this list. + BEXAR = 'B' FOLSOM = 'F' GRIZZLY = 'G' HAVANA = 'H' ICEHOUSE = 'I' + JUNO = 'J' + KILO = 'K' + LIBERTY = 'L' _RELEASES = { + # NOTE(morganfainberg): Bexar is used for unit test purposes, it is + # expected we maintain a gap between Bexar and Folsom in this list. + 'B': 'Bexar', 'F': 'Folsom', 'G': 'Grizzly', 'H': 'Havana', 'I': 'Icehouse', + 'J': 'Juno', + 'K': 'Kilo', + 'L': 'Liberty', } _deprecated_msg_with_alternative = _( @@ -74,6 +114,12 @@ class deprecated(object): '%(what)s is deprecated as of %(as_of)s and may be ' 'removed in %(remove_in)s. It will not be superseded.') + _deprecated_msg_with_alternative_no_removal = _( + '%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s.') + + _deprecated_msg_with_no_alternative_no_removal = _( + '%(what)s is deprecated as of %(as_of)s. It will not be superseded.') + def __init__(self, as_of, in_favor_of=None, remove_in=2, what=None): """Initialize decorator @@ -91,16 +137,34 @@ class deprecated(object): self.remove_in = remove_in self.what = what - def __call__(self, func): + def __call__(self, func_or_cls): if not self.what: - self.what = func.__name__ + '()' + self.what = func_or_cls.__name__ + '()' + msg, details = self._build_message() - @functools.wraps(func) - def wrapped(*args, **kwargs): - msg, details = self._build_message() - LOG.deprecated(msg, details) - return func(*args, **kwargs) - return wrapped + if inspect.isfunction(func_or_cls): + + @six.wraps(func_or_cls) + def wrapped(*args, **kwargs): + report_deprecated_feature(LOG, msg, details) + return func_or_cls(*args, **kwargs) + return wrapped + elif inspect.isclass(func_or_cls): + orig_init = func_or_cls.__init__ + + # TODO(tsufiev): change `functools` module to `six` as + # soon as six 1.7.4 (with fix for passing `assigned` + # argument to underlying `functools.wraps`) is released + # and added to the oslo-incubator requrements + @functools.wraps(orig_init, assigned=('__name__', '__doc__')) + def new_init(self, *args, **kwargs): + report_deprecated_feature(LOG, msg, details) + orig_init(self, *args, **kwargs) + func_or_cls.__init__ = new_init + return func_or_cls + else: + raise TypeError('deprecated can be used only with functions or ' + 'classes') def _get_safe_to_remove_release(self, release): # TODO(dstanek): this method will have to be reimplemented once @@ -119,9 +183,19 @@ class deprecated(object): if self.in_favor_of: details['in_favor_of'] = self.in_favor_of - msg = self._deprecated_msg_with_alternative + if self.remove_in > 0: + msg = self._deprecated_msg_with_alternative + else: + # There are no plans to remove this function, but it is + # now deprecated. + msg = self._deprecated_msg_with_alternative_no_removal else: - msg = self._deprecated_msg_no_alternative + if self.remove_in > 0: + msg = self._deprecated_msg_no_alternative + else: + # There are no plans to remove this function, but it is + # now deprecated. + msg = self._deprecated_msg_with_no_alternative_no_removal return msg, details @@ -146,3 +220,44 @@ def is_compatible(requested_version, current_version, same_major=True): return False return current_parts >= requested_parts + + +# Track the messages we have sent already. See +# report_deprecated_feature(). +_deprecated_messages_sent = {} + + +def report_deprecated_feature(logger, msg, *args, **kwargs): + """Call this function when a deprecated feature is used. + + If the system is configured for fatal deprecations then the message + is logged at the 'critical' level and :class:`DeprecatedConfig` will + be raised. + + Otherwise, the message will be logged (once) at the 'warn' level. + + :raises: :class:`DeprecatedConfig` if the system is configured for + fatal deprecations. + """ + stdmsg = _("Deprecated: %s") % msg + CONF.register_opts(deprecated_opts) + if CONF.fatal_deprecations: + logger.critical(stdmsg, *args, **kwargs) + raise DeprecatedConfig(msg=stdmsg) + + # Using a list because a tuple with dict can't be stored in a set. + sent_args = _deprecated_messages_sent.setdefault(msg, list()) + + if args in sent_args: + # Already logged this message, so don't log it again. + return + + sent_args.append(args) + logger.warn(stdmsg, *args, **kwargs) + + +class DeprecatedConfig(Exception): + message = _("Fatal call to deprecated config: %(msg)s") + + def __init__(self, msg): + super(Exception, self).__init__(self.message % dict(msg=msg)) diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py index ef1037c86c..81e771cbea 100644 --- a/tempest/scenario/manager.py +++ b/tempest/scenario/manager.py @@ -18,6 +18,7 @@ import os import subprocess import netaddr +from oslo_log import log import six from tempest_lib.common.utils import data_utils from tempest_lib import exceptions as lib_exc @@ -28,7 +29,6 @@ from tempest.common import credentials from tempest.common.utils.linux import remote_client from tempest import config from tempest import exceptions -from tempest.openstack.common import log from tempest.services.network import resources as net_resources import tempest.test diff --git a/tempest/scenario/test_aggregates_basic_ops.py b/tempest/scenario/test_aggregates_basic_ops.py index 4074e9b846..92e6c746ec 100644 --- a/tempest/scenario/test_aggregates_basic_ops.py +++ b/tempest/scenario/test_aggregates_basic_ops.py @@ -13,10 +13,10 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest.common import tempest_fixtures as fixtures -from tempest.openstack.common import log as logging from tempest.scenario import manager from tempest import test diff --git a/tempest/scenario/test_baremetal_basic_ops.py b/tempest/scenario/test_baremetal_basic_ops.py index 434d3df1c0..612a5a28b0 100644 --- a/tempest/scenario/test_baremetal_basic_ops.py +++ b/tempest/scenario/test_baremetal_basic_ops.py @@ -13,8 +13,9 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging + from tempest import config -from tempest.openstack.common import log as logging from tempest.scenario import manager from tempest import test diff --git a/tempest/scenario/test_large_ops.py b/tempest/scenario/test_large_ops.py index 2408109348..145efe7daa 100644 --- a/tempest/scenario/test_large_ops.py +++ b/tempest/scenario/test_large_ops.py @@ -13,11 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest_lib import exceptions as lib_exc from tempest import config -from tempest.openstack.common import log as logging from tempest.scenario import manager from tempest import test diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py index 63f74c467e..c780464a19 100644 --- a/tempest/scenario/test_minimum_basic.py +++ b/tempest/scenario/test_minimum_basic.py @@ -13,10 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging + from tempest.common import custom_matchers from tempest import config from tempest import exceptions -from tempest.openstack.common import log as logging from tempest.scenario import manager from tempest import test diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py index b4837a2e1d..bb668f7e46 100644 --- a/tempest/scenario/test_network_advanced_server_ops.py +++ b/tempest/scenario/test_network_advanced_server_ops.py @@ -13,12 +13,12 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest_lib import decorators import testtools from tempest import config -from tempest.openstack.common import log as logging from tempest.scenario import manager from tempest import test diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py index c9aa1ab597..16d9d12aec 100644 --- a/tempest/scenario/test_network_basic_ops.py +++ b/tempest/scenario/test_network_basic_ops.py @@ -16,12 +16,12 @@ import collections import re +from oslo_log import log as logging from tempest_lib.common.utils import data_utils import testtools from tempest import config from tempest import exceptions -from tempest.openstack.common import log as logging from tempest.scenario import manager from tempest.services.network import resources as net_resources from tempest import test diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py index 7b2bdd5a87..16ff8485ab 100644 --- a/tempest/scenario/test_network_v6.py +++ b/tempest/scenario/test_network_v6.py @@ -14,8 +14,10 @@ # under the License. import functools import netaddr + +from oslo_log import log as logging + from tempest import config -from tempest.openstack.common import log as logging from tempest.scenario import manager from tempest import test diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py index bb6c9b1ea3..cffb2fed8b 100644 --- a/tempest/scenario/test_security_groups_basic_ops.py +++ b/tempest/scenario/test_security_groups_basic_ops.py @@ -13,11 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest import clients from tempest import config -from tempest.openstack.common import log as logging from tempest.scenario import manager from tempest import test diff --git a/tempest/scenario/test_server_advanced_ops.py b/tempest/scenario/test_server_advanced_ops.py index 8cbc3885cb..f45f0c9bd3 100644 --- a/tempest/scenario/test_server_advanced_ops.py +++ b/tempest/scenario/test_server_advanced_ops.py @@ -13,10 +13,10 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging import testtools from tempest import config -from tempest.openstack.common import log as logging from tempest.scenario import manager from tempest import test diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py index b306b11406..e093f437da 100644 --- a/tempest/scenario/test_server_basic_ops.py +++ b/tempest/scenario/test_server_basic_ops.py @@ -13,8 +13,9 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging + from tempest import config -from tempest.openstack.common import log as logging from tempest.scenario import manager from tempest.scenario import utils as test_utils from tempest import test diff --git a/tempest/scenario/test_shelve_instance.py b/tempest/scenario/test_shelve_instance.py index 155ecbfd76..e674101b3e 100644 --- a/tempest/scenario/test_shelve_instance.py +++ b/tempest/scenario/test_shelve_instance.py @@ -13,10 +13,10 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log import testtools from tempest import config -from tempest.openstack.common import log from tempest.scenario import manager from tempest import test diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py index 109d36b06d..1298faa3da 100644 --- a/tempest/scenario/test_snapshot_pattern.py +++ b/tempest/scenario/test_snapshot_pattern.py @@ -13,10 +13,10 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log import testtools from tempest import config -from tempest.openstack.common import log from tempest.scenario import manager from tempest import test diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py index eaa6141baf..f7653e78ac 100644 --- a/tempest/scenario/test_stamp_pattern.py +++ b/tempest/scenario/test_stamp_pattern.py @@ -15,6 +15,7 @@ import time +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest_lib import decorators from tempest_lib import exceptions as lib_exc @@ -22,7 +23,6 @@ import testtools from tempest import config from tempest import exceptions -from tempest.openstack.common import log as logging from tempest.scenario import manager from tempest import test import tempest.test diff --git a/tempest/scenario/test_swift_basic_ops.py b/tempest/scenario/test_swift_basic_ops.py index b622c4ae32..69e0c4cb70 100644 --- a/tempest/scenario/test_swift_basic_ops.py +++ b/tempest/scenario/test_swift_basic_ops.py @@ -13,8 +13,9 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging + from tempest import config -from tempest.openstack.common import log as logging from tempest.scenario import manager from tempest import test diff --git a/tempest/scenario/test_swift_telemetry_middleware.py b/tempest/scenario/test_swift_telemetry_middleware.py index a10168cab2..302ccbec4b 100644 --- a/tempest/scenario/test_swift_telemetry_middleware.py +++ b/tempest/scenario/test_swift_telemetry_middleware.py @@ -14,9 +14,9 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging from tempest import config -from tempest.openstack.common import log as logging from tempest.scenario import manager from tempest import test diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py index 3c5e88cda6..35ac42b90b 100644 --- a/tempest/scenario/test_volume_boot_pattern.py +++ b/tempest/scenario/test_volume_boot_pattern.py @@ -10,11 +10,11 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log from tempest_lib.common.utils import data_utils from tempest_lib import decorators from tempest import config -from tempest.openstack.common import log from tempest.scenario import manager from tempest import test diff --git a/tempest/services/image/v1/json/image_client.py b/tempest/services/image/v1/json/image_client.py index 01a9c54ecb..0c3517499a 100644 --- a/tempest/services/image/v1/json/image_client.py +++ b/tempest/services/image/v1/json/image_client.py @@ -20,13 +20,13 @@ import os import time import urllib +from oslo_log import log as logging from tempest_lib.common.utils import misc as misc_utils from tempest_lib import exceptions as lib_exc from tempest.common import glance_http from tempest.common import service_client from tempest import exceptions -from tempest.openstack.common import log as logging LOG = logging.getLogger(__name__) diff --git a/tempest/services/telemetry/json/telemetry_client.py b/tempest/services/telemetry/json/telemetry_client.py index a249625706..36c123b324 100644 --- a/tempest/services/telemetry/json/telemetry_client.py +++ b/tempest/services/telemetry/json/telemetry_client.py @@ -15,8 +15,9 @@ import urllib +from oslo_serialization import jsonutils as json + from tempest.common import service_client -from tempest.openstack.common import jsonutils as json class TelemetryClientJSON(service_client.ServiceClient): diff --git a/tempest/services/volume/json/admin/volume_quotas_client.py b/tempest/services/volume/json/admin/volume_quotas_client.py index 616f8e45d2..abd36c1376 100644 --- a/tempest/services/volume/json/admin/volume_quotas_client.py +++ b/tempest/services/volume/json/admin/volume_quotas_client.py @@ -14,8 +14,9 @@ import urllib +from oslo_serialization import jsonutils + from tempest.common import service_client -from tempest.openstack.common import jsonutils class BaseVolumeQuotasClientJSON(service_client.ServiceClient): diff --git a/tempest/services/volume/json/snapshots_client.py b/tempest/services/volume/json/snapshots_client.py index 8430b633e9..9f880858cd 100644 --- a/tempest/services/volume/json/snapshots_client.py +++ b/tempest/services/volume/json/snapshots_client.py @@ -14,11 +14,11 @@ import json import time import urllib +from oslo_log import log as logging from tempest_lib import exceptions as lib_exc from tempest.common import service_client from tempest import exceptions -from tempest.openstack.common import log as logging LOG = logging.getLogger(__name__) diff --git a/tempest/stress/actions/unit_test.py b/tempest/stress/actions/unit_test.py index 2f1d28f64d..c3766932fb 100644 --- a/tempest/stress/actions/unit_test.py +++ b/tempest/stress/actions/unit_test.py @@ -10,9 +10,10 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging +from oslo_utils import importutils + from tempest import config -from tempest.openstack.common import importutils -from tempest.openstack.common import log as logging import tempest.stress.stressaction as stressaction CONF = config.CONF diff --git a/tempest/stress/cleanup.py b/tempest/stress/cleanup.py index 161d93fae5..d0b1be15fc 100644 --- a/tempest/stress/cleanup.py +++ b/tempest/stress/cleanup.py @@ -14,8 +14,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +from oslo_log import log as logging + from tempest import clients -from tempest.openstack.common import log as logging LOG = logging.getLogger(__name__) diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py index e007a49612..d095b53d64 100644 --- a/tempest/stress/driver.py +++ b/tempest/stress/driver.py @@ -17,6 +17,8 @@ import os import signal import time +from oslo_log import log as logging +from oslo_utils import importutils from six import moves from tempest_lib.common.utils import data_utils @@ -25,8 +27,6 @@ from tempest.common import cred_provider from tempest.common import ssh from tempest import config from tempest import exceptions -from tempest.openstack.common import importutils -from tempest.openstack.common import log as logging from tempest.stress import cleanup CONF = config.CONF diff --git a/tempest/stress/stressaction.py b/tempest/stress/stressaction.py index 286e02294a..a3d0d17446 100644 --- a/tempest/stress/stressaction.py +++ b/tempest/stress/stressaction.py @@ -18,7 +18,7 @@ import sys import six -from tempest.openstack.common import log as logging +from oslo_log import log as logging @six.add_metaclass(abc.ABCMeta) diff --git a/tempest/test.py b/tempest/test.py index f04aff7383..d6858a31ee 100644 --- a/tempest/test.py +++ b/tempest/test.py @@ -24,6 +24,8 @@ import urllib import uuid import fixtures +from oslo_log import log as logging +from oslo_utils import importutils import six import testscenarios import testtools @@ -33,8 +35,6 @@ from tempest.common import credentials import tempest.common.generator.valid_generator as valid from tempest import config from tempest import exceptions -from tempest.openstack.common import importutils -from tempest.openstack.common import log as logging LOG = logging.getLogger(__name__) diff --git a/tempest/tests/cmd/test_verify_tempest_config.py b/tempest/tests/cmd/test_verify_tempest_config.py index 7c04156103..b9afd5e97c 100644 --- a/tempest/tests/cmd/test_verify_tempest_config.py +++ b/tempest/tests/cmd/test_verify_tempest_config.py @@ -15,10 +15,10 @@ import json import mock +from oslotest import mockpatch from tempest.cmd import verify_tempest_config from tempest import config -from tempest.openstack.common.fixture import mockpatch from tempest.tests import base from tempest.tests import fake_config diff --git a/tempest/tests/common/test_accounts.py b/tempest/tests/common/test_accounts.py index 58e3c0c71e..29fe902ca4 100644 --- a/tempest/tests/common/test_accounts.py +++ b/tempest/tests/common/test_accounts.py @@ -14,10 +14,10 @@ import hashlib import os -import tempfile import mock -from oslo.config import cfg +from oslo_concurrency.fixture import lockutils as lockutils_fixtures +from oslo_config import cfg from oslotest import mockpatch from tempest import auth @@ -36,9 +36,7 @@ class TestAccount(base.TestCase): super(TestAccount, self).setUp() self.useFixture(fake_config.ConfigFixture()) self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate) - self.temp_dir = tempfile.mkdtemp() - cfg.CONF.set_default('lock_path', self.temp_dir) - self.addCleanup(os.rmdir, self.temp_dir) + self.useFixture(lockutils_fixtures.ExternalLockFixture()) self.test_accounts = [ {'username': 'test_user1', 'tenant_name': 'test_tenant1', 'password': 'p'}, @@ -117,7 +115,7 @@ class TestAccount(base.TestCase): self.assertTrue(res, "_create_hash_file should return True if the " "pseudo-lock doesn't already exist") - @mock.patch('tempest.openstack.common.lockutils.lock') + @mock.patch('oslo_concurrency.lockutils.lock') def test_get_free_hash_no_previous_accounts(self, lock_mock): # Emulate no pre-existing lock self.useFixture(mockpatch.Patch('os.path.isdir', return_value=False)) @@ -128,13 +126,21 @@ class TestAccount(base.TestCase): with mock.patch('__builtin__.open', mock.mock_open(), create=True) as open_mock: test_account_class._get_free_hash(hash_list) - lock_path = os.path.join(accounts.CONF.lock_path, 'test_accounts', + # FIXME(dhellmann): The configuration option is not part + # of the API of the library, because if we change the + # option name or group it will break this use. Tempest + # needs to set this value somewhere that it owns, and then + # use lockutils.set_defaults() to tell oslo.concurrency + # what value to use. + lock_path = os.path.join(accounts.CONF.oslo_concurrency.lock_path, + 'test_accounts', hash_list[0]) open_mock.assert_called_once_with(lock_path, 'w') - mkdir_path = os.path.join(accounts.CONF.lock_path, 'test_accounts') + mkdir_path = os.path.join(accounts.CONF.oslo_concurrency.lock_path, + 'test_accounts') mkdir_mock.mock.assert_called_once_with(mkdir_path) - @mock.patch('tempest.openstack.common.lockutils.lock') + @mock.patch('oslo_concurrency.lockutils.lock') def test_get_free_hash_no_free_accounts(self, lock_mock): hash_list = self._get_hash_list(self.test_accounts) # Emulate pre-existing lock dir @@ -146,7 +152,7 @@ class TestAccount(base.TestCase): self.assertRaises(exceptions.InvalidConfiguration, test_account_class._get_free_hash, hash_list) - @mock.patch('tempest.openstack.common.lockutils.lock') + @mock.patch('oslo_concurrency.lockutils.lock') def test_get_free_hash_some_in_use_accounts(self, lock_mock): # Emulate no pre-existing lock self.useFixture(mockpatch.Patch('os.path.isdir', return_value=True)) @@ -164,11 +170,18 @@ class TestAccount(base.TestCase): with mock.patch('__builtin__.open', mock.mock_open(), create=True) as open_mock: test_account_class._get_free_hash(hash_list) - lock_path = os.path.join(accounts.CONF.lock_path, 'test_accounts', + # FIXME(dhellmann): The configuration option is not part + # of the API of the library, because if we change the + # option name or group it will break this use. Tempest + # needs to set this value somewhere that it owns, and then + # use lockutils.set_defaults() to tell oslo.concurrency + # what value to use. + lock_path = os.path.join(accounts.CONF.oslo_concurrency.lock_path, + 'test_accounts', hash_list[3]) open_mock.assert_has_calls([mock.call(lock_path, 'w')]) - @mock.patch('tempest.openstack.common.lockutils.lock') + @mock.patch('oslo_concurrency.lockutils.lock') def test_remove_hash_last_account(self, lock_mock): hash_list = self._get_hash_list(self.test_accounts) # Pretend the pseudo-lock is there @@ -179,13 +192,21 @@ class TestAccount(base.TestCase): remove_mock = self.useFixture(mockpatch.Patch('os.remove')) rmdir_mock = self.useFixture(mockpatch.Patch('os.rmdir')) test_account_class.remove_hash(hash_list[2]) - hash_path = os.path.join(accounts.CONF.lock_path, 'test_accounts', + # FIXME(dhellmann): The configuration option is not part of + # the API of the library, because if we change the option name + # or group it will break this use. Tempest needs to set this + # value somewhere that it owns, and then use + # lockutils.set_defaults() to tell oslo.concurrency what value + # to use. + hash_path = os.path.join(accounts.CONF.oslo_concurrency.lock_path, + 'test_accounts', hash_list[2]) - lock_path = os.path.join(accounts.CONF.lock_path, 'test_accounts') + lock_path = os.path.join(accounts.CONF.oslo_concurrency.lock_path, + 'test_accounts') remove_mock.mock.assert_called_once_with(hash_path) rmdir_mock.mock.assert_called_once_with(lock_path) - @mock.patch('tempest.openstack.common.lockutils.lock') + @mock.patch('oslo_concurrency.lockutils.lock') def test_remove_hash_not_last_account(self, lock_mock): hash_list = self._get_hash_list(self.test_accounts) # Pretend the pseudo-lock is there @@ -197,7 +218,14 @@ class TestAccount(base.TestCase): remove_mock = self.useFixture(mockpatch.Patch('os.remove')) rmdir_mock = self.useFixture(mockpatch.Patch('os.rmdir')) test_account_class.remove_hash(hash_list[2]) - hash_path = os.path.join(accounts.CONF.lock_path, 'test_accounts', + # FIXME(dhellmann): The configuration option is not part of + # the API of the library, because if we change the option name + # or group it will break this use. Tempest needs to set this + # value somewhere that it owns, and then use + # lockutils.set_defaults() to tell oslo.concurrency what value + # to use. + hash_path = os.path.join(accounts.CONF.oslo_concurrency.lock_path, + 'test_accounts', hash_list[2]) remove_mock.mock.assert_called_once_with(hash_path) rmdir_mock.mock.assert_not_called() @@ -277,9 +305,7 @@ class TestNotLockingAccount(base.TestCase): super(TestNotLockingAccount, self).setUp() self.useFixture(fake_config.ConfigFixture()) self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate) - self.temp_dir = tempfile.mkdtemp() - cfg.CONF.set_default('lock_path', self.temp_dir) - self.addCleanup(os.rmdir, self.temp_dir) + self.useFixture(lockutils_fixtures.ExternalLockFixture()) self.test_accounts = [ {'username': 'test_user1', 'tenant_name': 'test_tenant1', 'password': 'p'}, diff --git a/tempest/tests/common/test_cred_provider.py b/tempest/tests/common/test_cred_provider.py index 3f7c0f8f42..4059a1d778 100644 --- a/tempest/tests/common/test_cred_provider.py +++ b/tempest/tests/common/test_cred_provider.py @@ -12,7 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. -from oslo.config import cfg +from oslo_config import cfg from tempest import auth from tempest.common import cred_provider diff --git a/tempest/tests/common/utils/linux/test_remote_client.py b/tempest/tests/common/utils/linux/test_remote_client.py index e8650c55ca..40b7b32aab 100644 --- a/tempest/tests/common/utils/linux/test_remote_client.py +++ b/tempest/tests/common/utils/linux/test_remote_client.py @@ -14,11 +14,11 @@ import time -from oslo.config import cfg +from oslo_config import cfg +from oslotest import mockpatch from tempest.common.utils.linux import remote_client from tempest import config -from tempest.openstack.common.fixture import mockpatch from tempest.tests import base from tempest.tests import fake_config diff --git a/tempest/tests/fake_config.py b/tempest/tests/fake_config.py index 2f8efa101f..4898c9ce7f 100644 --- a/tempest/tests/fake_config.py +++ b/tempest/tests/fake_config.py @@ -14,19 +14,17 @@ import os -from oslo.config import cfg +from oslo_concurrency import lockutils +from oslo_config import cfg +from oslo_config import fixture as conf_fixture from tempest import config -from tempest.openstack.common.fixture import config as conf_fixture -from tempest.openstack.common import importutils class ConfigFixture(conf_fixture.Config): def __init__(self): config.register_opts() - # Register locking options - importutils.import_module('tempest.openstack.common.lockutils') super(ConfigFixture, self).__init__() def setUp(self): @@ -43,8 +41,9 @@ class ConfigFixture(conf_fixture.Config): self.conf.set_default('heat', True, group='service_available') if not os.path.exists(str(os.environ.get('OS_TEST_LOCK_PATH'))): os.mkdir(str(os.environ.get('OS_TEST_LOCK_PATH'))) - self.conf.set_default('lock_path', - str(os.environ.get('OS_TEST_LOCK_PATH'))) + lockutils.set_defaults( + lock_path=str(os.environ.get('OS_TEST_LOCK_PATH')), + ) self.conf.set_default('auth_version', 'v2', group='identity') for config_option in ['username', 'password', 'tenant_name']: # Identity group items diff --git a/tempest/tests/stress/test_stress.py b/tempest/tests/stress/test_stress.py index 9c3533d64a..3a7b436b2b 100644 --- a/tempest/tests/stress/test_stress.py +++ b/tempest/tests/stress/test_stress.py @@ -18,7 +18,7 @@ import subprocess from tempest_lib import exceptions -from tempest.openstack.common import log as logging +from oslo_log import log as logging from tempest.tests import base LOG = logging.getLogger(__name__) diff --git a/tempest/tests/test_decorators.py b/tempest/tests/test_decorators.py index 5149ba6b2b..0cd54b99b6 100644 --- a/tempest/tests/test_decorators.py +++ b/tempest/tests/test_decorators.py @@ -15,7 +15,7 @@ import uuid import mock -from oslo.config import cfg +from oslo_config import cfg from oslotest import mockpatch import testtools diff --git a/tempest/tests/test_glance_http.py b/tempest/tests/test_glance_http.py index 852dd4b4a3..84b66d76fb 100644 --- a/tempest/tests/test_glance_http.py +++ b/tempest/tests/test_glance_http.py @@ -18,12 +18,12 @@ import json import socket import mock +from oslotest import mockpatch import six from tempest_lib import exceptions as lib_exc from tempest.common import glance_http from tempest import exceptions -from tempest.openstack.common.fixture import mockpatch from tempest.tests import base from tempest.tests import fake_auth_provider from tempest.tests import fake_http diff --git a/tempest/tests/test_tenant_isolation.py b/tempest/tests/test_tenant_isolation.py index a420a8f243..15ff0ffe27 100644 --- a/tempest/tests/test_tenant_isolation.py +++ b/tempest/tests/test_tenant_isolation.py @@ -13,13 +13,13 @@ # under the License. import mock -from oslo.config import cfg +from oslo_config import cfg +from oslotest import mockpatch from tempest.common import isolated_creds from tempest.common import service_client from tempest import config from tempest import exceptions -from tempest.openstack.common.fixture import mockpatch from tempest.services.identity.v2.json import identity_client as \ json_iden_client from tempest.services.identity.v2.json import token_client as json_token_client diff --git a/tempest/thirdparty/boto/test.py b/tempest/thirdparty/boto/test.py index 5b2ed70b4a..b5d3f8be94 100644 --- a/tempest/thirdparty/boto/test.py +++ b/tempest/thirdparty/boto/test.py @@ -24,13 +24,13 @@ from boto import ec2 from boto import exception from boto import s3 import keystoneclient.exceptions +from oslo_log import log as logging import six import tempest.clients from tempest.common.utils import file_utils from tempest import config from tempest import exceptions -from tempest.openstack.common import log as logging import tempest.test from tempest.thirdparty.boto.utils import wait diff --git a/tempest/thirdparty/boto/test_ec2_instance_run.py b/tempest/thirdparty/boto/test_ec2_instance_run.py index 19be559fdb..539d1b1799 100644 --- a/tempest/thirdparty/boto/test_ec2_instance_run.py +++ b/tempest/thirdparty/boto/test_ec2_instance_run.py @@ -13,12 +13,12 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging from tempest_lib.common.utils import data_utils from tempest.common.utils.linux import remote_client from tempest import config from tempest import exceptions -from tempest.openstack.common import log as logging from tempest import test from tempest.thirdparty.boto import test as boto_test from tempest.thirdparty.boto.utils import s3 diff --git a/tempest/thirdparty/boto/test_ec2_volumes.py b/tempest/thirdparty/boto/test_ec2_volumes.py index 9a6d13fdac..483d4c3874 100644 --- a/tempest/thirdparty/boto/test_ec2_volumes.py +++ b/tempest/thirdparty/boto/test_ec2_volumes.py @@ -13,8 +13,9 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging + from tempest import config -from tempest.openstack.common import log as logging from tempest import test from tempest.thirdparty.boto import test as boto_test diff --git a/tempest/thirdparty/boto/utils/s3.py b/tempest/thirdparty/boto/utils/s3.py index ff5e332b4d..55c1b0a605 100644 --- a/tempest/thirdparty/boto/utils/s3.py +++ b/tempest/thirdparty/boto/utils/s3.py @@ -20,7 +20,7 @@ import re import boto import boto.s3.key -from tempest.openstack.common import log as logging +from oslo_log import log as logging LOG = logging.getLogger(__name__) diff --git a/tempest/thirdparty/boto/utils/wait.py b/tempest/thirdparty/boto/utils/wait.py index 752ed0f9bb..8771ed75a8 100644 --- a/tempest/thirdparty/boto/utils/wait.py +++ b/tempest/thirdparty/boto/utils/wait.py @@ -17,10 +17,10 @@ import re import time import boto.exception +from oslo_log import log as logging import testtools from tempest import config -from tempest.openstack.common import log as logging CONF = config.CONF LOG = logging.getLogger(__name__) diff --git a/tools/config/config-generator.tempest.conf b/tools/config/config-generator.tempest.conf index e5a02f85f0..d718f93355 100644 --- a/tools/config/config-generator.tempest.conf +++ b/tools/config/config-generator.tempest.conf @@ -1,3 +1,8 @@ [DEFAULT] output_file = etc/tempest.conf.sample namespace = tempest.config +namespace = oslo.concurrency +namespace = oslo.i18n +namespace = oslo.log +namespace = oslo.serialization +namespace = oslo.utils