Adding ansible python interpreter as driver_info
This patch grants the possibility to change the ansible python interpreter used on remote managed machines as per-node driver_info option. Follw-up of https://review.openstack.org/641376 Change-Id: Ic1a994970a5aef5bbbbaaa747818e7ac402912ad Story: 2005159 Task: 29915
This commit is contained in:
parent
5614d251bb
commit
80e762e18a
@ -231,6 +231,13 @@ ansible_clean_steps_config
|
||||
Default is taken from ``[ansible]/default_clean_steps_config`` option of the
|
||||
ironic configuration file (defaults to ``clean_steps.yaml``).
|
||||
|
||||
ansible_python_interpreter
|
||||
Absolute path to the python interpreter on the managed machine.
|
||||
Default is taken from ``[ansible]/default_python_interpreter`` option of
|
||||
the ironic configuration file.
|
||||
Ansible uses ``/usr/bin/python`` by default.
|
||||
|
||||
|
||||
|
||||
Customizing the deployment logic
|
||||
================================
|
||||
|
@ -136,8 +136,10 @@ opts = [
|
||||
"'driver_info' field.")),
|
||||
cfg.StrOpt('default_python_interpreter',
|
||||
help=_("Absolute path to the python interpreter on the "
|
||||
"managed machines. By default, ansible uses "
|
||||
"/usr/bin/python")),
|
||||
"managed machines. It may be overridden by per-node "
|
||||
"'ansible_python_interpreter' option in node's "
|
||||
"'driver_info' field. "
|
||||
"By default, ansible uses /usr/bin/python")),
|
||||
]
|
||||
|
||||
|
||||
|
@ -73,6 +73,8 @@ OPTIONAL_PROPERTIES = {
|
||||
'ansible_clean_steps_config': _('Name of the file inside the '
|
||||
'"ansible_playbooks_path" folder with '
|
||||
'cleaning steps configuration. Optional.'),
|
||||
'ansible_python_interpreter': _('Absolute path to the python interpreter '
|
||||
'on the managed machines. Optional.'),
|
||||
}
|
||||
|
||||
COMMON_PROPERTIES = OPTIONAL_PROPERTIES
|
||||
@ -101,6 +103,11 @@ def _parse_ansible_driver_info(node, action='deploy'):
|
||||
return os.path.basename(playbook), user, key
|
||||
|
||||
|
||||
def _get_python_interpreter(node):
|
||||
return node.driver_info.get('ansible_python_interpreter',
|
||||
CONF.ansible.default_python_interpreter)
|
||||
|
||||
|
||||
def _get_configdrive_path(basename):
|
||||
return os.path.join(CONF.tempdir, basename + '.cndrive')
|
||||
|
||||
@ -126,9 +133,9 @@ def _run_playbook(node, name, extra_vars, key, tags=None, notags=None):
|
||||
playbook = os.path.join(root, name)
|
||||
inventory = os.path.join(root, 'inventory')
|
||||
ironic_vars = {'ironic': extra_vars}
|
||||
if CONF.ansible.default_python_interpreter:
|
||||
ironic_vars['ansible_python_interpreter'] = (
|
||||
CONF.ansible.default_python_interpreter)
|
||||
python_interpreter = _get_python_interpreter(node)
|
||||
if python_interpreter:
|
||||
ironic_vars['ansible_python_interpreter'] = python_interpreter
|
||||
args = [CONF.ansible.ansible_playbook_script, playbook,
|
||||
'-i', inventory,
|
||||
'-e', json.dumps(ironic_vars),
|
||||
|
@ -191,6 +191,35 @@ class TestAnsibleMethods(AnsibleDeployTestCaseBase):
|
||||
"ironic": {"foo": "bar"}},
|
||||
json.loads(all_vars))
|
||||
|
||||
@mock.patch.object(com_utils, 'execute', return_value=('out', 'err'),
|
||||
autospec=True)
|
||||
def test__run_playbook_ansible_interpreter_override(self, execute_mock):
|
||||
self.config(group='ansible', playbooks_path='/path/to/playbooks')
|
||||
self.config(group='ansible', config_file_path='/path/to/config')
|
||||
self.config(group='ansible', verbosity=3)
|
||||
self.config(group='ansible',
|
||||
default_python_interpreter='/usr/bin/python3')
|
||||
self.config(group='ansible', ansible_extra_args='--timeout=100')
|
||||
self.node.driver_info['ansible_python_interpreter'] = (
|
||||
'/usr/bin/python4')
|
||||
extra_vars = {'foo': 'bar'}
|
||||
|
||||
ansible_deploy._run_playbook(self.node, 'deploy',
|
||||
extra_vars, '/path/to/key',
|
||||
tags=['spam'], notags=['ham'])
|
||||
|
||||
execute_mock.assert_called_once_with(
|
||||
'env', 'ANSIBLE_CONFIG=/path/to/config',
|
||||
'ansible-playbook', '/path/to/playbooks/deploy', '-i',
|
||||
'/path/to/playbooks/inventory', '-e',
|
||||
mock.ANY, '--tags=spam', '--skip-tags=ham',
|
||||
'--private-key=/path/to/key', '-vvv', '--timeout=100')
|
||||
|
||||
all_vars = execute_mock.call_args[0][7]
|
||||
self.assertEqual({"ansible_python_interpreter": "/usr/bin/python4",
|
||||
"ironic": {"foo": "bar"}},
|
||||
json.loads(all_vars))
|
||||
|
||||
@mock.patch.object(com_utils, 'execute',
|
||||
side_effect=processutils.ProcessExecutionError(
|
||||
description='VIKINGS!'),
|
||||
@ -286,6 +315,16 @@ class TestAnsibleMethods(AnsibleDeployTestCaseBase):
|
||||
self.assertEqual(2, ansible_deploy._calculate_memory_req(task))
|
||||
image_mock.assert_called_once_with(task.context, 'fake-image')
|
||||
|
||||
def test__get_python_interpreter(self):
|
||||
self.config(group='ansible',
|
||||
default_python_interpreter='/usr/bin/python3')
|
||||
self.node.driver_info['ansible_python_interpreter'] = (
|
||||
'/usr/bin/python4')
|
||||
|
||||
python_interpreter = ansible_deploy._get_python_interpreter(self.node)
|
||||
|
||||
self.assertEqual('/usr/bin/python4', python_interpreter)
|
||||
|
||||
def test__get_configdrive_path(self):
|
||||
self.config(tempdir='/path/to/tmpdir')
|
||||
self.assertEqual('/path/to/tmpdir/spam.cndrive',
|
||||
|
@ -11,3 +11,5 @@ features:
|
||||
``/usr/bin/python3``.
|
||||
The same interpreter will be used in all operations that use the
|
||||
ansible deploy interface.
|
||||
It is also possible to override the value set in the configuration for a
|
||||
node by passing ``ansible_python_interpreter`` in its ``driver_info``.
|
Loading…
Reference in New Issue
Block a user