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
|
||||
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
|
||||
====================================
|
||||
|
||||
|
@ -122,3 +122,21 @@ Finally, start the Ironic and Ironic Inspector services again::
|
||||
|
||||
docker exec -it bifrost_deploy \
|
||||
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")
|
||||
|
||||
|
||||
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):
|
||||
"""Upgrade the seed hypervisor host services.
|
||||
|
||||
@ -503,6 +524,25 @@ class SeedHostPackageUpdate(KayobeAnsibleMixin, VaultMixin, Command):
|
||||
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,
|
||||
Command):
|
||||
"""Upgrade the seed host services.
|
||||
@ -877,6 +917,25 @@ class OvercloudHostPackageUpdate(KayobeAnsibleMixin, VaultMixin, Command):
|
||||
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):
|
||||
"""Upgrade the overcloud host services.
|
||||
|
||||
|
@ -273,6 +273,30 @@ class TestCase(unittest.TestCase):
|
||||
]
|
||||
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,
|
||||
"run_kayobe_playbooks")
|
||||
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)
|
||||
|
||||
@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,
|
||||
"run_kayobe_playbooks")
|
||||
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)
|
||||
|
||||
@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,
|
||||
"run_kayobe_playbooks")
|
||||
def test_overcloud_host_package_update_all(self, mock_run):
|
||||
|
@ -123,3 +123,8 @@ key2: value2
|
||||
|
||||
def test_quote_and_escape_non_string(self):
|
||||
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
|
||||
# under the License.
|
||||
|
||||
import base64
|
||||
import glob
|
||||
import logging
|
||||
import os
|
||||
@ -165,3 +166,18 @@ def quote_and_escape(value):
|
||||
if not isinstance(value, six.string_types):
|
||||
return value
|
||||
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_host_configure = kayobe.cli.commands:OvercloudHostConfigure
|
||||
overcloud_host_package_update = kayobe.cli.commands:OvercloudHostPackageUpdate
|
||||
overcloud_host_command_run = kayobe.cli.commands:OvercloudHostCommandRun
|
||||
overcloud_host_upgrade = kayobe.cli.commands:OvercloudHostUpgrade
|
||||
overcloud_introspection_data_save = kayobe.cli.commands:OvercloudIntrospectionDataSave
|
||||
overcloud_inventory_discover = kayobe.cli.commands:OvercloudInventoryDiscover
|
||||
@ -75,8 +76,10 @@ kayobe.cli=
|
||||
seed_deployment_image_build = kayobe.cli.commands:SeedDeploymentImageBuild
|
||||
seed_host_configure = kayobe.cli.commands:SeedHostConfigure
|
||||
seed_host_package_update = kayobe.cli.commands:SeedHostPackageUpdate
|
||||
seed_host_command_run = kayobe.cli.commands:SeedHostCommandRun
|
||||
seed_host_upgrade = kayobe.cli.commands:SeedHostUpgrade
|
||||
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_service_deploy = kayobe.cli.commands:SeedServiceDeploy
|
||||
seed_service_upgrade = kayobe.cli.commands:SeedServiceUpgrade
|
||||
|
Loading…
Reference in New Issue
Block a user