Merge "Move baremetal clean commands from Ansible"

This commit is contained in:
Zuul 2022-01-25 03:38:36 +00:00 committed by Gerrit Code Review
commit 75b27c6a9d
4 changed files with 138 additions and 60 deletions

View File

@ -114,14 +114,6 @@ class TestBaremetalWorkflows(fakes.FakePlaybookExecution):
def test_configure_manageable_nodes_success(self):
baremetal.configure_manageable_nodes(self.app.client_manager)
def test_clean_nodes_success(self):
baremetal.clean_nodes(node_uuids=[])
def test_clean_manageable_nodes_success(self):
baremetal.clean_manageable_nodes(
self.app.client_manager
)
def test_run_instance_boot_option(self):
result = baremetal._configure_boot(
self.app.client_manager,

View File

@ -266,16 +266,12 @@ class CleanNode(command.Command):
nodes = parsed_args.node_uuids
clean = tb.TripleoClean(verbosity=parsed_args.verbosity)
if nodes:
baremetal.clean_nodes(
node_uuids=parsed_args.node_uuids,
verbosity=oooutils.playbook_verbosity(self=self)
)
clean.clean(
nodes=parsed_args.node_uuids)
else:
baremetal.clean_manageable_nodes(
clients=self.app.client_manager,
verbosity=oooutils.playbook_verbosity(self=self)
)
clean.clean_manageable_nodes()
if parsed_args.provide:
provide = tb.TripleoProvide(verbosity=parsed_args.verbosity)

View File

@ -654,50 +654,6 @@ def discover_and_enroll(clients, ip_addresses, credentials, kernel_name,
)
def clean_nodes(node_uuids, verbosity=0):
"""Clean Baremetal Nodes
:param node_uuids: List of instance UUID(s).
:type node_uuids: List
:param verbosity: Verbosity level
:type verbosity: Integer
"""
with utils.TempDirs() as tmp:
utils.run_ansible_playbook(
playbook='cli-baremetal-clean.yaml',
inventory='localhost,',
workdir=tmp,
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=verbosity,
extra_vars={
'node_uuids': node_uuids
}
)
print('Successfully cleaned nodes: {}'.format(node_uuids))
def clean_manageable_nodes(clients, verbosity=0):
"""Clean all manageable Nodes
:param clients: application client object.
:type clients: Object
:param verbosity: Verbosity level
:type verbosity: Integer
"""
clean_nodes(
node_uuids=[
i.uuid for i in clients.baremetal.node.list()
if i.provision_state == "manageable" and not i.maintenance
],
verbosity=verbosity
)
def apply_bios_configuration(node_uuids, configuration, verbosity=0):
"""Apply BIOS settings on nodes.

View File

@ -12,7 +12,10 @@
# under the License.
import logging
from typing import Dict
from typing import List
from concurrent import futures
from openstack import connect as sdkclient
from openstack import exceptions
from openstack.utils import iterate_timeout
@ -175,3 +178,134 @@ class TripleoProvide(TripleoBaremetal):
def provide_manageable_nodes(self):
self.provide(self.all_manageable_nodes())
class TripleoClean(TripleoBaremetal):
"""TripleoClean manages the Ironic node cleaning process.
:param all_manageable: Should we work on all nodes in the manageable state
:type all_manageable: bool
:param provide: Should we also set the nodes back to the available state
:type provide: bool
:param timeout: How long should we wait before we consider the nodes to
have failed.
:type timeout: integer
:param raid_config: The raid configuration we should configure on the node
:type raid_config: Dictionary
:param concurrency: How many nodes should we do at once
:type concurrency: integer
:param clean_steps: The Ironic cleaning steps that should be executed on
the nodes
:type clean_steps: List
"""
log = logging.getLogger(__name__)
def __init__(self, all_manageable: bool = False, provide: bool = False,
timeout: int = 60, raid_config: Dict = {},
concurrency: int = 1, verbosity: int = 0,
clean_steps: List = [{'interface': 'deploy',
'step': 'erase_devices_metadata'}]):
super().__init__(verbosity=verbosity, timeout=timeout)
self.all_manageable = all_manageable
self.provide = provide
self.raid_config = raid_config
self.clean_steps = clean_steps
self.concurrency = concurrency
def _parallel_nodes_cleaning(self, nodes: List):
client = self.conn.baremetal
node_timeout = self.timeout
clean_steps = self.clean_steps
failed_nodes = []
success_nodes = []
if self.raid_config:
for node in nodes:
try:
client.update_node(
node,
target_raid_config=self.raid_config
)
success_nodes.append(node)
self.log.info("Setting the raid configuration "
"for node {} succeeded.".format(node))
except exceptions.BadRequestException as err:
self.log.error("Setting raid configuration "
"for node {} failed. Error: {}".format(
node, err
))
failed_nodes.append(node)
nodes.pop(nodes.index(node))
workers = min(len(nodes), self.concurrency) or 1
with futures.ThreadPoolExecutor(max_workers=workers) as executor:
future_to_build = {
executor.submit(
client.set_node_provision_state,
node,
"clean",
clean_steps=clean_steps,
wait=True
): node for node in nodes
}
done, not_done = futures.wait(
future_to_build,
timeout=node_timeout,
return_when=futures.ALL_COMPLETED
)
try:
self.log.info(
"Waiting for manageable state: {}".format(nodes))
res = client.wait_for_nodes_provision_state(
nodes=nodes,
expected_state='manageable',
timeout=self.timeout,
fail=False
)
except exceptions.ResourceFailure as e:
self.log.error("Failed providing nodes due to failure: {}".format(
e))
except exceptions.ResourceTimeout as e:
self.log.error("Failed providing nodes due to timeout: {}".format(
e))
finally:
err_nodes = [n.name for n in res if n.last_error]
s_nodes = [n.name for n in res if not n.last_error]
for node in err_nodes:
failed_nodes.append(node)
for node in s_nodes:
success_nodes.append(node)
return(set(failed_nodes), set(success_nodes))
def clean_manageable_nodes(self):
self.clean(nodes=self.all_manageable_nodes())
def clean(self, nodes: List):
"""clean manages the cleaning process for the Ironic nodes.
Using the provided clean steps, this method will clean the provided
baremetal nodes.
:param nodes: A list of nodes to clean
:type nodes: List
"""
if not nodes:
self.log.error("Provide either UUID or names of nodes!")
try:
failed_nodes, success_nodes = self._parallel_nodes_cleaning(
nodes)
if failed_nodes:
msg = ("Cleaning completed with failures. "
f"{failed_nodes} node(s) failed.")
self.log.error(msg)
else:
msg = ("Cleaning completed "
f"successfully: {len(success_nodes)} nodes")
self.log.info(msg)
except exceptions.OpenStackCloudException as err:
self.log.error(str(err))