Merge "Testing bad microversions on v1/nodes/{uuid}/firmware"
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..62b24c9
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,66 @@
+---
+default_language_version:
+ # force all unspecified python hooks to run python3
+ python: python3
+repos:
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v4.5.0
+ hooks:
+ - id: trailing-whitespace
+ # NOTE(JayF): We shouldn't modify release notes after their
+ # associated release. Instead, ignore these minor lint issues.
+ - id: mixed-line-ending
+ args: ['--fix', 'lf']
+ exclude: |
+ (?x)(
+ .*.svg$|
+ )
+ - id: fix-byte-order-marker
+ - id: check-merge-conflict
+ - id: debug-statements
+ - id: check-json
+ files: .*\.json$
+ - id: check-yaml
+ files: .*\.(yaml|yml)$
+ exclude: releasenotes/.*$
+ - repo: https://github.com/Lucas-C/pre-commit-hooks
+ rev: v1.5.4
+ hooks:
+ - id: remove-tabs
+ exclude: '.*\.(svg)$'
+ - repo: https://opendev.org/openstack/hacking
+ rev: 6.1.0
+ hooks:
+ - id: hacking
+ additional_dependencies: []
+ exclude: '^(doc|releasenotes|tools)/.*$'
+ - repo: https://github.com/codespell-project/codespell
+ rev: v2.4.1
+ hooks:
+ - id: codespell
+ args: [--write-changes]
+ - repo: https://github.com/sphinx-contrib/sphinx-lint
+ rev: v1.0.0
+ hooks:
+ - id: sphinx-lint
+ args: [--enable=default-role]
+ files: ^doc/|releasenotes|api-ref
+ - repo: https://opendev.org/openstack/bashate
+ rev: 2.1.0
+ hooks:
+ - id: bashate
+ args: ["-iE006,E044", "-eE005,E042"]
+ name: bashate
+ description: This hook runs bashate for linting shell scripts
+ entry: bashate
+ language: python
+ types: [shell]
+ - repo: https://github.com/PyCQA/doc8
+ rev: v1.1.2
+ hooks:
+ - id: doc8
+ - repo: https://github.com/astral-sh/ruff-pre-commit
+ rev: v0.7.3
+ hooks:
+ - id: ruff
+ args: ['--fix', '--unsafe-fixes']
diff --git a/ironic_tempest_plugin/common/waiters.py b/ironic_tempest_plugin/common/waiters.py
index e538cd8..cd13fe7 100644
--- a/ironic_tempest_plugin/common/waiters.py
+++ b/ironic_tempest_plugin/common/waiters.py
@@ -180,7 +180,7 @@
field_value = node[field]
if raise_if_insufficent_access and '** Redacted' in field_value:
msg = ('Unable to see contents of redacted field '
- 'indicating insufficent access to execute this test.')
+ 'indicating insufficient access to execute this test.')
raise lib_exc.InsufficientAPIAccess(msg)
return value in field_value
diff --git a/ironic_tempest_plugin/exceptions.py b/ironic_tempest_plugin/exceptions.py
index 865ab08..a1a9873 100644
--- a/ironic_tempest_plugin/exceptions.py
+++ b/ironic_tempest_plugin/exceptions.py
@@ -30,5 +30,5 @@
class InsufficientAPIAccess(exceptions.TempestException):
- message = ("Insufficent Access to the API exists. Please use a user "
+ message = ("Insufficient Access to the API exists. Please use a user "
"with an elevated level of access to execute this test.")
diff --git a/ironic_tempest_plugin/tests/api/base.py b/ironic_tempest_plugin/tests/api/base.py
index 11ce859..c07137b 100644
--- a/ironic_tempest_plugin/tests/api/base.py
+++ b/ironic_tempest_plugin/tests/api/base.py
@@ -523,8 +523,8 @@
class BaseBaremetalRBACTest(BaseBaremetalTest):
- # Unless otherwise superceeded by a version, RBAC tests generally start at
- # version 1.70 as that is when System scope and the delineation occured.
+ # Unless otherwise superseded by a version, RBAC tests generally start at
+ # version 1.70 as that is when System scope and the delineation occurred.
min_microversion = '1.70'
@classmethod
diff --git a/ironic_tempest_plugin/tests/api/rbac_defaults/test_nodes.py b/ironic_tempest_plugin/tests/api/rbac_defaults/test_nodes.py
index cd16fe2..2af624a 100644
--- a/ironic_tempest_plugin/tests/api/rbac_defaults/test_nodes.py
+++ b/ironic_tempest_plugin/tests/api/rbac_defaults/test_nodes.py
@@ -675,7 +675,7 @@
All tests here must always expect *multiple* nodes visible, since
this is a global reader role.
- https://opendev.org/openstack/ironic/src/branch/master/ironic/common/policy.py#L60 # noqa
+ https://opendev.org/openstack/ironic/src/branch/master/ironic/common/policy.py#L60
"""
credentials = ['system_admin', 'system_reader']
diff --git a/ironic_tempest_plugin/tests/scenario/baremetal_manager.py b/ironic_tempest_plugin/tests/scenario/baremetal_manager.py
index e9090cb..ad9e4c9 100644
--- a/ironic_tempest_plugin/tests/scenario/baremetal_manager.py
+++ b/ironic_tempest_plugin/tests/scenario/baremetal_manager.py
@@ -16,10 +16,12 @@
import time
+from oslo_log import log as logging
from tempest.common import waiters
from tempest import config
from tempest.lib.common import api_version_utils
from tempest.lib.common.utils.linux import remote_client
+from tempest.lib.common.utils import test_utils
from tempest.lib import exceptions as lib_exc
from ironic_tempest_plugin.common import utils
@@ -27,6 +29,7 @@
from ironic_tempest_plugin import manager
CONF = config.CONF
+LOG = logging.getLogger(__name__)
def retry_on_conflict(func):
@@ -307,3 +310,44 @@
instance['id'], 'ACTIVE')
# Verify server connection
self.get_remote_client(server_ip, server=instance)
+
+ def wait_for_ssh(self, ip_address,
+ username=None,
+ private_key=None,
+ server=None,
+ timeout=60,
+ delay=10):
+ def _wait_ssh():
+ try:
+ self.get_remote_client(ip_address, username, private_key,
+ server=server)
+ except Exception:
+ LOG.debug("Failed to get ssh client for %s", ip_address,
+ exc_info=True)
+ return False
+ return True
+
+ res = test_utils.call_until_true(_wait_ssh, timeout, delay)
+ self.assertTrue(res, f"Failed to wait for ssh on {ip_address}")
+
+ def check_vm_connectivity(self,
+ ip_address,
+ username=None,
+ private_key=None,
+ should_connect=True,
+ extra_msg="",
+ server=None,
+ mtu=None):
+ # NOTE(vsaienko): it may take some time to boot VM and initialize
+ # ssh by cloud init. Wait for SSH can pass authentication before
+ # checking connectivity.
+ if should_connect:
+ self.wait_for_ssh(ip_address=ip_address, username=username,
+ private_key=private_key, server=server)
+ super().check_vm_connectivity(ip_address=ip_address,
+ username=username,
+ private_key=private_key,
+ should_connect=should_connect,
+ extra_msg=extra_msg,
+ server=server,
+ mtu=mtu)
diff --git a/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py b/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py
index ddb550b..7fa8cb5 100644
--- a/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py
+++ b/ironic_tempest_plugin/tests/scenario/baremetal_standalone_manager.py
@@ -343,7 +343,7 @@
:param image_ref: Reference to user image to boot node with.
:param image_checksum: md5sum of image specified in image_ref.
Needed only when direct HTTP link is provided.
- :param boot_option: The defaut boot option to utilize. If not
+ :param boot_option: The default boot option to utilize. If not
specified, the ironic deployment default shall
be utilized.
:param config_drive_networking: If we should load configuration drive
@@ -583,7 +583,7 @@
# If we don't require an explicit driver, then what drivers *can* we
# operate with. In essence, this exists to prevent the test from failing
# on 3rd party drivers, and vendor specific driers which do not support
- # the sort of itnerfaces we may be trying to test by default.
+ # the sort of interfaces we may be trying to test by default.
valid_driver_list = []
# The bios interface to use by the HW type. The bios interface of the
@@ -719,7 +719,7 @@
if (cls.use_available_driver
and not cls.driver
and cls.node['driver'] in cls.valid_driver_list):
- # If we're attempting to re-use the existing driver, then
+ # If we're attempting to reuse the existing driver, then
# lets save a value for update_node_driver to work with.
cls.driver = cls.node['driver']
cls.update_node_driver(cls.node['uuid'], cls.driver, **boot_kwargs)
diff --git a/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_basic_ops.py b/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_basic_ops.py
index 5901d20..e16bfad 100644
--- a/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_basic_ops.py
+++ b/ironic_tempest_plugin/tests/scenario/ironic_standalone/test_basic_ops.py
@@ -638,7 +638,7 @@
use_available_driver = True
# List of valid drivers which these tests *can* attempt to utilize.
- # Generally these should be the most commom, stock, upstream drivers.
+ # Generally these should be the most common, stock, upstream drivers.
valid_driver_list = ['ipmi', 'redfish']
# Bypass secondary attribute presence check as these tests don't require
diff --git a/ironic_tempest_plugin/tests/scenario/test_baremetal_basic_ops.py b/ironic_tempest_plugin/tests/scenario/test_baremetal_basic_ops.py
index 2a36c6a..dcfc023 100644
--- a/ironic_tempest_plugin/tests/scenario/test_baremetal_basic_ops.py
+++ b/ironic_tempest_plugin/tests/scenario/test_baremetal_basic_ops.py
@@ -237,20 +237,6 @@
self.rescue_instance(self.instance, self.node, ip_address)
self.unrescue_instance(self.instance, self.node, ip_address)
- # Reboot node
- self.reboot_node(self.instance)
-
- # Ensure we have some sort of connectivity
- # Attempt to ping, if all else fails fall back to an ssh connection
- # which worked previously.
- pinging = self.ping_ip_address(ip_address)
- if not pinging:
- self.get_remote_client(ip_address, server=self.instance)
- else:
- # If we're here, this is successful. If ssh fails above,
- # the job will ultimately fail.
- self.assertTrue(pinging)
-
self.terminate_instance(self.instance)
@decorators.idempotent_id('549173a5-38ec-42bb-b0e2-c8b9f4a08943')
diff --git a/ironic_tempest_plugin/tests/scenario/test_introspection_basic.py b/ironic_tempest_plugin/tests/scenario/test_introspection_basic.py
index f30b5e0..44b8f98 100644
--- a/ironic_tempest_plugin/tests/scenario/test_introspection_basic.py
+++ b/ironic_tempest_plugin/tests/scenario/test_introspection_basic.py
@@ -61,9 +61,6 @@
* Verifies all properties are inspected
* Verifies introspection data
* Sets node to available state
- * Creates a keypair
- * Boots an instance using the keypair
- * Deletes the instance
"""
# prepare introspection rule
@@ -103,11 +100,6 @@
timeout=CONF.baremetal.active_timeout,
interval=self.wait_provisioning_state_interval)
- self.wait_for_nova_aware_of_bvms()
- self.add_keypair()
- ins, _node = self.boot_instance()
- self.terminate_instance(ins)
-
@decorators.idempotent_id('70ca3070-184b-4b7d-8892-e977d2bc2870')
def test_introspection_abort(self):
"""This smoke test case follows this very basic set of operations:
diff --git a/ironic_tempest_plugin/tests/scenario/test_introspection_discovery.py b/ironic_tempest_plugin/tests/scenario/test_introspection_discovery.py
index 6ebfcc6..9950453 100644
--- a/ironic_tempest_plugin/tests/scenario/test_introspection_discovery.py
+++ b/ironic_tempest_plugin/tests/scenario/test_introspection_discovery.py
@@ -136,13 +136,13 @@
* Generate discovery rule;
* Start introspection via ironic-inspector API;
* Delete the node from ironic;
- * Wating for node discovery;
+ * Waiting for node discovery;
* Verify introspected node.
"""
# NOTE(aarefiev): workaround for infra, 'tempest' user doesn't
# have virsh privileges, so lets power on the node via ironic
# and then delete it. Because of node is blacklisted in inspector
- # we can't just power on it, therefor start introspection is used
+ # we can't just power on it, therefore start introspection is used
# to whitelist discovered node first.
self.baremetal_client.set_node_provision_state(
self.node_info['uuid'], 'manage')
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..4fa5ffd
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,18 @@
+[build-system]
+requires = ["pbr>=6.0.0", "setuptools>=64.0.0"]
+build-backend = "pbr.build"
+
+[tool.doc8]
+ignore = ["D001"]
+
+[tool.ruff]
+line-length = 79
+target-version = "py37"
+
+[tool.ruff.lint]
+select = [
+ "E", # pycodestyle (error)
+ "F", # pyflakes
+ "G", # flake8-logging-format
+ "LOG", # flake8-logging
+]
diff --git a/requirements.txt b/requirements.txt
index bfafa58..ff7b704 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,4 @@
-pbr>=2.0.0 # Apache-2.0
+pbr>=6.0.0 # Apache-2.0
oslo.config>=5.2.0 # Apache-2.0
oslo.log>=3.36.0 # Apache-2.0
oslo.serialization>=2.18.0 # Apache-2.0
diff --git a/setup.py b/setup.py
index cd35c3c..b997e51 100644
--- a/setup.py
+++ b/setup.py
@@ -16,5 +16,5 @@
import setuptools
setuptools.setup(
- setup_requires=['pbr>=2.0.0'],
+ setup_requires=['pbr>=6.0.0'],
pbr=True)
diff --git a/tox.ini b/tox.ini
index 3a67abc..bf8061c 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-minversion = 3.18.0
+minversion = 4.4.0
envlist = pep8
ignore_basepython_conflict=true
@@ -14,11 +14,9 @@
commands = stestr run --slowest {posargs}
[testenv:pep8]
-deps =
- hacking~=6.0.0 # Apache-2.0
- flake8-import-order>=0.17.1 # LGPLv3
- pycodestyle>=2.0.0,<3.0.0 # MIT
-commands = flake8 {posargs}
+deps = pre-commit
+allowlist_externals = pre-commit
+commands = pre-commit run --all-files --show-diff-on-failure {posargs}
[testenv:venv]
commands = {posargs}