Migrate the CLI introspection from Mistral to Ansible
The baremetal introspection command has been implemented in v2 using an ansible playbook instead of a mistral workflow. Story: 2007212 Task: 38444 Task: 38445 Change-Id: I61a4d1ae241bd3877abbc77bf4bad226d2502379
This commit is contained in:
parent
712d8d7a61
commit
73dfcd1b96
|
@ -71,7 +71,7 @@ openstack.tripleoclient.v2 =
|
||||||
overcloud_node_configure = tripleoclient.v1.overcloud_node:ConfigureNode
|
overcloud_node_configure = tripleoclient.v1.overcloud_node:ConfigureNode
|
||||||
overcloud_node_delete = tripleoclient.v1.overcloud_node:DeleteNode
|
overcloud_node_delete = tripleoclient.v1.overcloud_node:DeleteNode
|
||||||
overcloud_node_import = tripleoclient.v1.overcloud_node:ImportNode
|
overcloud_node_import = tripleoclient.v1.overcloud_node:ImportNode
|
||||||
overcloud_node_introspect = tripleoclient.v1.overcloud_node:IntrospectNode
|
overcloud_node_introspect = tripleoclient.v2.overcloud_node:IntrospectNode
|
||||||
overcloud_node_provide = tripleoclient.v1.overcloud_node:ProvideNode
|
overcloud_node_provide = tripleoclient.v1.overcloud_node:ProvideNode
|
||||||
overcloud_node_discover = tripleoclient.v1.overcloud_node:DiscoverNode
|
overcloud_node_discover = tripleoclient.v1.overcloud_node:DiscoverNode
|
||||||
overcloud_node_clean = tripleoclient.v1.overcloud_node:CleanNode
|
overcloud_node_clean = tripleoclient.v1.overcloud_node:CleanNode
|
||||||
|
@ -123,6 +123,7 @@ openstack.tripleoclient.v2 =
|
||||||
tripleo_validator_run = tripleoclient.v1.tripleo_validator:TripleOValidatorRun
|
tripleo_validator_run = tripleoclient.v1.tripleo_validator:TripleOValidatorRun
|
||||||
tripleo_validator_show = tripleoclient.v1.tripleo_validator:TripleOValidatorShow
|
tripleo_validator_show = tripleoclient.v1.tripleo_validator:TripleOValidatorShow
|
||||||
tripleo_validator_show_parameter = tripleoclient.v1.tripleo_validator:TripleOValidatorShowParameter
|
tripleo_validator_show_parameter = tripleoclient.v1.tripleo_validator:TripleOValidatorShowParameter
|
||||||
|
|
||||||
oslo.config.opts =
|
oslo.config.opts =
|
||||||
undercloud_config = tripleoclient.config.undercloud:list_opts
|
undercloud_config = tripleoclient.config.undercloud:list_opts
|
||||||
standalone_config = tripleoclient.config.standalone:list_opts
|
standalone_config = tripleoclient.config.standalone:list_opts
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
# Copyright 2015 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
import mock
|
||||||
|
from osc_lib.tests import utils
|
||||||
|
|
||||||
|
|
||||||
|
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):
|
||||||
|
|
||||||
|
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):
|
||||||
|
|
||||||
|
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()
|
|
@ -0,0 +1,149 @@
|
||||||
|
# Copyright 2015 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from osc_lib.tests import utils as test_utils
|
||||||
|
|
||||||
|
from tripleoclient import constants
|
||||||
|
from tripleoclient.tests.v2.overcloud_node import fakes
|
||||||
|
from tripleoclient.v2 import overcloud_node
|
||||||
|
|
||||||
|
|
||||||
|
class TestIntrospectNode(fakes.TestOvercloudNode):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestIntrospectNode, self).setUp()
|
||||||
|
|
||||||
|
# Get the command object to test
|
||||||
|
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()
|
||||||
|
self.websocket.wait_for_messages.return_value = iter([{
|
||||||
|
"status": "SUCCESS",
|
||||||
|
"message": "Success",
|
||||||
|
"introspected_nodes": {},
|
||||||
|
"execution_id": execution.id
|
||||||
|
}] * 2)
|
||||||
|
|
||||||
|
# Get the command object to test
|
||||||
|
self.cmd = overcloud_node.IntrospectNode(self.app, None)
|
||||||
|
|
||||||
|
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
||||||
|
autospec=True)
|
||||||
|
def test_introspect_all_manageable_nodes_without_provide(self,
|
||||||
|
mock_playbook):
|
||||||
|
parsed_args = self.check_parser(self.cmd,
|
||||||
|
['--all-manageable'],
|
||||||
|
[('all_manageable', 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': [],
|
||||||
|
'run_validations': False,
|
||||||
|
'concurrency': 20,
|
||||||
|
'all_manageable': True
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
||||||
|
autospec=True)
|
||||||
|
def test_introspect_all_manageable_nodes_with_provide(self,
|
||||||
|
mock_playbook):
|
||||||
|
parsed_args = self.check_parser(self.cmd,
|
||||||
|
['--all-manageable', '--provide'],
|
||||||
|
[('all_manageable', True),
|
||||||
|
('provide', True)])
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
mock_playbook.assert_called_once_with(
|
||||||
|
workdir=mock.ANY,
|
||||||
|
playbook='cli-baremetal-introspect.yaml',
|
||||||
|
inventory=mock.ANY,
|
||||||
|
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||||
|
extra_vars={
|
||||||
|
'node_uuids': [],
|
||||||
|
'run_validations': False,
|
||||||
|
'concurrency': 20,
|
||||||
|
'all_manageable': True
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
||||||
|
autospec=True)
|
||||||
|
def test_introspect_nodes_without_provide(self, mock_playbook):
|
||||||
|
nodes = ['node_uuid1', 'node_uuid2']
|
||||||
|
parsed_args = self.check_parser(self.cmd,
|
||||||
|
nodes,
|
||||||
|
[('node_uuids', nodes)])
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
mock_playbook.assert_called_once_with(
|
||||||
|
workdir=mock.ANY,
|
||||||
|
playbook='cli-baremetal-introspect.yaml',
|
||||||
|
inventory=mock.ANY,
|
||||||
|
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||||
|
extra_vars={
|
||||||
|
'node_uuids': nodes,
|
||||||
|
'run_validations': False,
|
||||||
|
'concurrency': 20,
|
||||||
|
'all_manageable': False
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
||||||
|
autospec=True)
|
||||||
|
def test_introspect_nodes_with_provide(self, mock_playbook):
|
||||||
|
nodes = ['node_uuid1', 'node_uuid2']
|
||||||
|
argslist = nodes + ['--provide']
|
||||||
|
parsed_args = self.check_parser(self.cmd,
|
||||||
|
argslist,
|
||||||
|
[('node_uuids', nodes),
|
||||||
|
('provide', True)])
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
mock_playbook.assert_called_once_with(
|
||||||
|
workdir=mock.ANY,
|
||||||
|
playbook='cli-baremetal-introspect.yaml',
|
||||||
|
inventory=mock.ANY,
|
||||||
|
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||||
|
extra_vars={
|
||||||
|
'node_uuids': nodes,
|
||||||
|
'run_validations': False,
|
||||||
|
'concurrency': 20,
|
||||||
|
'all_manageable': False
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
||||||
|
autospec=True)
|
||||||
|
def test_introspect_no_node_or_flag_specified(self, mock_playbook):
|
||||||
|
self.assertRaises(test_utils.ParserException,
|
||||||
|
self.check_parser,
|
||||||
|
self.cmd, [], [])
|
||||||
|
|
||||||
|
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
||||||
|
autospec=True)
|
||||||
|
def test_introspect_uuids_and_all_both_specified(self, mock_playbook):
|
||||||
|
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)
|
|
@ -0,0 +1,98 @@
|
||||||
|
# Copyright 2015 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from osc_lib.i18n import _
|
||||||
|
|
||||||
|
from tripleoclient import command
|
||||||
|
from tripleoclient import constants
|
||||||
|
from tripleoclient import utils as oooutils
|
||||||
|
from tripleoclient.workflows import baremetal
|
||||||
|
|
||||||
|
# NOTE(cloudnull): V1 imports, These classes will be removed as they're
|
||||||
|
# converted from mistral to ansible.
|
||||||
|
from tripleoclient.v1.overcloud_node import CleanNode # noqa
|
||||||
|
from tripleoclient.v1.overcloud_node import ConfigureNode # noqa
|
||||||
|
from tripleoclient.v1.overcloud_node import DeleteNode # noqa
|
||||||
|
from tripleoclient.v1.overcloud_node import DiscoverNode # noqa
|
||||||
|
from tripleoclient.v1.overcloud_node import ImportNode # noqa
|
||||||
|
from tripleoclient.v1.overcloud_node import ProvideNode # noqa
|
||||||
|
from tripleoclient.v1.overcloud_node import ProvisionNode # noqa
|
||||||
|
from tripleoclient.v1.overcloud_node import UnprovisionNode # noqa
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
extra_vars = {
|
||||||
|
"node_uuids": parsed_args.node_uuids,
|
||||||
|
"run_validations": parsed_args.run_validations,
|
||||||
|
"concurrency": parsed_args.concurrency,
|
||||||
|
"all_manageable": parsed_args.all_manageable,
|
||||||
|
}
|
||||||
|
|
||||||
|
with oooutils.TempDirs() as tmp:
|
||||||
|
oooutils.run_ansible_playbook(
|
||||||
|
playbook='cli-baremetal-introspect.yaml',
|
||||||
|
inventory='localhost,',
|
||||||
|
workdir=tmp,
|
||||||
|
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||||
|
extra_vars=extra_vars
|
||||||
|
)
|
||||||
|
|
||||||
|
# NOTE(cloudnull): This is using the old provide function, in a future
|
||||||
|
# release this may be ported to a standalone playbook
|
||||||
|
if parsed_args.provide:
|
||||||
|
if parsed_args.node_uuids:
|
||||||
|
baremetal.provide(
|
||||||
|
self.app.client_manager,
|
||||||
|
node_uuids=parsed_args.node_uuids,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
baremetal.provide_manageable_nodes(self.app.client_manager)
|
Loading…
Reference in New Issue