Files
python-tripleoclient/tripleoclient/tests/v2/overcloud_node/test_overcloud_node.py
Kevin Carter 7c40575d7b Update client to create archive and use tripleo-common
The client utils will now run a new playbook to ensure that the local
archive directory is created early in the deployment process. This
change will allow us to build toward a swift-less deployment. All of
the client calls, save one, has been moved to use tripleo-common which
will assist us to better manage, and migrate from swift storage to a
local archive.

> As a product of this change all of the "webhook" calls have been
  removed. which was deprecated as part of the Zaqar and Mistral work.
  These calls were removed because several swift calls were tied into
  them, and because mistral is no longer part of the stack, and has
  been gone for a few cycles, we can safely remove these calls which
  do nothing.

Depends-On: Ibe9b2ffe94cdf493fc84366979d1d78b8528ea1b
Change-Id: I7531612a49527f8a21df415c648acb41ac7a0b10
Signed-off-by: Kevin Carter <kecarter@redhat.com>
2021-01-20 09:43:52 -06:00

430 lines
17 KiB
Python

# 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 collections
import fixtures
import json
import mock
import os
import tempfile
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 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)
# 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')]))
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
def test_import_only(self, mock_playbook):
parsed_args = self.check_parser(self.cmd,
[self.json_file.name],
[('introspect', False),
('provide', False)])
self.cmd.take_action(parsed_args)
@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,
verbosity=mock.ANY,
extra_vars={
'node_uuids': ['MOCK_NODE_UUID'],
'run_validations': False,
'concurrency': 20
}
)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
def test_import_and_provide(self, mock_playbook):
parsed_args = self.check_parser(self.cmd,
[self.json_file.name,
'--provide'],
[('introspect', False),
('provide', True)])
self.cmd.take_action(parsed_args)
@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_with(
workdir=mock.ANY,
playbook=mock.ANY,
inventory=mock.ANY,
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=mock.ANY,
extra_vars={
'node_uuids': ['MOCK_NODE_UUID']
}
)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
def test_import_with_netboot(self, mock_playbook):
parsed_args = self.check_parser(self.cmd,
[self.json_file.name,
'--no-deploy-image'],
[('no_deploy_image', True)])
self.cmd.take_action(parsed_args)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
def test_import_with_no_deployed_image(self, mock_playbook):
parsed_args = self.check_parser(self.cmd,
[self.json_file.name,
'--instance-boot-option',
'netboot'],
[('instance_boot_option', 'netboot')])
self.cmd.take_action(parsed_args)
class TestIntrospectNode(fakes.TestOvercloudNode):
def setUp(self):
super(TestIntrospectNode, self).setUp()
# 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,
verbosity=mock.ANY,
extra_vars={
'node_uuids': [],
'run_validations': False,
'concurrency': 20,
'node_timeout': 1200,
'max_retries': 1,
'retry_timeout': 120,
}
)
@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_with(
workdir=mock.ANY,
playbook='cli-overcloud-node-provide.yaml',
inventory=mock.ANY,
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=mock.ANY,
extra_vars={
'node_uuids': []
}
)
@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,
verbosity=mock.ANY,
extra_vars={
'node_uuids': nodes,
'run_validations': False,
'concurrency': 20,
'node_timeout': 1200,
'max_retries': 1,
'retry_timeout': 120,
}
)
@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_with(
workdir=mock.ANY,
playbook='cli-overcloud-node-provide.yaml',
inventory=mock.ANY,
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
verbosity=mock.ANY,
extra_vars={
'node_uuids': nodes
}
)
@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)
def _check_introspect_all_manageable(self, parsed_args, provide=False):
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.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)
class TestProvisionNode(fakes.TestOvercloudNode):
def setUp(self):
super(TestProvisionNode, self).setUp()
self.cmd = overcloud_node.ProvisionNode(self.app, None)
self.cmd.app_args = mock.Mock(verbose_level=1)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
def test_ok(self, mock_playbook):
with tempfile.NamedTemporaryFile() as inp:
with tempfile.NamedTemporaryFile() as outp:
with tempfile.NamedTemporaryFile() as keyf:
inp.write(b'- name: Compute\n- name: Controller\n')
inp.flush()
keyf.write(b'I am a key')
keyf.flush()
with open('{}.pub'.format(keyf.name), 'w') as f:
f.write('I am a key')
argslist = ['--output', outp.name,
'--overcloud-ssh-key', keyf.name,
inp.name]
verifylist = [('input', inp.name),
('output', outp.name),
('overcloud_ssh_key', keyf.name)]
parsed_args = self.check_parser(self.cmd,
argslist, verifylist)
self.cmd.take_action(parsed_args)
mock_playbook.assert_called_once_with(
extra_vars={
'stack_name': 'overcloud',
'baremetal_deployment': [
{'name': 'Compute'},
{'name': 'Controller'}
],
'baremetal_deployed_path': mock.ANY,
'ssh_public_keys': 'I am a key',
'ssh_user_name': 'heat-admin',
'node_timeout': 3600,
'concurrency': 20,
'manage_network_ports': False,
},
inventory='localhost,',
playbook='cli-overcloud-node-provision.yaml',
playbook_dir='/usr/share/ansible/tripleo-playbooks',
verbosity=mock.ANY,
workdir=mock.ANY
)
class TestUnprovisionNode(fakes.TestOvercloudNode):
def setUp(self):
super(TestUnprovisionNode, self).setUp()
self.cmd = overcloud_node.UnprovisionNode(self.app, None)
self.cmd.app_args = mock.Mock(verbose_level=1)
@mock.patch('tripleoclient.utils.run_ansible_playbook',
autospec=True)
@mock.patch('tripleoclient.utils.tempfile')
@mock.patch('tripleoclient.utils.prompt_user_for_confirmation')
def test_ok(self, mock_prompt, mock_tempfile, mock_playbook):
tmp = tempfile.mkdtemp()
mock_tempfile.mkdtemp.return_value = tmp
mock_prompt.return_value = True
unprovision_confirm = os.path.join(tmp, 'unprovision_confirm.json')
with open(unprovision_confirm, 'w') as confirm:
confirm.write(json.dumps([
{'hostname': 'compute-0', 'name': 'baremetal-1'},
{'hostname': 'controller-0', 'name': 'baremetal-2'}
]))
with tempfile.NamedTemporaryFile() as inp:
inp.write(b'- name: Compute\n- name: Controller\n')
inp.flush()
argslist = ['--all', inp.name]
verifylist = [('input', inp.name), ('all', True)]
parsed_args = self.check_parser(self.cmd,
argslist, verifylist)
self.cmd.take_action(parsed_args)
mock_playbook.assert_has_calls([
mock.call(
extra_vars={
'stack_name': 'overcloud',
'baremetal_deployment': [
{'name': 'Compute'},
{'name': 'Controller'}
],
'all': True,
'prompt': True,
'unprovision_confirm': unprovision_confirm,
'manage_network_ports': False,
},
inventory='localhost,',
playbook='cli-overcloud-node-unprovision.yaml',
playbook_dir='/usr/share/ansible/tripleo-playbooks',
verbosity=mock.ANY,
workdir=tmp
),
mock.call(
extra_vars={
'stack_name': 'overcloud',
'baremetal_deployment': [
{'name': 'Compute'},
{'name': 'Controller'}
],
'all': True,
'prompt': False,
'manage_network_ports': False,
},
inventory='localhost,',
playbook='cli-overcloud-node-unprovision.yaml',
playbook_dir='/usr/share/ansible/tripleo-playbooks',
verbosity=mock.ANY,
workdir=tmp
)
])