Merge "Move baremetal clean commands from Ansible"
This commit is contained in:
commit
75b27c6a9d
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue