Fix misused ansible connection timeout and deployment timeout passed in config download and ansible runner utility. Allow ansible runner utility to be given a job_timeout as well. Also fix the misuse of timeout parameters in related worklows. Add --overcloud-ssh-port-timeout and use it to configure ansible connection timeout for the DeleteNode interace of the involved workflows. Then use the timeout parameter as real timeout instead of mistakingly passing it as a connection timeout. Add new unit test for ansible timeout in config_download. Add missing coverage for the existing timeout-related params in other unit tests. Closes-Bug: #1868063 Co-authored-by: Kevin Carter <kevin@cloudnull.com> Change-Id: I2a4d151bcb83074af5bcf7d1b8c68d81d3c0400d Signed-off-by: Bogdan Dobrelya <bdobreli@redhat.com>
751 lines
28 KiB
Python
751 lines
28 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 copy
|
|
import fixtures
|
|
import json
|
|
import mock
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
|
|
from osc_lib import exceptions as oscexc
|
|
from osc_lib.tests import utils as test_utils
|
|
import yaml
|
|
|
|
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):
|
|
|
|
def setUp(self):
|
|
super(TestDeleteNode, self).setUp()
|
|
|
|
# Get the command object to test
|
|
self.cmd = overcloud_node.DeleteNode(self.app, None)
|
|
self.cmd.app_args = mock.Mock(verbose_level=1)
|
|
self.app.client_manager.workflow_engine = mock.Mock()
|
|
self.tripleoclient = mock.Mock()
|
|
|
|
self.websocket = mock.Mock()
|
|
self.websocket.__enter__ = lambda s: self.websocket
|
|
self.websocket.__exit__ = lambda s, *exc: None
|
|
self.tripleoclient.messaging_websocket.return_value = self.websocket
|
|
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(
|
|
stack_name="overcloud"
|
|
)
|
|
stack.output_show.return_value = {'output': {'output_value': []}}
|
|
execution = mock.Mock()
|
|
execution.id = "IDID"
|
|
self.workflow.executions.create.return_value = execution
|
|
|
|
delete_node = mock.patch(
|
|
'tripleo_common.actions.scale.ScaleDownAction.run',
|
|
autospec=True
|
|
)
|
|
delete_node.start()
|
|
delete_node.return_value = None
|
|
self.addCleanup(delete_node.stop)
|
|
|
|
wait_stack = mock.patch(
|
|
'tripleoclient.utils.wait_for_stack_ready',
|
|
autospec=True
|
|
)
|
|
wait_stack.start()
|
|
wait_stack.return_value = None
|
|
self.addCleanup(wait_stack.stop)
|
|
self.app.client_manager.compute.servers.get.return_value = None
|
|
|
|
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
|
autospec=True)
|
|
def test_node_delete(self, mock_playbook):
|
|
argslist = ['instance1', 'instance2', '--templates',
|
|
'--stack', 'overcast', '--timeout', '90', '--yes']
|
|
verifylist = [
|
|
('stack', 'overcast'),
|
|
('nodes', ['instance1', 'instance2'])
|
|
]
|
|
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
|
self.cmd.take_action(parsed_args)
|
|
|
|
@mock.patch('tripleoclient.utils.prompt_user_for_confirmation',
|
|
return_value=False)
|
|
def test_node_delete_no_confirm(self, confirm_mock):
|
|
argslist = ['instance1', 'instance2', '--templates',
|
|
'--stack', 'overcast', '--timeout', '90']
|
|
verifylist = [
|
|
('stack', 'overcast'),
|
|
('nodes', ['instance1', 'instance2'])
|
|
]
|
|
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
|
|
|
self.assertRaises(oscexc.CommandError,
|
|
self.cmd.take_action,
|
|
parsed_args)
|
|
|
|
@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', ])
|
|
]
|
|
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)
|
|
|
|
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
|
autospec=True)
|
|
def test_node_delete_without_stack(self, mock_playbook):
|
|
arglist = ['instance1', '--yes']
|
|
|
|
verifylist = [
|
|
('stack', 'overcloud'),
|
|
('nodes', ['instance1']),
|
|
]
|
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
self.cmd.take_action(parsed_args)
|
|
|
|
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
|
autospec=True)
|
|
@mock.patch('tripleoclient.utils.tempfile')
|
|
def test_node_delete_baremetal_deployment(self,
|
|
mock_tempfile,
|
|
mock_playbook):
|
|
|
|
bm_yaml = [{
|
|
'name': 'Compute',
|
|
'count': 5,
|
|
'instances': [{
|
|
'name': 'baremetal-2',
|
|
'hostname': 'overcast-compute-0',
|
|
'provisioned': False
|
|
}],
|
|
}, {
|
|
'name': 'Controller',
|
|
'count': 2,
|
|
'instances': [{
|
|
'name': 'baremetal-1',
|
|
'hostname': 'overcast-controller-1',
|
|
'provisioned': False
|
|
}]
|
|
}]
|
|
|
|
tmp = tempfile.mkdtemp()
|
|
mock_tempfile.mkdtemp.side_effect = [
|
|
tmp,
|
|
tempfile.mkdtemp(),
|
|
tempfile.mkdtemp(),
|
|
tempfile.mkdtemp()
|
|
]
|
|
|
|
unprovision_confirm = os.path.join(tmp, 'unprovision_confirm.json')
|
|
with open(unprovision_confirm, 'w') as confirm:
|
|
confirm.write(json.dumps([
|
|
{
|
|
'hostname': 'overcast-controller-1',
|
|
'name': 'baremetal-1',
|
|
'id': 'aaaa'
|
|
}, {
|
|
'hostname': 'overcast-compute-0',
|
|
'name': 'baremetal-2',
|
|
'id': 'bbbb'
|
|
}
|
|
]))
|
|
|
|
with tempfile.NamedTemporaryFile(mode='w') as inp:
|
|
yaml.dump(bm_yaml, inp, encoding='utf-8')
|
|
inp.flush()
|
|
|
|
argslist = ['--baremetal-deployment', inp.name, '--templates',
|
|
'--stack', 'overcast', '--overcloud-ssh-port-timeout',
|
|
'42', '--timeout', '90', '--yes']
|
|
verifylist = [
|
|
('stack', 'overcast'),
|
|
('overcloud_ssh_port_timeout', 42),
|
|
('baremetal_deployment', inp.name)
|
|
]
|
|
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
|
|
|
self.cmd.take_action(parsed_args)
|
|
|
|
# Verify
|
|
mock_playbook.assert_has_calls([
|
|
mock.call(
|
|
playbook='cli-overcloud-node-unprovision.yaml',
|
|
inventory='localhost,',
|
|
verbosity=mock.ANY,
|
|
workdir=mock.ANY,
|
|
playbook_dir='/usr/share/ansible/tripleo-playbooks',
|
|
extra_vars={
|
|
'stack_name': 'overcast',
|
|
'baremetal_deployment': [{
|
|
'count': 5,
|
|
'instances': [{
|
|
'hostname': 'overcast-compute-0',
|
|
'name': 'baremetal-2',
|
|
'provisioned': False
|
|
}],
|
|
'name': 'Compute'
|
|
}, {
|
|
'count': 2,
|
|
'instances': [{
|
|
'hostname': 'overcast-controller-1',
|
|
'name': 'baremetal-1',
|
|
'provisioned': False
|
|
}], 'name': 'Controller'
|
|
}],
|
|
'prompt': True,
|
|
'unprovision_confirm': unprovision_confirm,
|
|
},
|
|
),
|
|
mock.call(
|
|
playbook='cli-grant-local-access.yaml',
|
|
inventory='localhost,',
|
|
workdir=mock.ANY,
|
|
playbook_dir='/usr/share/ansible/tripleo-playbooks',
|
|
verbosity=mock.ANY,
|
|
extra_vars={
|
|
'access_path': '/var/lib/mistral',
|
|
'execution_user': mock.ANY},
|
|
),
|
|
mock.call(
|
|
playbook=mock.ANY,
|
|
inventory=mock.ANY,
|
|
workdir=mock.ANY,
|
|
playbook_dir=mock.ANY,
|
|
skip_tags='opendev-validation',
|
|
ansible_cfg=None,
|
|
verbosity=mock.ANY,
|
|
ssh_user='tripleo-admin',
|
|
key=mock.ANY,
|
|
limit_hosts='overcast-controller-1:overcast-compute-0',
|
|
ansible_timeout=42,
|
|
reproduce_command=True,
|
|
extra_env_variables={'ANSIBLE_BECOME': True},
|
|
extra_vars=None,
|
|
tags=None,
|
|
timeout=90
|
|
),
|
|
mock.call(
|
|
inventory='localhost,',
|
|
playbook='cli-overcloud-node-unprovision.yaml',
|
|
verbosity=mock.ANY,
|
|
workdir=mock.ANY,
|
|
playbook_dir='/usr/share/ansible/tripleo-playbooks',
|
|
extra_vars={
|
|
'stack_name': 'overcast',
|
|
'baremetal_deployment': [{
|
|
'count': 5,
|
|
'instances': [{
|
|
'hostname': 'overcast-compute-0',
|
|
'name': 'baremetal-2',
|
|
'provisioned': False
|
|
}], 'name': 'Compute'
|
|
}, {
|
|
'count': 2,
|
|
'instances': [{
|
|
'hostname': 'overcast-controller-1',
|
|
'name': 'baremetal-1',
|
|
'provisioned': False
|
|
}],
|
|
'name': 'Controller'
|
|
}],
|
|
'prompt': False
|
|
},
|
|
)
|
|
])
|
|
|
|
@mock.patch('tripleoclient.utils.run_ansible_playbook',
|
|
autospec=True)
|
|
@mock.patch('tripleoclient.utils.tempfile')
|
|
def test_nodes_to_delete(self, mock_tempfile, mock_playbook):
|
|
bm_yaml = [{
|
|
'name': 'Compute',
|
|
'count': 5,
|
|
'instances': [{
|
|
'name': 'baremetal-2',
|
|
'hostname': 'overcast-compute-0',
|
|
'provisioned': False
|
|
}],
|
|
}, {
|
|
'name': 'Controller',
|
|
'count': 2,
|
|
'instances': [{
|
|
'name': 'baremetal-1',
|
|
'hostname': 'overcast-controller-1',
|
|
'provisioned': False
|
|
}]
|
|
}]
|
|
|
|
tmp = tempfile.mkdtemp()
|
|
mock_tempfile.mkdtemp.return_value = tmp
|
|
|
|
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',
|
|
'id': 'aaaa'
|
|
}, {
|
|
'hostname': 'controller-0',
|
|
'name': 'baremetal-2',
|
|
'id': 'bbbb'
|
|
}
|
|
]))
|
|
|
|
argslist = ['--baremetal-deployment', '/foo/bm_deploy.yaml']
|
|
verifylist = [
|
|
('baremetal_deployment', '/foo/bm_deploy.yaml')
|
|
]
|
|
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
|
nodes_text, nodes = self.cmd._nodes_to_delete(parsed_args, bm_yaml)
|
|
expected = '''+--------------+-------------+------+
|
|
| hostname | name | id |
|
|
+--------------+-------------+------+
|
|
| compute-0 | baremetal-1 | aaaa |
|
|
| controller-0 | baremetal-2 | bbbb |
|
|
+--------------+-------------+------+
|
|
'''
|
|
self.assertEqual(expected, nodes_text)
|
|
self.assertEqual(['compute-0', 'controller-0'], nodes)
|
|
|
|
|
|
class TestProvideNode(fakes.TestOvercloudNode):
|
|
|
|
def setUp(self):
|
|
super(TestProvideNode, self).setUp()
|
|
|
|
# Get the command object to test
|
|
self.cmd = overcloud_node.ProvideNode(self.app, None)
|
|
|
|
def test_provide_all_manageable_nodes(self):
|
|
|
|
parsed_args = self.check_parser(self.cmd,
|
|
['--all-manageable'],
|
|
[('all_manageable', True)])
|
|
self.cmd.take_action(parsed_args)
|
|
|
|
def test_provide_one_node(self):
|
|
node_id = 'node_uuid1'
|
|
|
|
parsed_args = self.check_parser(self.cmd,
|
|
[node_id],
|
|
[('node_uuids', [node_id])])
|
|
self.cmd.take_action(parsed_args)
|
|
|
|
def test_provide_multiple_nodes(self):
|
|
node_id1 = 'node_uuid1'
|
|
node_id2 = 'node_uuid2'
|
|
|
|
argslist = [node_id1, node_id2]
|
|
verifylist = [('node_uuids', [node_id1, node_id2])]
|
|
|
|
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
|
self.cmd.take_action(parsed_args)
|
|
|
|
|
|
class TestCleanNode(fakes.TestOvercloudNode):
|
|
|
|
def setUp(self):
|
|
super(TestCleanNode, 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.CleanNode(self.app, None)
|
|
|
|
def _check_clean_all_manageable(self, parsed_args, provide=False):
|
|
self.cmd.take_action(parsed_args)
|
|
|
|
def _check_clean_nodes(self, parsed_args, nodes, provide=False):
|
|
self.cmd.take_action(parsed_args)
|
|
|
|
def test_clean_all_manageable_nodes_without_provide(self):
|
|
parsed_args = self.check_parser(self.cmd,
|
|
['--all-manageable'],
|
|
[('all_manageable', True)])
|
|
self._check_clean_all_manageable(parsed_args, provide=False)
|
|
|
|
def test_clean_all_manageable_nodes_with_provide(self):
|
|
parsed_args = self.check_parser(self.cmd,
|
|
['--all-manageable', '--provide'],
|
|
[('all_manageable', True),
|
|
('provide', True)])
|
|
self._check_clean_all_manageable(parsed_args, provide=True)
|
|
|
|
def test_clean_nodes_without_provide(self):
|
|
nodes = ['node_uuid1', 'node_uuid2']
|
|
parsed_args = self.check_parser(self.cmd,
|
|
nodes,
|
|
[('node_uuids', nodes)])
|
|
self._check_clean_nodes(parsed_args, nodes, provide=False)
|
|
|
|
def test_clean_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_clean_nodes(parsed_args, nodes, provide=True)
|
|
|
|
|
|
class TestImportNodeMultiArch(fakes.TestOvercloudNode):
|
|
|
|
def setUp(self):
|
|
super(TestImportNodeMultiArch, 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",
|
|
"arch": "x86_64",
|
|
"mac": [
|
|
"00:0b:d0:69:7e:58"
|
|
]
|
|
}, {
|
|
"pm_user": "stack",
|
|
"pm_addr": "192.168.122.3",
|
|
"pm_password": "KEY3",
|
|
"pm_type": "pxe_ssh",
|
|
"arch": "x86_64",
|
|
"platform": "SNB",
|
|
"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_v2.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'),
|
|
image(id=6, name='x86_64-overcloud-full'),
|
|
image(id=9, name='SNB-x86_64-overcloud-full'),
|
|
]
|
|
|
|
self.http_boot = '/var/lib/ironic/httpboot'
|
|
|
|
self.mock_playbook = mock.patch(
|
|
"tripleoclient.utils.run_ansible_playbook", spec=True)
|
|
self.mock_run_ansible_playbook = self.mock_playbook.start()
|
|
self.addCleanup(self.mock_playbook.stop)
|
|
|
|
existing = ['agent', 'x86_64/agent', 'SNB-x86_64/agent']
|
|
existing = {os.path.join(self.http_boot, name + ext)
|
|
for name in existing for ext in ('.kernel', '.ramdisk')}
|
|
|
|
self.useFixture(fixtures.MockPatch(
|
|
'os.path.exists', autospec=True,
|
|
side_effect=lambda path: path in existing))
|
|
|
|
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"
|
|
}]
|
|
|
|
file_return_nodes = [
|
|
{
|
|
'uuid': 'MOCK_NODE_UUID'
|
|
}
|
|
]
|
|
mock_open = mock.mock_open(read_data=json.dumps(file_return_nodes))
|
|
# TODO(cloudnull): Remove this when py27 is dropped
|
|
if sys.version_info >= (3, 0):
|
|
mock_open_path = 'builtins.open'
|
|
else:
|
|
mock_open_path = 'tripleoclient.v1.overcloud_node.open'
|
|
with mock.patch(mock_open_path, mock_open):
|
|
self.cmd.take_action(parsed_args)
|
|
|
|
nodes_list = copy.deepcopy(self.nodes_list)
|
|
if not no_deploy_image:
|
|
nodes_list[0]['kernel_id'] = (
|
|
'file://%s/agent.kernel' % self.http_boot)
|
|
nodes_list[0]['ramdisk_id'] = (
|
|
'file://%s/agent.ramdisk' % self.http_boot)
|
|
nodes_list[1]['kernel_id'] = (
|
|
'file://%s/x86_64/agent.kernel' % self.http_boot)
|
|
nodes_list[1]['ramdisk_id'] = (
|
|
'file://%s/x86_64/agent.ramdisk' % self.http_boot)
|
|
nodes_list[2]['kernel_id'] = (
|
|
'file://%s/SNB-x86_64/agent.kernel' % self.http_boot)
|
|
nodes_list[2]['ramdisk_id'] = (
|
|
'file://%s/SNB-x86_64/agent.ramdisk' % self.http_boot)
|
|
|
|
if introspect:
|
|
self.mock_run_ansible_playbook.assert_called_with(
|
|
extra_vars={
|
|
'node_uuids': ['MOCK_NODE_UUID']},
|
|
inventory='localhost,',
|
|
playbook='cli-overcloud-node-provide.yaml',
|
|
playbook_dir='/usr/share/ansible/tripleo-playbooks',
|
|
workdir=mock.ANY,
|
|
)
|
|
|
|
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_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 TestConfigureNode(fakes.TestOvercloudNode):
|
|
|
|
def setUp(self):
|
|
super(TestConfigureNode, 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()
|
|
self.websocket.wait_for_messages.return_value = iter([{
|
|
"status": "SUCCESS",
|
|
"message": "",
|
|
"execution_id": "IDID"
|
|
}])
|
|
|
|
# Get the command object to test
|
|
self.cmd = overcloud_node.ConfigureNode(self.app, None)
|
|
|
|
self.http_boot = '/var/lib/ironic/httpboot'
|
|
|
|
self.workflow_input = {
|
|
'kernel_name': 'file://%s/agent.kernel' % self.http_boot,
|
|
'ramdisk_name': 'file://%s/agent.ramdisk' % self.http_boot,
|
|
'instance_boot_option': None,
|
|
'root_device': None,
|
|
'root_device_minimum_size': 4,
|
|
'overwrite_root_device_hints': False
|
|
}
|
|
|
|
def test_configure_all_manageable_nodes(self):
|
|
parsed_args = self.check_parser(self.cmd,
|
|
['--all-manageable'],
|
|
[('all_manageable', True)])
|
|
self.cmd.take_action(parsed_args)
|
|
|
|
def test_configure_specified_nodes(self):
|
|
argslist = ['node_uuid1', 'node_uuid2']
|
|
verifylist = [('node_uuids', ['node_uuid1', 'node_uuid2'])]
|
|
|
|
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
|
self.cmd.take_action(parsed_args)
|
|
|
|
def test_configure_no_node_or_flag_specified(self):
|
|
self.assertRaises(test_utils.ParserException,
|
|
self.check_parser,
|
|
self.cmd, [], [])
|
|
|
|
def test_configure_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)
|
|
|
|
def test_configure_kernel_and_ram(self):
|
|
argslist = ['--all-manageable', '--deploy-ramdisk', 'test_ramdisk',
|
|
'--deploy-kernel', 'test_kernel']
|
|
verifylist = [('deploy_kernel', 'test_kernel'),
|
|
('deploy_ramdisk', 'test_ramdisk')]
|
|
|
|
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
|
self.cmd.take_action(parsed_args)
|
|
|
|
def test_configure_instance_boot_option(self):
|
|
argslist = ['--all-manageable', '--instance-boot-option', 'netboot']
|
|
verifylist = [('instance_boot_option', 'netboot')]
|
|
|
|
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
|
self.cmd.take_action(parsed_args)
|
|
|
|
def test_configure_root_device(self):
|
|
argslist = ['--all-manageable',
|
|
'--root-device', 'smallest',
|
|
'--root-device-minimum-size', '2',
|
|
'--overwrite-root-device-hints']
|
|
verifylist = [('root_device', 'smallest'),
|
|
('root_device_minimum_size', 2),
|
|
('overwrite_root_device_hints', True)]
|
|
|
|
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
|
self.cmd.take_action(parsed_args)
|
|
|
|
def test_configure_specified_node_with_all_arguments(self):
|
|
argslist = ['node_id',
|
|
'--deploy-kernel', 'test_kernel',
|
|
'--deploy-ramdisk', 'test_ramdisk',
|
|
'--instance-boot-option', 'netboot',
|
|
'--root-device', 'smallest',
|
|
'--root-device-minimum-size', '2',
|
|
'--overwrite-root-device-hints']
|
|
verifylist = [('node_uuids', ['node_id']),
|
|
('deploy_kernel', 'test_kernel'),
|
|
('deploy_ramdisk', 'test_ramdisk'),
|
|
('instance_boot_option', 'netboot'),
|
|
('root_device', 'smallest'),
|
|
('root_device_minimum_size', 2),
|
|
('overwrite_root_device_hints', True)]
|
|
|
|
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
|
self.cmd.take_action(parsed_args)
|
|
|
|
|
|
class TestDiscoverNode(fakes.TestOvercloudNode):
|
|
|
|
def setUp(self):
|
|
super(TestDiscoverNode, 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
|
|
client.create_mistral_context = plugin.ClientWrapper(
|
|
instance=ooofakes.FakeInstanceData
|
|
).create_mistral_context
|
|
self.websocket = client.messaging_websocket()
|
|
|
|
self.cmd = overcloud_node.DiscoverNode(self.app, None)
|
|
|
|
self.gcn = mock.patch(
|
|
'tripleo_common.actions.baremetal.GetCandidateNodes',
|
|
autospec=True
|
|
)
|
|
self.gcn.start()
|
|
self.addCleanup(self.gcn.stop)
|
|
|
|
self.websocket.wait_for_messages.return_value = [{
|
|
"status": "SUCCESS",
|
|
"message": "Success",
|
|
"registered_nodes": [{
|
|
"uuid": "MOCK_NODE_UUID"
|
|
}],
|
|
"execution_id": "IDID"
|
|
}]
|
|
|
|
self.http_boot = '/var/lib/ironic/httpboot'
|
|
|
|
def test_with_ip_range(self):
|
|
argslist = ['--range', '10.0.0.0/24',
|
|
'--credentials', 'admin:password']
|
|
verifylist = [('ip_addresses', '10.0.0.0/24'),
|
|
('credentials', ['admin:password'])]
|
|
|
|
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
|
self.cmd.take_action(parsed_args)
|
|
|
|
def test_with_address_list(self):
|
|
argslist = ['--ip', '10.0.0.1', '--ip', '10.0.0.2',
|
|
'--credentials', 'admin:password']
|
|
verifylist = [('ip_addresses', ['10.0.0.1', '10.0.0.2']),
|
|
('credentials', ['admin:password'])]
|
|
|
|
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
|
self.cmd.take_action(parsed_args)
|
|
|
|
def test_with_all_options(self):
|
|
argslist = ['--range', '10.0.0.0/24',
|
|
'--credentials', 'admin:password',
|
|
'--credentials', 'admin2:password2',
|
|
'--port', '623', '--port', '6230',
|
|
'--introspect', '--provide', '--run-validations',
|
|
'--no-deploy-image', '--instance-boot-option', 'netboot',
|
|
'--concurrency', '10']
|
|
verifylist = [('ip_addresses', '10.0.0.0/24'),
|
|
('credentials', ['admin:password', 'admin2:password2']),
|
|
('port', [623, 6230]),
|
|
('introspect', True),
|
|
('run_validations', True),
|
|
('concurrency', 10),
|
|
('provide', True),
|
|
('no_deploy_image', True),
|
|
('instance_boot_option', 'netboot')]
|
|
|
|
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
|
|
self.cmd.take_action(parsed_args)
|