Use custom warnings everywhere

Build on change I3846e8fcffdb5de2afe64365952d90b5ecb0f74a by switching
all callers of 'warning.warn' to use our custom warnings. This allows
users (like OSC) to filter these out as needed.

Since we have new types of warning, the docs are updated accordingly.

Change-Id: I5039fd8585e3352798a6d2fae7d5623fbc1adb6a
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane 2023-05-25 13:22:14 +01:00
parent e74301292a
commit 3f9685ffad
13 changed files with 109 additions and 74 deletions

View File

@ -3,12 +3,13 @@ Warnings
openstacksdk uses the `warnings`__ infrastructure to warn users about
deprecated resources and resource fields, as well as deprecated behavior in
openstacksdk itself. Currently, these warnings are all derived from
``DeprecationWarning``. In Python, deprecation warnings are silenced by
default. You must turn them on using the ``-Wa`` Python command line option or
the ``PYTHONWARNINGS`` environment variable. If you are writing an application
that uses openstacksdk, you may wish to enable some of these warnings during
test runs to ensure you migrate away from deprecated behavior.
openstacksdk itself. These warnings are derived from ``Warning`` or
``DeprecationWarning``. In Python, warnings are emitted by default while
deprecation warnings are silenced by default and must be turned on using the
``-Wa`` Python command line option or the ``PYTHONWARNINGS`` environment
variable. If you are writing an application that uses openstacksdk, you may
wish to enable some of these warnings during test runs to ensure you migrate
away from deprecated behavior.
Available warnings
------------------

View File

@ -23,6 +23,7 @@ import jsonpatch
from openstack.baremetal.v1._proxy import Proxy
from openstack.cloud import exc
from openstack import warnings as os_warnings
def _normalize_port_list(nics):
@ -317,7 +318,7 @@ class BaremetalCloudMixin:
if wait is not None:
warnings.warn(
"wait argument is deprecated and has no effect",
DeprecationWarning,
os_warnings.OpenStackDeprecationWarning,
)
machine = self.get_machine(uuid)
@ -480,9 +481,8 @@ class BaremetalCloudMixin:
def validate_node(self, uuid):
warnings.warn(
'validate_node is deprecated, please use '
'validate_machine instead',
DeprecationWarning,
'validate_node is deprecated, please use validate_machine instead',
os_warnings.OpenStackDeprecationWarning,
)
self.baremetal.validate_node(uuid)
@ -623,7 +623,7 @@ class BaremetalCloudMixin:
warnings.warn(
"The set_node_instance_info call is deprecated, "
"use patch_machine or update_machine instead",
DeprecationWarning,
os_warnings.OpenStackDeprecationWarning,
)
return self.patch_machine(uuid, patch)
@ -631,7 +631,7 @@ class BaremetalCloudMixin:
warnings.warn(
"The purge_node_instance_info call is deprecated, "
"use patch_machine or update_machine instead",
DeprecationWarning,
os_warnings.OpenStackDeprecationWarning,
)
return self.patch_machine(
uuid, dict(path='/instance_info', op='remove')
@ -649,6 +649,6 @@ class BaremetalCloudMixin:
"The wait_for_baremetal_node_lock call is deprecated "
"in favor of wait_for_node_reservation on the baremetal "
"proxy",
DeprecationWarning,
os_warnings.OpenStackDeprecationWarning,
)
self.baremetal.wait_for_node_reservation(node, timeout)

View File

@ -22,6 +22,7 @@ from openstack.cloud import _utils
from openstack.cloud import exc
from openstack import exceptions
from openstack import proxy
from openstack import warnings as os_warnings
def _no_pending_volumes(volumes):
@ -46,7 +47,7 @@ class BlockStorageCloudMixin:
warnings.warn(
"the 'cache' argument is deprecated and no longer does anything; "
"consider removing it from calls",
DeprecationWarning,
os_warnings.OpenStackDeprecationWarning,
)
return list(self.block_storage.volumes())
@ -63,7 +64,7 @@ class BlockStorageCloudMixin:
warnings.warn(
"the 'get_extra' argument is deprecated and no longer does "
"anything; consider removing it from calls",
DeprecationWarning,
os_warnings.OpenStackDeprecationWarning,
)
return list(self.block_storage.types())

View File

@ -26,6 +26,7 @@ from openstack import exceptions
from openstack.network.v2._proxy import Proxy
from openstack import proxy
from openstack import utils
from openstack import warnings as os_warnings
_CONFIG_DOC_URL = (
"https://docs.openstack.org/openstacksdk/latest/"
@ -66,8 +67,8 @@ class FloatingIPCloudMixin:
# `filters` could be a jmespath expression which Neutron server doesn't
# understand, obviously.
warnings.warn(
"search_floating_ips is deprecated. "
"Use search_resource instead."
"search_floating_ips is deprecated. Use search_resource instead.",
os_warnings.OpenStackDeprecationWarning,
)
if self._use_neutron_floating() and isinstance(filters, dict):
return list(self.network.ips(**filters))

View File

@ -36,7 +36,7 @@ from openstack.config import cloud_region as cloud_region_mod
from openstack import exceptions
from openstack import proxy
from openstack import utils
from openstack import warnings as os_warnings
DEFAULT_SERVER_AGE = 5
DEFAULT_PORT_AGE = 5
@ -303,7 +303,7 @@ class _OpenStackCloudMixin:
app_name=self.config._app_name,
app_version=self.config._app_version,
discovery_cache=self.session._discovery_cache,
**params
**params,
)
# Override the cloud name so that logging/location work right
@ -433,23 +433,21 @@ class _OpenStackCloudMixin:
api_major = self._get_major_version_id(api_version)
# If we detect a different version that was configured, warn the user.
# shade still knows what to do - but if the user gave us an explicit
# version and we couldn't find it, they may want to investigate.
# openstacksdk still knows what to do - but if the user gave us an
# explicit version and we couldn't find it, they may want to
# investigate
if api_version and config_version and (api_major != config_major):
api_version_str = '.'.join([str(f) for f in api_version])
warning_msg = (
'{service_type} is configured for {config_version}'
' but only {api_version} is available. shade is happy'
' with this version, but if you were trying to force an'
' override, that did not happen. You may want to check'
' your cloud, or remove the version specification from'
' your config.'.format(
service_type=service_type,
config_version=config_version,
api_version='.'.join([str(f) for f in api_version]),
)
f'{service_type} is configured for {config_version} but only '
f'{api_version_str} is available. openstacksdk is happy '
f'with this version, but if you were trying to force an '
f'override, that did not happen. You may want to check '
f'your cloud, or remove the version specification from '
f'your config.'
)
self.log.debug(warning_msg)
warnings.warn(warning_msg)
warnings.warn(warning_msg, os_warnings.OpenStackDeprecationWarning)
return adapter
# TODO(shade) This should be replaced with using openstack Connection
@ -790,7 +788,7 @@ class _OpenStackCloudMixin:
get_kwargs=None,
list_args=None,
list_kwargs=None,
**filters
**filters,
):
"""Search resources

View File

@ -40,6 +40,7 @@ from openstack.network.v2 import security_group as _sg
from openstack import proxy
from openstack import resource
from openstack import utils
from openstack import warnings as os_warnings
class Proxy(proxy.Proxy):
@ -483,7 +484,7 @@ class Proxy(proxy.Proxy):
warnings.warn(
'This API is a proxy to the image service and has been '
'deprecated; use the image service proxy API instead',
DeprecationWarning,
os_warnings.OpenStackDeprecationWarning,
)
self._delete(_image.Image, image, ignore_missing=ignore_missing)
@ -508,7 +509,7 @@ class Proxy(proxy.Proxy):
warnings.warn(
'This API is a proxy to the image service and has been '
'deprecated; use the image service proxy API instead',
DeprecationWarning,
os_warnings.OpenStackDeprecationWarning,
)
return self._find(
_image.Image,
@ -529,7 +530,7 @@ class Proxy(proxy.Proxy):
warnings.warn(
'This API is a proxy to the image service and has been '
'deprecated; use the image service proxy API instead',
DeprecationWarning,
os_warnings.OpenStackDeprecationWarning,
)
return self._get(_image.Image, image)
@ -548,7 +549,7 @@ class Proxy(proxy.Proxy):
warnings.warn(
'This API is a proxy to the image service and has been '
'deprecated; use the image service proxy API instead',
DeprecationWarning,
os_warnings.OpenStackDeprecationWarning,
)
base_path = '/images/detail' if details else None
return self._list(_image.Image, base_path=base_path, **query)
@ -1859,7 +1860,10 @@ class Proxy(proxy.Proxy):
'argument. This is legacy behavior that will be removed in '
'a future version. Update callers to use a volume argument.'
)
warnings.warn(deprecation_msg, DeprecationWarning)
warnings.warn(
deprecation_msg,
os_warnings.OpenStackDeprecationWarning,
)
else:
volume_id = resource.Resource._get_id(volume)
@ -1932,7 +1936,10 @@ class Proxy(proxy.Proxy):
if isinstance(server, _volume.Volume) or isinstance(
volume, _server.Server
):
warnings.warn(deprecation_msg, DeprecationWarning)
warnings.warn(
deprecation_msg,
os_warnings.OpenStackDeprecationWarning,
)
return volume, server
# without type info we have to try a find the server corresponding to
@ -1940,7 +1947,10 @@ class Proxy(proxy.Proxy):
if self.find_server(server, ignore_missing=True) is not None:
return server, volume
else:
warnings.warn(deprecation_msg, DeprecationWarning)
warnings.warn(
deprecation_msg,
os_warnings.OpenStackDeprecationWarning,
)
return volume, server
def delete_volume_attachment(self, server, volume, ignore_missing=True):

View File

@ -15,6 +15,7 @@ import warnings
from openstack import exceptions
from openstack import resource
from openstack import utils
from openstack import warnings as os_warnings
class Hypervisor(resource.Resource):
@ -86,7 +87,8 @@ class Hypervisor(resource.Resource):
Updates uptime attribute of the hypervisor object
"""
warnings.warn(
"This call is deprecated and is only available until Nova 2.88"
"This call is deprecated and is only available until Nova 2.88",
os_warnings.LegacyAPIWarning,
)
if utils.supports_microversion(session, '2.88'):
raise exceptions.SDKException(

View File

@ -48,6 +48,7 @@ from openstack.config import defaults as config_defaults
from openstack import exceptions
from openstack import proxy
from openstack import version as openstack_version
from openstack import warnings as os_warnings
_logger = _log.setup_logging('openstack')
@ -100,7 +101,7 @@ def from_session(
force_ipv4=False,
app_name=None,
app_version=None,
**kwargs
**kwargs,
):
"""Construct a CloudRegion from an existing `keystoneauth1.session.Session`
@ -387,11 +388,10 @@ class CloudRegion:
else:
if cacert:
warnings.warn(
"You are specifying a cacert for the cloud {full_name}"
" but also to ignore the host verification. The host SSL"
" cert will not be verified.".format(
full_name=self.full_name
)
f"You are specifying a cacert for the cloud "
f"{self.full_name} but also to ignore the host "
f"verification. The host SSL cert will not be verified.",
os_warnings.ConfigurationWarning,
)
cert = self.config.get('cert')
@ -505,9 +505,10 @@ class CloudRegion:
except ValueError:
if 'latest' in version:
warnings.warn(
"You have a configured API_VERSION with 'latest' in"
" it. In the context of openstacksdk this doesn't make"
" any sense."
"You have a configured API_VERSION with 'latest' in "
"it. In the context of openstacksdk this doesn't make "
"any sense.",
os_warnings.ConfigurationWarning,
)
return None
return version
@ -686,7 +687,7 @@ class CloudRegion:
raise exceptions.ConfigException(
"Problem with auth parameters"
)
(verify, cert) = self.get_requests_verify_args()
verify, cert = self.get_requests_verify_args()
# Turn off urllib3 warnings about insecure certs if we have
# explicitly configured requests to tell it we do not want
# cert verification
@ -876,7 +877,7 @@ class CloudRegion:
default_microversion=version_request.default_microversion,
rate_limit=self.get_rate_limit(service_type),
concurrency=self.get_concurrency(service_type),
**kwargs
**kwargs,
)
if version_request.default_microversion:
default_microversion = version_request.default_microversion
@ -962,7 +963,7 @@ class CloudRegion:
region_name=region_name,
interface=interface,
service_name=service_name,
**version_kwargs
**version_kwargs,
)
except keystoneauth1.exceptions.catalog.EndpointNotFound:
endpoint = None

View File

@ -12,7 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
# alias because we already had an option named argparse
import argparse as argparse_mod
import collections
@ -35,6 +34,7 @@ from openstack.config import cloud_region
from openstack.config import defaults
from openstack.config import vendors
from openstack import exceptions
from openstack import warnings as os_warnings
APPDIRS = appdirs.AppDirs('openstack', 'OpenStack', multipath='/etc')
CONFIG_HOME = APPDIRS.user_config_dir
@ -506,9 +506,10 @@ class OpenStackConfig:
regions = config['region_name'].split(',')
if len(regions) > 1:
warnings.warn(
"Comma separated lists in region_name are deprecated."
" Please use a yaml list in the regions"
" parameter in {0} instead.".format(self.config_filename)
f"Comma separated lists in region_name are deprecated. "
f"Please use a yaml list in the regions "
f"parameter in {self.config_filename} instead.",
os_warnings.OpenStackDeprecationWarning,
)
return self._expand_regions(regions)
else:
@ -585,9 +586,10 @@ class OpenStackConfig:
return
if 'cloud' in our_cloud:
warnings.warn(
"{0} uses the keyword 'cloud' to reference a known "
"vendor profile. This has been deprecated in favor of the "
"'profile' keyword.".format(self.config_filename)
f"{self.config_filename} uses the keyword 'cloud' to "
f"reference a known vendor profile. This has been deprecated "
f"in favor of the 'profile' keyword.",
os_warnings.OpenStackDeprecationWarning,
)
vendor_filename, vendor_file = self._load_vendor_file()
@ -609,9 +611,8 @@ class OpenStackConfig:
message = profile_data.pop('message', '')
if status == 'deprecated':
warnings.warn(
"{profile_name} is deprecated: {message}".format(
profile_name=profile_name, message=message
)
f"{profile_name} is deprecated: {message}",
os_warnings.OpenStackDeprecationWarning,
)
elif status == 'shutdown':
raise exceptions.ConfigException(
@ -624,8 +625,9 @@ class OpenStackConfig:
else:
# Can't find the requested vendor config, go about business
warnings.warn(
"Couldn't find the vendor profile '{0}', for"
" the cloud '{1}'".format(profile_name, name)
f"Couldn't find the vendor profile {profile_name} for"
f"the cloud {name}",
os_warnings.ConfigurationWarning,
)
def _project_scoped(self, cloud):
@ -687,11 +689,10 @@ class OpenStackConfig:
)
if key in cloud:
warnings.warn(
"{key} is deprecated. Please replace with an entry in"
" a dict inside of the networks list with name: {name}"
" and routes_externally: {external}".format(
key=key, name=cloud[key], external=external
)
f"{key} is deprecated. Please replace with an entry in "
f"a dict inside of the networks list with name: "
f"{cloud[key]} and routes_externally: {external}",
os_warnings.OpenStackDeprecationWarning,
)
networks.append(
dict(

View File

@ -18,6 +18,7 @@ from openstack import exceptions
from openstack.image.v1 import image as _image
from openstack import proxy
from openstack import utils
from openstack import warnings as os_warnings
def _get_name_and_filename(name, image_format):
@ -258,7 +259,10 @@ class Proxy(proxy.Proxy):
:returns: The results of image creation
:rtype: :class:`~openstack.image.v1.image.Image`
"""
warnings.warn("upload_image is deprecated. Use create_image instead.")
warnings.warn(
"upload_image is deprecated. Use create_image instead.",
os_warnings.OpenStackDeprecationWarning,
)
return self._create(_image.Image, **attrs)
def _upload_image(

View File

@ -27,6 +27,7 @@ from openstack.image.v2 import task as _task
from openstack import proxy
from openstack import resource
from openstack import utils
from openstack import warnings as os_warnings
# Rackspace returns this for intermittent import errors
_IMAGE_ERROR_396 = "Image cannot be imported. Error code: '396'"
@ -500,7 +501,10 @@ class Proxy(proxy.Proxy):
:returns: The results of image creation
:rtype: :class:`~openstack.image.v2.image.Image`
"""
warnings.warn("upload_image is deprecated. Use create_image instead.")
warnings.warn(
"upload_image is deprecated. Use create_image instead.",
os_warnings.OpenStackDeprecationWarning,
)
# container_format and disk_format are required to be set
# on the image by the time upload_image is called, but they're not
# required by the _create call. Enforce them here so that we don't

View File

@ -39,6 +39,7 @@ from openstack.compute.v2 import usage
from openstack.compute.v2 import volume_attachment
from openstack import resource
from openstack.tests.unit import test_proxy_base
from openstack import warnings as os_warnings
class TestComputeProxy(test_proxy_base.TestProxyBase):
@ -523,7 +524,10 @@ class TestVolumeAttachment(TestComputeProxy):
)
self.assertEqual(1, len(w))
self.assertEqual(w[-1].category, DeprecationWarning)
self.assertEqual(
os_warnings.OpenStackDeprecationWarning,
w[-1].category,
)
self.assertIn(
'This method was called with a volume_id or volumeId argument',
str(w[-1]),

View File

@ -31,5 +31,13 @@ class LegacyAPIWarning(OpenStackDeprecationWarning):
"""Indicates an API that is in 'legacy' status, a long term deprecation."""
class UnsupportedServiceVersion(Warning):
class OpenStackWarning(Warning):
"""Base class for general warnings in openstacksdk."""
class ConfigurationWarning(OpenStackWarning):
"""Indicates an issue with configuration."""
class UnsupportedServiceVersion(OpenStackWarning):
"""Indicates a major version that SDK doesn't understand."""