Add commands to run command on hosts
Change-Id: I019fc3f5c59c383215febb958f9c4cf8c8b8e4a6 Story: 2003312 Task: 24270
This commit is contained in:
parent
7cb684a253
commit
b8305b1799
6
ansible/host-command-run.yml
Normal file
6
ansible/host-command-run.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
- name: Run a command
|
||||||
|
hosts: seed-hypervisor:seed:overcloud
|
||||||
|
tasks:
|
||||||
|
- name: Run a command
|
||||||
|
shell: "{{ host_command_to_run }}"
|
@ -21,6 +21,20 @@ To only install updates that have been marked security related::
|
|||||||
Note that these commands do not affect packages installed in containers, only
|
Note that these commands do not affect packages installed in containers, only
|
||||||
those installed on the host.
|
those installed on the host.
|
||||||
|
|
||||||
|
Running Commands
|
||||||
|
================
|
||||||
|
|
||||||
|
It is possible to run a command on the overcloud hosts::
|
||||||
|
|
||||||
|
(kayobe) $ kayobe overcloud host command run --command "<command>"
|
||||||
|
|
||||||
|
For example::
|
||||||
|
|
||||||
|
(kayobe) $ kayobe overcloud host command run --command "service docker restart"
|
||||||
|
|
||||||
|
To execute the command with root privileges, add the ``--become`` argument.
|
||||||
|
Adding the ``--verbose`` argument allows the output of the command to be seen.
|
||||||
|
|
||||||
Reconfiguring Containerised Services
|
Reconfiguring Containerised Services
|
||||||
====================================
|
====================================
|
||||||
|
|
||||||
|
@ -122,3 +122,21 @@ Finally, start the Ironic and Ironic Inspector services again::
|
|||||||
|
|
||||||
docker exec -it bifrost_deploy \
|
docker exec -it bifrost_deploy \
|
||||||
systemctl start ironic-api ironic-conductor ironic-inspector
|
systemctl start ironic-api ironic-conductor ironic-inspector
|
||||||
|
|
||||||
|
Running Commands
|
||||||
|
================
|
||||||
|
|
||||||
|
It is possible to run a command on the seed host::
|
||||||
|
|
||||||
|
(kayobe) $ kayobe seed host command run --command "<command>"
|
||||||
|
|
||||||
|
For example::
|
||||||
|
|
||||||
|
(kayobe) $ kayobe seed host command run --command "service docker restart"
|
||||||
|
|
||||||
|
Commands can also be run on the seed hypervisor host, if one is in use::
|
||||||
|
|
||||||
|
(kayobe) $ kayobe seed hypervisor host command run --command "<command>"
|
||||||
|
|
||||||
|
To execute the command with root privileges, add the ``--become`` argument.
|
||||||
|
Adding the ``--verbose`` argument allows the output of the command to be seen.
|
||||||
|
@ -326,6 +326,27 @@ class SeedHypervisorHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin,
|
|||||||
limit="seed-hypervisor")
|
limit="seed-hypervisor")
|
||||||
|
|
||||||
|
|
||||||
|
class SeedHypervisorHostCommandRun(KayobeAnsibleMixin, VaultMixin, Command):
|
||||||
|
"""Run command on the seed hypervisor host."""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(SeedHypervisorHostCommandRun, self).get_parser(
|
||||||
|
prog_name)
|
||||||
|
group = parser.add_argument_group("Host Command Run")
|
||||||
|
group.add_argument("--command", required=True,
|
||||||
|
help="Command to run (required).")
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.debug("Run command on seed hypervisor host")
|
||||||
|
extra_vars = {
|
||||||
|
"host_command_to_run": utils.escape_jinja(parsed_args.command)}
|
||||||
|
playbooks = _build_playbook_list("host-command-run")
|
||||||
|
self.run_kayobe_playbooks(parsed_args, playbooks,
|
||||||
|
limit="seed-hypervisor",
|
||||||
|
extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
class SeedHypervisorHostUpgrade(KayobeAnsibleMixin, VaultMixin, Command):
|
class SeedHypervisorHostUpgrade(KayobeAnsibleMixin, VaultMixin, Command):
|
||||||
"""Upgrade the seed hypervisor host services.
|
"""Upgrade the seed hypervisor host services.
|
||||||
|
|
||||||
@ -503,6 +524,25 @@ class SeedHostPackageUpdate(KayobeAnsibleMixin, VaultMixin, Command):
|
|||||||
extra_vars=extra_vars)
|
extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class SeedHostCommandRun(KayobeAnsibleMixin, VaultMixin, Command):
|
||||||
|
"""Run command on the seed host."""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(SeedHostCommandRun, self).get_parser(prog_name)
|
||||||
|
group = parser.add_argument_group("Host Command Run")
|
||||||
|
group.add_argument("--command", required=True,
|
||||||
|
help="Command to run (required).")
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.debug("Run command on seed host")
|
||||||
|
extra_vars = {
|
||||||
|
"host_command_to_run": utils.escape_jinja(parsed_args.command)}
|
||||||
|
playbooks = _build_playbook_list("host-command-run")
|
||||||
|
self.run_kayobe_playbooks(parsed_args, playbooks, limit="seed",
|
||||||
|
extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
class SeedHostUpgrade(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin,
|
class SeedHostUpgrade(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin,
|
||||||
Command):
|
Command):
|
||||||
"""Upgrade the seed host services.
|
"""Upgrade the seed host services.
|
||||||
@ -877,6 +917,25 @@ class OvercloudHostPackageUpdate(KayobeAnsibleMixin, VaultMixin, Command):
|
|||||||
extra_vars=extra_vars)
|
extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class OvercloudHostCommandRun(KayobeAnsibleMixin, VaultMixin, Command):
|
||||||
|
"""Run command on the overcloud host."""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(OvercloudHostCommandRun, self).get_parser(prog_name)
|
||||||
|
group = parser.add_argument_group("Host Command Run")
|
||||||
|
group.add_argument("--command", required=True,
|
||||||
|
help="Command to run (required).")
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.debug("Run command on overcloud host")
|
||||||
|
extra_vars = {
|
||||||
|
"host_command_to_run": utils.escape_jinja(parsed_args.command)}
|
||||||
|
playbooks = _build_playbook_list("host-command-run")
|
||||||
|
self.run_kayobe_playbooks(parsed_args, playbooks, limit="overcloud",
|
||||||
|
extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
class OvercloudHostUpgrade(KayobeAnsibleMixin, VaultMixin, Command):
|
class OvercloudHostUpgrade(KayobeAnsibleMixin, VaultMixin, Command):
|
||||||
"""Upgrade the overcloud host services.
|
"""Upgrade the overcloud host services.
|
||||||
|
|
||||||
|
@ -273,6 +273,30 @@ class TestCase(unittest.TestCase):
|
|||||||
]
|
]
|
||||||
self.assertEqual(expected_calls, mock_run.call_args_list)
|
self.assertEqual(expected_calls, mock_run.call_args_list)
|
||||||
|
|
||||||
|
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||||
|
"run_kayobe_playbooks")
|
||||||
|
def test_seed_hypervisor_host_command_run(self, mock_run):
|
||||||
|
command = commands.SeedHypervisorHostCommandRun(TestApp(), [])
|
||||||
|
parser = command.get_parser("test")
|
||||||
|
parsed_args = parser.parse_args(["--command", "ls -a"])
|
||||||
|
|
||||||
|
result = command.run(parsed_args)
|
||||||
|
self.assertEqual(0, result)
|
||||||
|
|
||||||
|
expected_calls = [
|
||||||
|
mock.call(
|
||||||
|
mock.ANY,
|
||||||
|
[
|
||||||
|
utils.get_data_files_path("ansible",
|
||||||
|
"host-command-run.yml"),
|
||||||
|
],
|
||||||
|
limit="seed-hypervisor",
|
||||||
|
extra_vars={
|
||||||
|
"host_command_to_run": utils.escape_jinja("ls -a")},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
self.assertEqual(expected_calls, mock_run.call_args_list)
|
||||||
|
|
||||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||||
"run_kayobe_playbooks")
|
"run_kayobe_playbooks")
|
||||||
def test_seed_hypervisor_host_upgrade(self, mock_run):
|
def test_seed_hypervisor_host_upgrade(self, mock_run):
|
||||||
@ -485,6 +509,30 @@ class TestCase(unittest.TestCase):
|
|||||||
]
|
]
|
||||||
self.assertEqual(expected_calls, mock_kolla_run.call_args_list)
|
self.assertEqual(expected_calls, mock_kolla_run.call_args_list)
|
||||||
|
|
||||||
|
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||||
|
"run_kayobe_playbooks")
|
||||||
|
def test_seed_host_command_run(self, mock_run):
|
||||||
|
command = commands.SeedHostCommandRun(TestApp(), [])
|
||||||
|
parser = command.get_parser("test")
|
||||||
|
parsed_args = parser.parse_args(["--command", "ls -a"])
|
||||||
|
|
||||||
|
result = command.run(parsed_args)
|
||||||
|
self.assertEqual(0, result)
|
||||||
|
|
||||||
|
expected_calls = [
|
||||||
|
mock.call(
|
||||||
|
mock.ANY,
|
||||||
|
[
|
||||||
|
utils.get_data_files_path("ansible",
|
||||||
|
"host-command-run.yml"),
|
||||||
|
],
|
||||||
|
limit="seed",
|
||||||
|
extra_vars={
|
||||||
|
"host_command_to_run": utils.escape_jinja("ls -a")},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
self.assertEqual(expected_calls, mock_run.call_args_list)
|
||||||
|
|
||||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||||
"run_kayobe_playbooks")
|
"run_kayobe_playbooks")
|
||||||
def test_seed_host_package_update_all(self, mock_run):
|
def test_seed_host_package_update_all(self, mock_run):
|
||||||
@ -1059,6 +1107,30 @@ class TestCase(unittest.TestCase):
|
|||||||
]
|
]
|
||||||
self.assertEqual(expected_calls, mock_kolla_run.call_args_list)
|
self.assertEqual(expected_calls, mock_kolla_run.call_args_list)
|
||||||
|
|
||||||
|
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||||
|
"run_kayobe_playbooks")
|
||||||
|
def test_overcloud_host_command_run(self, mock_run):
|
||||||
|
command = commands.OvercloudHostCommandRun(TestApp(), [])
|
||||||
|
parser = command.get_parser("test")
|
||||||
|
parsed_args = parser.parse_args(["--command", "ls -a"])
|
||||||
|
|
||||||
|
result = command.run(parsed_args)
|
||||||
|
self.assertEqual(0, result)
|
||||||
|
|
||||||
|
expected_calls = [
|
||||||
|
mock.call(
|
||||||
|
mock.ANY,
|
||||||
|
[
|
||||||
|
utils.get_data_files_path("ansible",
|
||||||
|
"host-command-run.yml"),
|
||||||
|
],
|
||||||
|
limit="overcloud",
|
||||||
|
extra_vars={
|
||||||
|
"host_command_to_run": utils.escape_jinja("ls -a")},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
self.assertEqual(expected_calls, mock_run.call_args_list)
|
||||||
|
|
||||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||||
"run_kayobe_playbooks")
|
"run_kayobe_playbooks")
|
||||||
def test_overcloud_host_package_update_all(self, mock_run):
|
def test_overcloud_host_package_update_all(self, mock_run):
|
||||||
|
@ -123,3 +123,8 @@ key2: value2
|
|||||||
|
|
||||||
def test_quote_and_escape_non_string(self):
|
def test_quote_and_escape_non_string(self):
|
||||||
self.assertEqual(True, utils.quote_and_escape(True))
|
self.assertEqual(True, utils.quote_and_escape(True))
|
||||||
|
|
||||||
|
def test_escape_jinja(self):
|
||||||
|
value = "string to escape"
|
||||||
|
expected = "{{'c3RyaW5nIHRvIGVzY2FwZQ==' | b64decode }}"
|
||||||
|
self.assertEqual(expected, utils.escape_jinja(value))
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import base64
|
||||||
import glob
|
import glob
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
@ -165,3 +166,18 @@ def quote_and_escape(value):
|
|||||||
if not isinstance(value, six.string_types):
|
if not isinstance(value, six.string_types):
|
||||||
return value
|
return value
|
||||||
return "'" + value.replace("'", "'\\''") + "'"
|
return "'" + value.replace("'", "'\\''") + "'"
|
||||||
|
|
||||||
|
|
||||||
|
def escape_jinja(string):
|
||||||
|
"""Escapes a string so that jinja template variables are not expanded
|
||||||
|
|
||||||
|
:param string: the string to escape
|
||||||
|
:return: the escaped string
|
||||||
|
"""
|
||||||
|
# We base64 encode the string to avoid the need to escape characters.
|
||||||
|
# This is because ansible has some parsing quirks that makes it fairly
|
||||||
|
# hard to escape stuff in generic way.
|
||||||
|
# See: https://github.com/ansible/ansible/issues/10464
|
||||||
|
|
||||||
|
b64_value = base64.b64encode(string.encode())
|
||||||
|
return ''.join(('{{', "'", b64_value.decode(), "' | b64decode ", '}}'))
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Add commands to run commands on seed hypervisor, seed and overcloud hosts:
|
||||||
|
|
||||||
|
``kayobe seed hypervisor host command run --command <command>``
|
||||||
|
``kayobe seed host command run --command <command>``
|
||||||
|
``kayobe overcloud host command run --command <command>``
|
@ -58,6 +58,7 @@ kayobe.cli=
|
|||||||
overcloud_hardware_inspect = kayobe.cli.commands:OvercloudHardwareInspect
|
overcloud_hardware_inspect = kayobe.cli.commands:OvercloudHardwareInspect
|
||||||
overcloud_host_configure = kayobe.cli.commands:OvercloudHostConfigure
|
overcloud_host_configure = kayobe.cli.commands:OvercloudHostConfigure
|
||||||
overcloud_host_package_update = kayobe.cli.commands:OvercloudHostPackageUpdate
|
overcloud_host_package_update = kayobe.cli.commands:OvercloudHostPackageUpdate
|
||||||
|
overcloud_host_command_run = kayobe.cli.commands:OvercloudHostCommandRun
|
||||||
overcloud_host_upgrade = kayobe.cli.commands:OvercloudHostUpgrade
|
overcloud_host_upgrade = kayobe.cli.commands:OvercloudHostUpgrade
|
||||||
overcloud_introspection_data_save = kayobe.cli.commands:OvercloudIntrospectionDataSave
|
overcloud_introspection_data_save = kayobe.cli.commands:OvercloudIntrospectionDataSave
|
||||||
overcloud_inventory_discover = kayobe.cli.commands:OvercloudInventoryDiscover
|
overcloud_inventory_discover = kayobe.cli.commands:OvercloudInventoryDiscover
|
||||||
@ -75,8 +76,10 @@ kayobe.cli=
|
|||||||
seed_deployment_image_build = kayobe.cli.commands:SeedDeploymentImageBuild
|
seed_deployment_image_build = kayobe.cli.commands:SeedDeploymentImageBuild
|
||||||
seed_host_configure = kayobe.cli.commands:SeedHostConfigure
|
seed_host_configure = kayobe.cli.commands:SeedHostConfigure
|
||||||
seed_host_package_update = kayobe.cli.commands:SeedHostPackageUpdate
|
seed_host_package_update = kayobe.cli.commands:SeedHostPackageUpdate
|
||||||
|
seed_host_command_run = kayobe.cli.commands:SeedHostCommandRun
|
||||||
seed_host_upgrade = kayobe.cli.commands:SeedHostUpgrade
|
seed_host_upgrade = kayobe.cli.commands:SeedHostUpgrade
|
||||||
seed_hypervisor_host_configure = kayobe.cli.commands:SeedHypervisorHostConfigure
|
seed_hypervisor_host_configure = kayobe.cli.commands:SeedHypervisorHostConfigure
|
||||||
|
seed_hypervisor_host_command_run = kayobe.cli.commands:SeedHypervisorHostCommandRun
|
||||||
seed_hypervisor_host_upgrade = kayobe.cli.commands:SeedHypervisorHostUpgrade
|
seed_hypervisor_host_upgrade = kayobe.cli.commands:SeedHypervisorHostUpgrade
|
||||||
seed_service_deploy = kayobe.cli.commands:SeedServiceDeploy
|
seed_service_deploy = kayobe.cli.commands:SeedServiceDeploy
|
||||||
seed_service_upgrade = kayobe.cli.commands:SeedServiceUpgrade
|
seed_service_upgrade = kayobe.cli.commands:SeedServiceUpgrade
|
||||||
|
Loading…
Reference in New Issue
Block a user