Remove mistral when running the register_or_update workflow

This change removes all of mistral from the register_or_update workflow
by calling the required functions directly.

Story: 2007212
Task: 38442

Closes-Bug: #1866637
Change-Id: Ie85adc64cd4fcec469d6979a424d8f01b00f34f2
Signed-off-by: Kevin Carter <kecarter@redhat.com>
changes/83/709583/14
Kevin Carter 2020-02-24 12:28:58 -06:00
parent ed75570496
commit ad9c7a7504
No known key found for this signature in database
GPG Key ID: CE94BD890A47B20A
10 changed files with 196 additions and 617 deletions

View File

@ -84,24 +84,26 @@ class FakeFile(FakeHandle):
self.contents = None
class FakeWebSocket(FakeHandle):
def wait_for_messages(self, timeout=None):
yield {
'execution_id': 'IDID',
'status': 'SUCCESS',
}
class FakeClientWrapper(object):
def __init__(self):
self.ws = FakeWebSocket()
self.object_store = FakeObjectClient()
self._instance = mock.Mock()
self.object_store = FakeObjectClient()
self._mock_websocket = mock.Mock()
self._mock_websocket.__enter__ = mock.Mock(
return_value=self._mock_websocket)
# Return False to avoid silencing exceptions
self._mock_websocket.__exit__ = mock.Mock(return_value=False)
self._mock_websocket.wait_for_messages = mock.Mock(
return_value=iter([{
"status": "SUCCESS",
"message": "Success",
"execution_id": "IDID"
}])
)
def messaging_websocket(self):
return self.ws
return self._mock_websocket
class FakeRunnerConfig(object):
@ -169,7 +171,8 @@ class FakePlaybookExecution(utils.TestCommand):
self.app.client_manager.image = mock.Mock()
self.app.client_manager.network = mock.Mock()
tc = self.app.client_manager.tripleoclient = FakeClientWrapper()
self.app.client_manager.workflow_engine = mock.Mock()
self.tripleoclient = mock.Mock()
self.workflow = self.app.client_manager.workflow_engine = mock.Mock()
stack = self.app.client_manager.orchestration = mock.Mock()
stack.stacks.get.return_value = FakeStackObject
tc.create_mistral_context = plugin.ClientWrapper(
@ -177,10 +180,9 @@ class FakePlaybookExecution(utils.TestCommand):
).create_mistral_context
# NOTE(cloudnull): When mistral is gone this should be removed.
workflow = execution = mock.Mock()
execution.id = "IDID"
workflow.executions.create.return_value = execution
self.app.client_manager.workflow_engine = workflow
self.execution = mock.Mock()
self.execution.id = "IDID"
self.workflow.executions.create.return_value = self.execution
config_mock = mock.patch(
'tripleo_common.actions.config.GetOvercloudConfig',
@ -207,6 +209,14 @@ class FakePlaybookExecution(utils.TestCommand):
get_key.return_value = 'keyfile-path'
self.addCleanup(get_key.stop)
self.register_or_update = mock.patch(
'tripleo_common.actions.baremetal.RegisterOrUpdateNodes.run',
autospec=True,
return_value=[mock.Mock(uuid='MOCK_NODE_UUID')]
)
self.register_or_update.start()
self.addCleanup(self.register_or_update.stop)
if ansible_mock:
get_stack = mock.patch('tripleoclient.utils.get_stack')
get_stack.start()

View File

@ -13,46 +13,16 @@
# under the License.
#
import mock
from osc_lib.tests import utils
from tripleoclient import plugin
from tripleoclient.tests import fakes
class FakeClientWrapper(object):
def __init__(self):
self._instance = mock.Mock()
self._mock_websocket = mock.Mock()
self._mock_websocket.__enter__ = mock.Mock(
return_value=self._mock_websocket)
# Return False to avoid silencing exceptions
self._mock_websocket.__exit__ = mock.Mock(return_value=False)
def messaging_websocket(self):
return self._mock_websocket
class TestDeleteNode(utils.TestCommand):
class TestDeleteNode(fakes.FakePlaybookExecution):
def setUp(self):
super(TestDeleteNode, self).setUp()
self.app.client_manager.auth_ref = mock.Mock(auth_token="TOKEN")
self.app.client_manager.orchestration = mock.Mock()
self.app.client_manager.tripleoclient = FakeClientWrapper()
class TestOvercloudNode(utils.TestCommand):
class TestOvercloudNode(fakes.FakePlaybookExecution):
def setUp(self):
super(TestOvercloudNode, self).setUp()
self.app.client_manager.baremetal = mock.Mock()
self.app.client_manager.workflow_engine = mock.Mock()
tc = self.app.client_manager.tripleoclient = FakeClientWrapper()
tc.create_mistral_context = plugin.ClientWrapper(
instance=fakes.FakeInstanceData
).create_mistral_context

View File

@ -15,21 +15,23 @@
import collections
import copy
import fixtures
import json
import mock
import os
import tempfile
import fixtures
from osc_lib import exceptions as oscexc
from osc_lib.tests import utils as test_utils
import yaml
from tripleoclient import constants
from tripleoclient import exceptions
from tripleoclient import plugin
from tripleoclient.tests import fakes as ooofakes
from tripleoclient.tests.v1.overcloud_node import fakes
from tripleoclient.v1 import overcloud_node
from tripleoclient.v2 import overcloud_node as overcloud_node_v2
class TestDeleteNode(fakes.TestDeleteNode):
@ -45,31 +47,7 @@ class TestDeleteNode(fakes.TestDeleteNode):
self.websocket = mock.Mock()
self.websocket.__enter__ = lambda s: self.websocket
self.websocket.__exit__ = lambda s, *exc: None
self.tripleoclient = mock.Mock()
self.tripleoclient.messaging_websocket.return_value = self.websocket
tc = self.app.client_manager.tripleoclient = self.tripleoclient
tc.create_mistral_context = plugin.ClientWrapper(
instance=ooofakes.FakeInstanceData
).create_mistral_context
self.gcn = mock.patch(
'tripleo_common.actions.config.DownloadConfigAction',
autospec=True
)
self.gcn.start()
self.addCleanup(self.gcn.stop)
self.ansible = mock.patch(
'tripleo_common.actions.ansible.AnsibleGenerateInventoryAction',
autospec=True
)
self.ansible.start()
self.addCleanup(self.ansible.stop)
config_mock = mock.patch(
'tripleo_common.actions.config.GetOvercloudConfig',
autospec=True
)
config_mock.start()
self.addCleanup(config_mock.stop)
self.workflow = self.app.client_manager.workflow_engine
self.stack_name = self.app.client_manager.orchestration.stacks.get
stack = self.stack_name.return_value = mock.Mock(
@ -95,6 +73,7 @@ class TestDeleteNode(fakes.TestDeleteNode):
wait_stack.start()
wait_stack.return_value = None
self.addCleanup(wait_stack.stop)
self.app.client_manager.compute.servers.get.return_value = None
# TODO(someone): This test does not pass with autospec=True, it should
# probably be fixed so that it can pass with that.
@ -125,24 +104,24 @@ class TestDeleteNode(fakes.TestDeleteNode):
self.cmd.take_action,
parsed_args)
def test_node_wrong_stack(self):
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True,
side_effect=exceptions.InvalidConfiguration)
def test_node_wrong_stack(self, mock_playbook):
argslist = ['instance1', '--templates',
'--stack', 'overcast', '--yes']
verifylist = [
('stack', 'overcast'),
('nodes', ['instance1', ])
]
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
self.stack_name.return_value = None
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
self.assertRaises(exceptions.InvalidConfiguration,
self.cmd.take_action,
parsed_args)
# Verify
self.workflow.executions.create.assert_not_called()
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
def test_node_delete_without_stack(self, mock_playbook):
@ -461,116 +440,6 @@ class TestProvideNode(fakes.TestOvercloudNode):
self.cmd, argslist, verifylist)
class TestIntrospectNode(fakes.TestOvercloudNode):
def setUp(self):
super(TestIntrospectNode, self).setUp()
self.workflow = self.app.client_manager.workflow_engine
execution = mock.Mock()
execution.id = "IDID"
self.workflow.executions.create.return_value = execution
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_messages.return_value = iter([{
"status": "SUCCESS",
"message": "Success",
"introspected_nodes": {},
"execution_id": "IDID"
}] * 2)
self.cmd.take_action(parsed_args)
call_list = [mock.call(
'tripleo.baremetal.v1.introspect_manageable_nodes',
workflow_input={'run_validations': False, 'concurrency': 20}
)]
if provide:
call_list.append(mock.call(
'tripleo.baremetal.v1.provide_manageable_nodes',
workflow_input={}
))
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_messages.return_value = [{
"status": "SUCCESS",
"message": "Success",
"execution_id": "IDID",
}]
self.cmd.take_action(parsed_args)
call_list = [mock.call(
'tripleo.baremetal.v1.introspect', workflow_input={
'node_uuids': nodes,
'run_validations': False,
'concurrency': 20}
)]
if provide:
call_list.append(mock.call(
'tripleo.baremetal.v1.provide', workflow_input={
'node_uuids': nodes}
))
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)
class TestCleanNode(fakes.TestOvercloudNode):
def setUp(self):
@ -666,156 +535,6 @@ class TestCleanNode(fakes.TestOvercloudNode):
self._check_clean_nodes(parsed_args, nodes, provide=True)
class TestImportNode(fakes.TestOvercloudNode):
def setUp(self):
super(TestImportNode, self).setUp()
self.nodes_list = [{
"pm_user": "stack",
"pm_addr": "192.168.122.1",
"pm_password": "KEY1",
"pm_type": "pxe_ssh",
"mac": [
"00:0b:d0:69:7e:59"
],
}, {
"pm_user": "stack",
"pm_addr": "192.168.122.2",
"pm_password": "KEY2",
"pm_type": "pxe_ssh",
"mac": [
"00:0b:d0:69:7e:58"
]
}]
self.json_file = tempfile.NamedTemporaryFile(
mode='w', delete=False, suffix='.json')
json.dump(self.nodes_list, self.json_file)
self.json_file.close()
self.addCleanup(os.unlink, self.json_file.name)
self.workflow = self.app.client_manager.workflow_engine
execution = mock.Mock()
execution.id = "IDID"
self.workflow.executions.create.return_value = execution
client = self.app.client_manager.tripleoclient
self.websocket = client.messaging_websocket()
# Get the command object to test
self.cmd = overcloud_node.ImportNode(self.app, None)
image = collections.namedtuple('image', ['id', 'name'])
self.app.client_manager.image = mock.Mock()
self.app.client_manager.image.images.list.return_value = [
image(id=3, name='overcloud-full'),
]
self.http_boot = '/var/lib/ironic/httpboot'
self.useFixture(fixtures.MockPatch(
'os.path.exists', autospec=True,
side_effect=lambda path: path in [os.path.join(self.http_boot, i)
for i in ('agent.kernel',
'agent.ramdisk')]))
def _check_workflow_call(self, parsed_args, introspect=False,
provide=False, local=None, no_deploy_image=False):
self.websocket.wait_for_messages.return_value = [{
"status": "SUCCESS",
"message": "Success",
"registered_nodes": [{
"uuid": "MOCK_NODE_UUID"
}],
"execution_id": "IDID"
}]
self.cmd.take_action(parsed_args)
nodes_list = copy.deepcopy(self.nodes_list)
if not no_deploy_image:
for node in nodes_list:
node.update({
'kernel_id': 'file://%s/agent.kernel' % self.http_boot,
'ramdisk_id': 'file://%s/agent.ramdisk' % self.http_boot,
})
call_count = 1
call_list = [mock.call(
'tripleo.baremetal.v1.register_or_update', workflow_input={
'nodes_json': nodes_list,
'instance_boot_option': ('local' if local is True else
'netboot' if local is False else None)
}
)]
if introspect:
call_count += 1
call_list.append(mock.call(
'tripleo.baremetal.v1.introspect', workflow_input={
'node_uuids': ['MOCK_NODE_UUID'],
'run_validations': False,
'concurrency': 20}
))
if provide:
call_count += 1
call_list.append(mock.call(
'tripleo.baremetal.v1.provide', workflow_input={
'node_uuids': ['MOCK_NODE_UUID']
}
))
self.workflow.executions.create.assert_has_calls(call_list)
self.assertEqual(self.workflow.executions.create.call_count,
call_count)
def test_import_only(self):
argslist = [self.json_file.name]
verifylist = [('introspect', False),
('provide', False)]
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
self._check_workflow_call(parsed_args)
def test_import_and_introspect(self):
argslist = [self.json_file.name, '--introspect']
verifylist = [('introspect', True),
('provide', False)]
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
self._check_workflow_call(parsed_args, introspect=True)
def test_import_and_provide(self):
argslist = [self.json_file.name, '--provide']
verifylist = [('introspect', False),
('provide', True)]
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
self._check_workflow_call(parsed_args, provide=True)
def test_import_and_introspect_and_provide(self):
argslist = [self.json_file.name, '--introspect', '--provide']
verifylist = [('introspect', True),
('provide', True)]
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
self._check_workflow_call(parsed_args, introspect=True, provide=True)
def test_import_with_netboot(self):
arglist = [self.json_file.name, '--instance-boot-option', 'netboot']
verifylist = [('instance_boot_option', 'netboot')]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self._check_workflow_call(parsed_args, local=False)
def test_import_with_no_deployed_image(self):
arglist = [self.json_file.name, '--no-deploy-image']
verifylist = [('no_deploy_image', True)]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self._check_workflow_call(parsed_args, no_deploy_image=True)
class TestImportNodeMultiArch(fakes.TestOvercloudNode):
def setUp(self):
@ -863,7 +582,7 @@ class TestImportNodeMultiArch(fakes.TestOvercloudNode):
self.websocket = client.messaging_websocket()
# Get the command object to test
self.cmd = overcloud_node.ImportNode(self.app, None)
self.cmd = overcloud_node_v2.ImportNode(self.app, None)
image = collections.namedtuple('image', ['id', 'name'])
self.app.client_manager.image = mock.Mock()
@ -894,7 +613,9 @@ class TestImportNodeMultiArch(fakes.TestOvercloudNode):
"execution_id": "IDID"
}]
self.cmd.take_action(parsed_args)
with mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True):
self.cmd.take_action(parsed_args)
nodes_list = copy.deepcopy(self.nodes_list)
if not no_deploy_image:
@ -911,14 +632,8 @@ class TestImportNodeMultiArch(fakes.TestOvercloudNode):
nodes_list[2]['ramdisk_id'] = (
'file://%s/SNB-x86_64/agent.ramdisk' % self.http_boot)
call_count = 1
call_list = [mock.call(
'tripleo.baremetal.v1.register_or_update', workflow_input={
'nodes_json': nodes_list,
'instance_boot_option': ('local' if local is True else
'netboot' if local is False else None)
}
)]
call_count = 0
call_list = []
if introspect:
call_count += 1
@ -949,13 +664,26 @@ class TestImportNodeMultiArch(fakes.TestOvercloudNode):
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
self._check_workflow_call(parsed_args)
def test_import_and_introspect(self):
argslist = [self.json_file.name, '--introspect']
verifylist = [('introspect', True),
('provide', False)]
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
self._check_workflow_call(parsed_args, introspect=True)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
def test_import_and_introspect(self, mock_playbook):
parsed_args = self.check_parser(self.cmd,
[self.json_file.name,
'--introspect'],
[('introspect', True),
('provide', False)])
self.cmd.take_action(parsed_args)
mock_playbook.assert_called_once_with(
workdir=mock.ANY,
playbook=mock.ANY,
inventory=mock.ANY,
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
extra_vars={
'node_uuids': ['MOCK_NODE_UUID'],
'run_validations': False,
'concurrency': 20
}
)
def test_import_and_provide(self):
argslist = [self.json_file.name, '--provide']
@ -965,13 +693,27 @@ class TestImportNodeMultiArch(fakes.TestOvercloudNode):
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
self._check_workflow_call(parsed_args, provide=True)
def test_import_and_introspect_and_provide(self):
argslist = [self.json_file.name, '--introspect', '--provide']
verifylist = [('introspect', True),
('provide', True)]
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
self._check_workflow_call(parsed_args, introspect=True, provide=True)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
def test_import_and_introspect_and_provide(self, mock_playbook):
parsed_args = self.check_parser(self.cmd,
[self.json_file.name,
'--introspect',
'--provide'],
[('introspect', True),
('provide', True)])
self.cmd.take_action(parsed_args)
mock_playbook.assert_called_once_with(
workdir=mock.ANY,
playbook=mock.ANY,
inventory=mock.ANY,
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
extra_vars={
'node_uuids': ['MOCK_NODE_UUID'],
'run_validations': False,
'concurrency': 20
}
)
def test_import_with_netboot(self):
arglist = [self.json_file.name, '--instance-boot-option', 'netboot']
@ -1193,12 +935,6 @@ class TestDiscoverNode(fakes.TestOvercloudNode):
)
self.gcn.start()
self.addCleanup(self.gcn.stop)
self.roun = mock.patch(
'tripleo_common.actions.baremetal.RegisterOrUpdateNodes',
autospec=True
)
self.roun.start()
self.addCleanup(self.roun.stop)
self.websocket.wait_for_messages.return_value = [{
"status": "SUCCESS",
@ -1252,11 +988,11 @@ class TestDiscoverNode(fakes.TestOvercloudNode):
workflows_calls = [
mock.call('tripleo.baremetal.v1.introspect',
workflow_input={'node_uuids': [],
workflow_input={'node_uuids': ['MOCK_NODE_UUID'],
'run_validations': True,
'concurrency': 10}),
mock.call('tripleo.baremetal.v1.provide',
workflow_input={'node_uuids': []}
workflow_input={'node_uuids': ['MOCK_NODE_UUID']}
)
]
self.workflow.executions.create.assert_has_calls(workflows_calls)

View File

@ -13,39 +13,16 @@
# under the License.
#
import mock
from osc_lib.tests import utils
from tripleoclient.tests import fakes
class FakeClientWrapper(object):
def __init__(self):
self._instance = mock.Mock()
self._mock_websocket = mock.Mock()
self._mock_websocket.__enter__ = mock.Mock(
return_value=self._mock_websocket)
# Return False to avoid silencing exceptions
self._mock_websocket.__exit__ = mock.Mock(return_value=False)
def messaging_websocket(self):
return self._mock_websocket
class TestDeleteNode(utils.TestCommand):
class TestDeleteNode(fakes.FakePlaybookExecution):
def setUp(self):
super(TestDeleteNode, self).setUp()
self.app.client_manager.auth_ref = mock.Mock(auth_token="TOKEN")
self.app.client_manager.orchestration = mock.Mock()
self.app.client_manager.tripleoclient = FakeClientWrapper()
class TestOvercloudNode(utils.TestCommand):
class TestOvercloudNode(fakes.FakePlaybookExecution):
def setUp(self):
super(TestOvercloudNode, self).setUp()
self.app.client_manager.baremetal = mock.Mock()
self.app.client_manager.workflow_engine = mock.Mock()
self.app.client_manager.tripleoclient = FakeClientWrapper()

View File

@ -297,3 +297,54 @@ class TestIntrospectNode(fakes.TestOvercloudNode):
self.assertRaises(test_utils.ParserException,
self.check_parser,
self.cmd, argslist, verifylist)
def _check_introspect_all_manageable(self, parsed_args, provide=False):
self.websocket.wait_for_messages.return_value = iter([{
"status": "SUCCESS",
"message": "Success",
"introspected_nodes": {},
"execution_id": "IDID"
}] * 2)
self.cmd.take_action(parsed_args)
call_list = [mock.call(
'tripleo.baremetal.v1.introspect_manageable_nodes',
workflow_input={'run_validations': False, 'concurrency': 20}
)]
if provide:
call_list.append(mock.call(
'tripleo.baremetal.v1.provide_manageable_nodes',
workflow_input={}
))
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_messages.return_value = [{
"status": "SUCCESS",
"message": "Success",
"execution_id": "IDID",
}]
self.cmd.take_action(parsed_args)
call_list = [mock.call(
'tripleo.baremetal.v1.introspect', workflow_input={
'node_uuids': nodes,
'run_validations': False,
'concurrency': 20}
)]
if provide:
call_list.append(mock.call(
'tripleo.baremetal.v1.provide', workflow_input={
'node_uuids': nodes}
))
self.workflow.executions.create.assert_has_calls(call_list)
self.assertEqual(self.workflow.executions.create.call_count,
2 if provide else 1)

View File

@ -14,13 +14,12 @@
import mock
from osc_lib.tests import utils
from tripleoclient import exceptions
from tripleoclient.tests import fakes
from tripleoclient.workflows import baremetal
class TestBaremetalWorkflows(utils.TestCommand):
class TestBaremetalWorkflows(fakes.FakePlaybookExecution):
def setUp(self):
super(TestBaremetalWorkflows, self).setUp()
@ -49,44 +48,11 @@ class TestBaremetalWorkflows(utils.TestCommand):
}])
def test_register_or_update_success(self):
self.websocket.wait_for_messages.return_value = self.message_success
self.assertEqual(baremetal.register_or_update(
self.app.client_manager,
nodes_json=[],
kernel_name="kernel",
ramdisk_name="ramdisk"
), [])
self.workflow.executions.create.assert_called_once_with(
'tripleo.baremetal.v1.register_or_update',
workflow_input={
'kernel_name': 'kernel',
'nodes_json': [],
'ramdisk_name': 'ramdisk'
})
def test_register_or_update_error(self):
self.websocket.wait_for_messages.return_value = self.message_failed
self.assertRaises(
exceptions.RegisterOrUpdateError,
baremetal.register_or_update,
self.app.client_manager,
nodes_json=[],
kernel_name="kernel",
ramdisk_name="ramdisk"
)
self.workflow.executions.create.assert_called_once_with(
'tripleo.baremetal.v1.register_or_update',
workflow_input={
'kernel_name': 'kernel',
'nodes_json': [],
'ramdisk_name': 'ramdisk'
})
instance_boot_option='local'
), [mock.ANY])
def test_provide_success(self):

View File

@ -13,10 +13,8 @@
# under the License.
#
import argparse
import collections
import logging
import os
import sys
from cliff.formatters import table
@ -286,148 +284,6 @@ class CleanNode(command.Command):
baremetal.provide_manageable_nodes(self.app.client_manager)
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=_('Baremetal Node 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'))
parser.add_argument('--run-validations', action='store_true',
default=False,
help=_('Run the pre-deployment validations. These '
'external validations are from the TripleO '
'Validations project.'))
parser.add_argument('--concurrency', type=int,
default=20,
help=_('Maximum number of nodes to introspect at '
'once.'))
return parser
def take_action(self, parsed_args):
self.log.debug("take_action(%s)" % parsed_args)
nodes = parsed_args.node_uuids
if nodes:
baremetal.introspect(self.app.client_manager,
node_uuids=nodes,
run_validations=parsed_args.run_validations,
concurrency=parsed_args.concurrency
)
else:
baremetal.introspect_manageable_nodes(
self.app.client_manager,
run_validations=parsed_args.run_validations,
concurrency=parsed_args.concurrency
)
if parsed_args.provide:
if nodes:
baremetal.provide(self.app.client_manager,
node_uuids=nodes,
)
else:
baremetal.provide_manageable_nodes(self.app.client_manager)
class ImportNode(command.Command):
"""Import baremetal nodes from a JSON, YAML or CSV file.
The node status will be set to 'manageable' by default.
"""
log = logging.getLogger(__name__ + ".ImportNode")
def get_parser(self, prog_name):
parser = super(ImportNode, self).get_parser(prog_name)
parser.add_argument('--introspect',
action='store_true',
help=_('Introspect the imported nodes'))
parser.add_argument('--run-validations', action='store_true',
default=False,
help=_('Run the pre-deployment validations. These '
'external validations are from the TripleO '
'Validations project.'))
parser.add_argument('--validate-only', action='store_true',
default=False,
help=_('Validate the env_file and then exit '
'without actually importing the nodes.'))
parser.add_argument('--provide',
action='store_true',
help=_('Provide (make available) the nodes'))
parser.add_argument('--no-deploy-image', action='store_true',
help=_('Skip setting the deploy kernel and '
'ramdisk.'))
parser.add_argument('--instance-boot-option',
choices=['local', 'netboot'], default=None,
help=_('Whether to set instances for booting from '
'local hard drive (local) or network '
'(netboot).'))
parser.add_argument("--http-boot",
default=os.environ.get(
'HTTP_BOOT',
constants.IRONIC_HTTP_BOOT_BIND_MOUNT),
help=_("Root directory for the ironic-python-agent"
" image"))
parser.add_argument('--concurrency', type=int,
default=20,
help=_('Maximum number of nodes to introspect at '
'once.'))
parser.add_argument('env_file', type=argparse.FileType('r'))
return parser
def take_action(self, parsed_args):
self.log.debug("take_action(%s)" % parsed_args)
nodes_config = oooutils.parse_env_file(parsed_args.env_file)
parsed_args.env_file.close()
if parsed_args.validate_only:
return baremetal.validate_nodes(self.app.client_manager,
nodes_json=nodes_config)
# Look for *specific* deploy images and update the node data if
# one is found.
if not parsed_args.no_deploy_image:
oooutils.update_nodes_deploy_data(nodes_config,
http_boot=parsed_args.http_boot)
nodes = baremetal.register_or_update(
self.app.client_manager,
nodes_json=nodes_config,
instance_boot_option=parsed_args.instance_boot_option
)
nodes_uuids = [node['uuid'] for node in nodes]
if parsed_args.introspect:
baremetal.introspect(self.app.client_manager,
node_uuids=nodes_uuids,
run_validations=parsed_args.run_validations,
concurrency=parsed_args.concurrency
)
if parsed_args.provide:
baremetal.provide(self.app.client_manager,
node_uuids=nodes_uuids,
)
class ConfigureNode(command.Command):
"""Configure Node boot options."""
@ -578,7 +434,7 @@ class DiscoverNode(command.Command):
**kwargs
)
nodes_uuids = [node['uuid'] for node in nodes]
nodes_uuids = [node.uuid for node in nodes]
if parsed_args.introspect:
baremetal.introspect(self.app.client_manager,

View File

@ -102,7 +102,7 @@ class ImportNode(command.Command):
instance_boot_option=parsed_args.instance_boot_option
)
nodes_uuids = [node['uuid'] for node in nodes]
nodes_uuids = [node.uuid for node in nodes]
if parsed_args.introspect:
extra_vars = {

View File

@ -44,34 +44,53 @@ def validate_nodes(clients, nodes_json):
raise exceptions.RegisterOrUpdateError(validated_nodes)
def register_or_update(clients, **workflow_input):
def register_or_update(clients, nodes_json, kernel_name=None,
ramdisk_name=None, instance_boot_option=None):
"""Node Registration or Update
Run the tripleo.baremetal.v1.register_or_update Mistral workflow.
:param clients: Application client object.
:type clients: Object
:param nodes_json:
:type nodes_json: Object
:param kernel_name: Kernel to use
:type kernel_name: String
:param ramdisk_name: RAMDISK to use
:type ramdisk_name: String
:param instance_boot_option: Whether to set instances for booting from
local hard drive (local) or network
(netboot).
:type instance_boot_option: String
:returns: List
"""
workflow_client = clients.workflow_engine
tripleoclients = clients.tripleoclient
context = clients.tripleoclient.create_mistral_context()
nodes = baremetal.RegisterOrUpdateNodes(
nodes_json=nodes_json,
ramdisk_name=ramdisk_name,
kernel_name=kernel_name,
instance_boot_option=instance_boot_option
)
with tripleoclients.messaging_websocket() as ws:
execution = base.start_workflow(
workflow_client,
'tripleo.baremetal.v1.register_or_update',
workflow_input=workflow_input
)
for payload in base.wait_for_messages(workflow_client, ws, execution):
if 'message' in payload:
print(payload['message'])
if payload['status'] == 'SUCCESS':
registered_nodes = payload['registered_nodes']
for nd in registered_nodes:
print('Successfully registered node UUID %s' % nd['uuid'])
return registered_nodes
registered_nodes = nodes.run(context=context)
if not isinstance(registered_nodes, list):
raise exceptions.RegisterOrUpdateError(registered_nodes)
else:
raise exceptions.RegisterOrUpdateError(
'Exception registering nodes: {}'.format(payload['message']))
for node in registered_nodes:
if node.provision_state == 'enroll':
clients.baremetal.node.set_provision_state(
node_uuid=node.uuid,
state='manage'
)
print('Successfully registered node UUID {}'.format(node.uuid))
else:
print('Node UUID {} is already registered'.format(node.uuid))
return registered_nodes
def _format_errors(payload):
@ -363,18 +382,13 @@ def discover_and_enroll(clients, ip_addresses, credentials, kernel_name,
)
print('Successfully probed node IP {}'.format(node['ip']))
register_or_update = baremetal.RegisterOrUpdateNodes(
return register_or_update(
clients=clients,
nodes_json=probed_nodes,
instance_boot_option=instance_boot_option,
kernel_name=kernel_name,
ramdisk_name=ramdisk_name
)
registered_nodes = list()
for node in register_or_update.run(context=context):
print('Successfully registered node UUID {}'.format(node['uuid']))
registered_nodes.append(node)
else:
return registered_nodes
def clean_nodes(clients, **workflow_input):

View File

@ -59,12 +59,11 @@ def deploy(log, clients, **workflow_input):
message = payload.get('message')
if message and status == "RUNNING":
print(message)
if payload['status'] != "SUCCESS":
log.info(pprint.pformat(payload))
print(payload['message'])
raise ValueError("Unexpected status %s for %s"
% (payload['status'], wf_name))
elif payload['status'] != "SUCCESS":
log.info(pprint.pformat(payload))
print(payload['message'])
raise ValueError("Unexpected status %s for %s"
% (payload['status'], wf_name))
def deploy_and_wait(log, clients, stack, plan_name, verbose_level,