Add 'openstack overcloud node introspect' command
Change-Id: I1c58d9c825543cf402ff417d1fd05e89759e3ecd Partial-Bug: #1595205
This commit is contained in:
parent
13011dc041
commit
6108b3be7d
@ -67,6 +67,7 @@ openstack.tripleoclient.v1 =
|
||||
overcloud_image_build = tripleoclient.v1.overcloud_image:BuildOvercloudImage
|
||||
overcloud_image_upload = tripleoclient.v1.overcloud_image:UploadOvercloudImage
|
||||
overcloud_node_delete = tripleoclient.v1.overcloud_node:DeleteNode
|
||||
overcloud_node_introspect = tripleoclient.v1.overcloud_node:IntrospectNode
|
||||
overcloud_node_provide = tripleoclient.v1.overcloud_node:ProvideNode
|
||||
overcloud_profiles_match = tripleoclient.v1.overcloud_profiles:MatchProfiles
|
||||
overcloud_profiles_list = tripleoclient.v1.overcloud_profiles:ListProfiles
|
||||
|
@ -128,3 +128,109 @@ class TestProvideNode(fakes.TestOvercloudNode):
|
||||
self.assertRaises(test_utils.ParserException,
|
||||
self.check_parser,
|
||||
self.cmd, argslist, verifylist)
|
||||
|
||||
|
||||
class TestIntrospectNode(fakes.TestOvercloudNode):
|
||||
|
||||
def setUp(self):
|
||||
super(TestIntrospectNode, self).setUp()
|
||||
|
||||
self.workflow = self.app.client_manager.workflow_engine
|
||||
client = self.app.client_manager.tripleoclient
|
||||
self.websocket = client.messaging_websocket()
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = overcloud_node.IntrospectNode(self.app, None)
|
||||
|
||||
def _check_introspect_all_manageable(self, parsed_args, provide=False):
|
||||
self.websocket.wait_for_message.return_value = {
|
||||
"status": "SUCCESS",
|
||||
"message": "Success",
|
||||
"introspected_nodes": {}
|
||||
}
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
call_list = [mock.call(
|
||||
'tripleo.baremetal.v1.introspect_manageable_nodes',
|
||||
workflow_input={'queue_name': 'UUID4'}
|
||||
)]
|
||||
|
||||
if provide:
|
||||
call_list.append(mock.call(
|
||||
'tripleo.baremetal.v1.provide_manageable_nodes',
|
||||
workflow_input={'queue_name': 'UUID4'}
|
||||
))
|
||||
|
||||
self.workflow.executions.create.assert_has_calls(call_list)
|
||||
self.assertEqual(self.workflow.executions.create.call_count,
|
||||
2 if provide else 1)
|
||||
|
||||
def _check_introspect_nodes(self, parsed_args, nodes, provide=False):
|
||||
self.websocket.wait_for_message.return_value = {
|
||||
"status": "SUCCESS",
|
||||
"message": "Success",
|
||||
"introspected_nodes": {}
|
||||
}
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
call_list = [mock.call(
|
||||
'tripleo.baremetal.v1.introspect', workflow_input={
|
||||
'node_uuids': nodes,
|
||||
'queue_name': 'UUID4'}
|
||||
)]
|
||||
|
||||
if provide:
|
||||
call_list.append(mock.call(
|
||||
'tripleo.baremetal.v1.provide', workflow_input={
|
||||
'node_uuids': nodes,
|
||||
'queue_name': 'UUID4'}
|
||||
))
|
||||
|
||||
self.workflow.executions.create.assert_has_calls(call_list)
|
||||
self.assertEqual(self.workflow.executions.create.call_count,
|
||||
2 if provide else 1)
|
||||
|
||||
def test_introspect_all_manageable_nodes_without_provide(self):
|
||||
parsed_args = self.check_parser(self.cmd,
|
||||
['--all-manageable'],
|
||||
[('all_manageable', True)])
|
||||
self._check_introspect_all_manageable(parsed_args, provide=False)
|
||||
|
||||
def test_introspect_all_manageable_nodes_with_provide(self):
|
||||
parsed_args = self.check_parser(self.cmd,
|
||||
['--all-manageable', '--provide'],
|
||||
[('all_manageable', True),
|
||||
('provide', True)])
|
||||
self._check_introspect_all_manageable(parsed_args, provide=True)
|
||||
|
||||
def test_introspect_nodes_without_provide(self):
|
||||
nodes = ['node_uuid1', 'node_uuid2']
|
||||
parsed_args = self.check_parser(self.cmd,
|
||||
nodes,
|
||||
[('node_uuids', nodes)])
|
||||
self._check_introspect_nodes(parsed_args, nodes, provide=False)
|
||||
|
||||
def test_introspect_nodes_with_provide(self):
|
||||
nodes = ['node_uuid1', 'node_uuid2']
|
||||
argslist = nodes + ['--provide']
|
||||
|
||||
parsed_args = self.check_parser(self.cmd,
|
||||
argslist,
|
||||
[('node_uuids', nodes),
|
||||
('provide', True)])
|
||||
self._check_introspect_nodes(parsed_args, nodes, provide=True)
|
||||
|
||||
def test_introspect_no_node_or_flag_specified(self):
|
||||
self.assertRaises(test_utils.ParserException,
|
||||
self.check_parser,
|
||||
self.cmd, [], [])
|
||||
|
||||
def test_introspect_uuids_and_all_both_specified(self):
|
||||
argslist = ['node_id1', 'node_id2', '--all-manageable']
|
||||
verifylist = [('node_uuids', ['node_id1', 'node_id2']),
|
||||
('all_manageable', True)]
|
||||
self.assertRaises(test_utils.ParserException,
|
||||
self.check_parser,
|
||||
self.cmd, argslist, verifylist)
|
||||
|
@ -120,6 +120,45 @@ class TestBaremetalWorkflows(utils.TestCommand):
|
||||
'queue_name': "QUEUE_NAME"
|
||||
})
|
||||
|
||||
def test_introspect_success(self):
|
||||
|
||||
self.websocket.wait_for_message.return_value = {
|
||||
"status": "SUCCESS",
|
||||
"introspected_nodes": {}
|
||||
}
|
||||
|
||||
baremetal.introspect(self.app.client_manager, node_uuids=[],
|
||||
queue_name="QUEUE_NAME")
|
||||
|
||||
self.workflow.executions.create.assert_called_once_with(
|
||||
'tripleo.baremetal.v1.introspect',
|
||||
workflow_input={
|
||||
'node_uuids': [],
|
||||
'queue_name': "QUEUE_NAME"
|
||||
})
|
||||
|
||||
def test_introspect_error(self):
|
||||
|
||||
self.websocket.wait_for_message.return_value = {
|
||||
"status": "FAIL",
|
||||
"message": "Failed",
|
||||
"introspected_nodes": {}
|
||||
}
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.IntrospectionError,
|
||||
baremetal.introspect,
|
||||
self.app.client_manager,
|
||||
node_uuids=[],
|
||||
queue_name="QUEUE_NAME")
|
||||
|
||||
self.workflow.executions.create.assert_called_once_with(
|
||||
'tripleo.baremetal.v1.introspect',
|
||||
workflow_input={
|
||||
'node_uuids': [],
|
||||
'queue_name': "QUEUE_NAME"
|
||||
})
|
||||
|
||||
def test_introspect_manageable_nodes_success(self):
|
||||
|
||||
self.websocket.wait_for_message.return_value = {
|
||||
|
@ -241,13 +241,19 @@ class ImportBaremetal(command.Command):
|
||||
|
||||
|
||||
class StartBaremetalIntrospectionBulk(command.Command):
|
||||
"""Start bulk introspection on all baremetal nodes"""
|
||||
"""Start bulk introspection on all baremetal nodes (Deprecated).
|
||||
|
||||
Please use 'openstack overcloud node introspect' instead.
|
||||
"""
|
||||
|
||||
log = logging.getLogger(__name__ + ".StartBaremetalIntrospectionBulk")
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
|
||||
self.log.debug("take_action(%s)" % parsed_args)
|
||||
self.log.warning('This command is deprecated. Please use "openstack '
|
||||
'overcloud node introspect" to introspect manageable '
|
||||
'nodes instead.\n')
|
||||
|
||||
queue_name = str(uuid.uuid4())
|
||||
clients = self.app.client_manager
|
||||
|
@ -98,3 +98,51 @@ class ProvideNode(command.Command):
|
||||
else:
|
||||
baremetal.provide_manageable_nodes(self.app.client_manager,
|
||||
queue_name=queue_name)
|
||||
|
||||
|
||||
class IntrospectNode(command.Command):
|
||||
"""Introspect specified nodes or all nodes in 'manageable' state."""
|
||||
|
||||
log = logging.getLogger(__name__ + ".IntrospectNode")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(IntrospectNode, self).get_parser(prog_name)
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument('node_uuids',
|
||||
nargs="*",
|
||||
metavar="<node_uuid>",
|
||||
default=[],
|
||||
help=_('Ironic UUIDs for the node(s) to be '
|
||||
'introspected'))
|
||||
group.add_argument("--all-manageable",
|
||||
action='store_true',
|
||||
help=_("Introspect all nodes currently in "
|
||||
"'manageable' state"))
|
||||
parser.add_argument('--provide',
|
||||
action='store_true',
|
||||
help=_('Provide (make available) the nodes once '
|
||||
'introspected'))
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug("take_action(%s)" % parsed_args)
|
||||
|
||||
queue_name = str(uuid.uuid4())
|
||||
nodes = parsed_args.node_uuids
|
||||
|
||||
if nodes:
|
||||
baremetal.introspect(self.app.client_manager,
|
||||
node_uuids=nodes,
|
||||
queue_name=queue_name)
|
||||
else:
|
||||
baremetal.introspect_manageable_nodes(self.app.client_manager,
|
||||
queue_name=queue_name)
|
||||
|
||||
if parsed_args.provide:
|
||||
if nodes:
|
||||
baremetal.provide(self.app.client_manager,
|
||||
node_uuids=nodes,
|
||||
queue_name=queue_name)
|
||||
else:
|
||||
baremetal.provide_manageable_nodes(self.app.client_manager,
|
||||
queue_name=queue_name)
|
||||
|
@ -70,6 +70,37 @@ def provide(clients, **workflow_input):
|
||||
payload['message']))
|
||||
|
||||
|
||||
def introspect(clients, **workflow_input):
|
||||
"""Introspect Baremetal Nodes
|
||||
|
||||
Run the tripleo.baremetal.v1.introspect Mistral workflow.
|
||||
"""
|
||||
|
||||
workflow_client = clients.workflow_engine
|
||||
tripleoclients = clients.tripleoclient
|
||||
queue_name = workflow_input['queue_name']
|
||||
|
||||
execution = workflow_client.executions.create(
|
||||
'tripleo.baremetal.v1.introspect',
|
||||
workflow_input={'node_uuids': workflow_input['node_uuids'],
|
||||
'queue_name': queue_name}
|
||||
)
|
||||
|
||||
print("Waiting for introspection to finish...")
|
||||
|
||||
with tripleoclients.messaging_websocket(queue_name) as ws:
|
||||
payload = ws.wait_for_message(execution.id)
|
||||
|
||||
if payload['status'] == 'SUCCESS':
|
||||
print('Successfully introspected all nodes.')
|
||||
else:
|
||||
raise exceptions.IntrospectionError(
|
||||
"Introspection completed with errors:\n%s" % '\n'
|
||||
.join(msg for msg in payload['message'] if msg))
|
||||
|
||||
print("Introspection completed.")
|
||||
|
||||
|
||||
def introspect_manageable_nodes(clients, **workflow_input):
|
||||
"""Introspect all manageable nodes
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user