Add commands to enable and disable the serial console
This allows you to access the serial console from within Horizon. Change-Id: Id40e72047174fc0c0c565871f24b775b30e83825 Story: 2004192 Task: 27682
This commit is contained in:
parent
60ecee2b25
commit
4867c91481
130
ansible/baremetal-compute-serial-console.yml
Normal file
130
ansible/baremetal-compute-serial-console.yml
Normal file
@ -0,0 +1,130 @@
|
||||
---
|
||||
# This playbook will enable a serial console on all ironic nodes. This
|
||||
# will allow you to access the serial console from within Horizon.
|
||||
# See: https://docs.openstack.org/ironic/latest/admin/console.html
|
||||
|
||||
- name: Setup OpenStack Environment
|
||||
hosts: controllers[0]
|
||||
gather_facts: False
|
||||
vars:
|
||||
venv: "{{ virtualenv_path }}/openstack-cli"
|
||||
pre_tasks:
|
||||
- name: Set up openstack cli virtualenv
|
||||
pip:
|
||||
virtualenv: "{{ venv }}"
|
||||
name:
|
||||
- python-openstackclient
|
||||
- python-ironicclient
|
||||
|
||||
- block:
|
||||
- name: Fail if allocation pool start not defined
|
||||
fail:
|
||||
msg: >
|
||||
The variable, ironic_serial_console_tcp_pool_start is not defined.
|
||||
This variable is required to run this playbook.
|
||||
when: not ironic_serial_console_tcp_pool_start
|
||||
|
||||
- name: Fail if allocation pool end not defined
|
||||
fail:
|
||||
msg: >
|
||||
The variable, ironic_serial_console_tcp_pool_end is not defined.
|
||||
This variable is required to run this playbook.
|
||||
when:
|
||||
- not ironic_serial_console_tcp_pool_end
|
||||
|
||||
- name: Get list of nodes that we should configure serial consoles on
|
||||
set_fact:
|
||||
baremetal_nodes: >-
|
||||
{{ query('inventory_hostnames', console_compute_node_limit |
|
||||
default('baremetal-compute') ) | unique }}
|
||||
|
||||
- name: Reserve TCP ports for ironic serial consoles
|
||||
include_role:
|
||||
name: console-allocation
|
||||
vars:
|
||||
console_allocation_pool_start: "{{ ironic_serial_console_tcp_pool_start }}"
|
||||
console_allocation_pool_end: "{{ ironic_serial_console_tcp_pool_end }}"
|
||||
console_allocation_ironic_nodes: "{{ baremetal_nodes }}"
|
||||
console_allocation_filename: "{{ kayobe_config_path }}/console-allocation.yml"
|
||||
when: cmd == "enable"
|
||||
|
||||
- name: Enable serial console
|
||||
hosts: "{{ console_compute_node_limit | default('baremetal-compute') }}"
|
||||
gather_facts: False
|
||||
vars:
|
||||
venv: "{{ virtualenv_path }}/openstack-cli"
|
||||
controller_host: "{{ groups['controllers'][0] }}"
|
||||
tasks:
|
||||
- name: Get list of nodes
|
||||
command: >
|
||||
{{ venv }}/bin/openstack baremetal node list -f json --long
|
||||
register: nodes
|
||||
delegate_to: "{{ controller_host }}"
|
||||
environment: "{{ openstack_auth_env }}"
|
||||
run_once: true
|
||||
changed_when: false
|
||||
vars:
|
||||
# NOTE: Without this, the controller's ansible_host variable will not
|
||||
# be respected when using delegate_to.
|
||||
ansible_host: "{{ hostvars[controller_host].ansible_host | default(controller_host) }}"
|
||||
|
||||
- block:
|
||||
- name: Fail if console interface is not ipmitool-socat
|
||||
fail:
|
||||
msg: >-
|
||||
In order to use the serial console you must set the console_interface to ipmitool-socat.
|
||||
when: node["Console Interface"] != "ipmitool-socat"
|
||||
|
||||
- name: Set IPMI serial console terminal port
|
||||
vars:
|
||||
name: "{{ node['Name'] }}"
|
||||
port: "{{ hostvars[controller_host].console_allocation_result.ports[name] }}"
|
||||
# NOTE: Without this, the controller's ansible_host variable will not
|
||||
# be respected when using delegate_to.
|
||||
ansible_host: "{{ hostvars[controller_host].ansible_host | default(controller_host) }}"
|
||||
command: >
|
||||
{{ venv }}/bin/openstack baremetal node set {{ name }} --driver-info ipmi_terminal_port={{ port }}
|
||||
delegate_to: "{{ controller_host }}"
|
||||
environment: "{{ openstack_auth_env }}"
|
||||
when: >-
|
||||
node['Driver Info'].ipmi_terminal_port is not defined or
|
||||
node['Driver Info'].ipmi_terminal_port | int != port | int
|
||||
|
||||
- name: Enable the IPMI socat serial console
|
||||
vars:
|
||||
# NOTE: Without this, the controller's ansible_host variable will not
|
||||
# be respected when using delegate_to.
|
||||
ansible_host: "{{ hostvars[controller_host].ansible_host | default(controller_host) }}"
|
||||
command: >
|
||||
{{ venv }}/bin/openstack baremetal node console enable {{ node['Name'] }}
|
||||
delegate_to: "{{ controller_host }}"
|
||||
environment: "{{ openstack_auth_env }}"
|
||||
when: not node['Console Enabled']
|
||||
vars:
|
||||
matching_nodes: >-
|
||||
{{ (nodes.stdout | from_json) | selectattr('Name', 'defined') |
|
||||
selectattr('Name', 'equalto', inventory_hostname ) | list }}
|
||||
node: "{{ matching_nodes | first }}"
|
||||
when:
|
||||
- cmd == "enable"
|
||||
- matching_nodes | length > 0
|
||||
|
||||
- block:
|
||||
- name: Disable the IPMI socat serial console
|
||||
vars:
|
||||
# NOTE: Without this, the controller's ansible_host variable will not
|
||||
# be respected when using delegate_to.
|
||||
ansible_host: "{{ hostvars[controller_host].ansible_host | default(controller_host) }}"
|
||||
command: >
|
||||
{{ venv }}/bin/openstack baremetal node console disable {{ node['Name'] }}
|
||||
delegate_to: "{{ controller_host }}"
|
||||
environment: "{{ openstack_auth_env }}"
|
||||
when: node['Console Enabled']
|
||||
vars:
|
||||
matching_nodes: >-
|
||||
{{ (nodes.stdout | from_json) | selectattr('Name', 'defined') |
|
||||
selectattr('Name', 'equalto', inventory_hostname ) | list }}
|
||||
node: "{{ matching_nodes | first }}"
|
||||
when:
|
||||
- cmd == "disable"
|
||||
- matching_nodes | length > 0
|
@ -132,3 +132,16 @@ kolla_ironic_pxe_append_params_extra: []
|
||||
kolla_ironic_pxe_append_params: >
|
||||
{{ kolla_ironic_pxe_append_params_default +
|
||||
kolla_ironic_pxe_append_params_extra }}
|
||||
|
||||
###############################################################################
|
||||
# Ironic Node Configuration
|
||||
|
||||
# This defines the start of the range of TCP ports to used for the IPMI socat
|
||||
# serial consoles
|
||||
ironic_serial_console_tcp_pool_start: 30000
|
||||
|
||||
# This defines the end of the range of TCP ports to used for the IPMI socat
|
||||
# serial consoles
|
||||
ironic_serial_console_tcp_pool_end: 31000
|
||||
|
||||
###############################################################################
|
||||
|
13
ansible/roles/console-allocation/defaults/main.yml
Normal file
13
ansible/roles/console-allocation/defaults/main.yml
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
# Path to file in which to store console allocations.
|
||||
console_allocation_filename:
|
||||
|
||||
# List of Names or UUIDs corresponding to Ironic nodes that you want to allocate
|
||||
# serial consoles for
|
||||
console_allocation_ironic_nodes: []
|
||||
|
||||
# allocation_pool_start: First TCP port in the allocation pool
|
||||
console_allocation_pool_start:
|
||||
|
||||
# allocation_pool_end: Last TCP port in the allocation pool
|
||||
console_allocation_pool_end:
|
192
ansible/roles/console-allocation/library/console_allocation.py
Normal file
192
ansible/roles/console-allocation/library/console_allocation.py
Normal file
@ -0,0 +1,192 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright (c) 2017 StackHPC Ltd.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# TODO(wszumski): If we have multiple conductors and they are on different machines
|
||||
# we could make a pool per machine.
|
||||
|
||||
DOCUMENTATION = """
|
||||
module: console_allocation
|
||||
short_description: Allocate a serial console TCP port for an Ironic node from a pool
|
||||
author: Mark Goddard (mark@stackhpc.com) and Will Szumski (will@stackhpc.com)
|
||||
options:
|
||||
- option-name: nodes
|
||||
description: List of Names or UUIDs corresponding to Ironic Nodes
|
||||
required: True
|
||||
type: list
|
||||
- option-name: allocation_pool_start
|
||||
description: First address of the pool from which to allocate
|
||||
required: True
|
||||
type: int
|
||||
- option-name: allocation_pool_end
|
||||
description: Last address of the pool from which to allocate
|
||||
required: True
|
||||
type: int
|
||||
- option-name: allocation_file
|
||||
description: >
|
||||
Path to a file in which to store the allocations. Will be created if it
|
||||
does not exist.
|
||||
required: True
|
||||
type: string
|
||||
requirements:
|
||||
- PyYAML
|
||||
"""
|
||||
|
||||
EXAMPLES = """
|
||||
- name: Ensure Ironic node has a TCP port assigned for it's serial console
|
||||
console_allocation:
|
||||
nodes: ['node-1', 'node-2']
|
||||
allocation_pool_start: 30000
|
||||
allocation_pool_end: 31000
|
||||
allocation_file: /path/to/allocation/file.yml
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
ports:
|
||||
description: >
|
||||
A dictionary mapping the node name to the allocated serial console TCP port
|
||||
returned: success
|
||||
type: dict
|
||||
sample: { 'node1' : 30000, 'node2':300001 }
|
||||
"""
|
||||
|
||||
from ansible.module_utils.basic import *
|
||||
import sys
|
||||
|
||||
# Store a list of import errors to report to the user.
|
||||
IMPORT_ERRORS=[]
|
||||
try:
|
||||
import yaml
|
||||
except Exception as e:
|
||||
IMPORT_ERRORS.append(e)
|
||||
|
||||
|
||||
def read_allocations(module):
|
||||
"""Read TCP port allocations from the allocation file."""
|
||||
filename = module.params['allocation_file']
|
||||
try:
|
||||
with open(filename, 'r') as f:
|
||||
content = yaml.load(f)
|
||||
except IOError as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
# Ignore ENOENT - we will create the file.
|
||||
return {}
|
||||
module.fail_json(msg="Failed to open allocation file %s for reading" % filename)
|
||||
except yaml.YAMLError as e:
|
||||
module.fail_json(msg="Failed to parse allocation file %s as YAML" % filename)
|
||||
if content is None:
|
||||
# If the file is empty, yaml.load() will return None.
|
||||
content = {}
|
||||
return content
|
||||
|
||||
|
||||
def write_allocations(module, allocations):
|
||||
"""Write TCP port allocations to the allocation file."""
|
||||
filename = module.params['allocation_file']
|
||||
try:
|
||||
with open(filename, 'w') as f:
|
||||
yaml.dump(allocations, f, default_flow_style=False)
|
||||
except IOError as e:
|
||||
module.fail_json(msg="Failed to open allocation file %s for writing" % filename)
|
||||
except yaml.YAMLError as e:
|
||||
module.fail_json(msg="Failed to dump allocation file %s as YAML" % filename)
|
||||
|
||||
def is_valid_port(port):
|
||||
try:
|
||||
int(port)
|
||||
except ValueError:
|
||||
return False
|
||||
if port < 0:
|
||||
return False
|
||||
if port > 65535:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def update_allocation(module, allocations):
|
||||
"""Allocate a TCP port of an Ironic serial console.
|
||||
|
||||
:param module: AnsibleModule instance
|
||||
:param allocations: Existing IP address allocations
|
||||
"""
|
||||
nodes = module.params['nodes']
|
||||
|
||||
allocation_pool_start = module.params['allocation_pool_start']
|
||||
allocation_pool_end = module.params['allocation_pool_end']
|
||||
result = {
|
||||
'changed': False,
|
||||
'ports': {}
|
||||
}
|
||||
object_name = "serial_console_allocations"
|
||||
console_allocations = allocations.setdefault(object_name, {})
|
||||
invalid_allocations = {node: port for node, port in console_allocations.items()
|
||||
if not is_valid_port(port)}
|
||||
if invalid_allocations:
|
||||
module.fail_json(msg="Found invalid existing allocations in %s: %s" %
|
||||
(object_name,
|
||||
", ".join("%s: %s" % (node, port)
|
||||
for node, port in invalid_allocations.items())))
|
||||
|
||||
allocated_consoles = { int(x) for x in console_allocations.values() }
|
||||
allocation_pool = { x for x in range(allocation_pool_start, allocation_pool_end + 1) }
|
||||
free_ports = list(allocation_pool - allocated_consoles)
|
||||
free_ports.sort(reverse=True)
|
||||
|
||||
for node in nodes:
|
||||
if node not in console_allocations:
|
||||
if len(free_ports) < 1:
|
||||
module.fail_json(msg="No unallocated TCP ports for %s in %s" % (node, object_name))
|
||||
result['changed'] = True
|
||||
free_port = free_ports.pop()
|
||||
console_allocations[node] = free_port
|
||||
result['ports'][node] = console_allocations[node]
|
||||
return result
|
||||
|
||||
|
||||
def allocate(module):
|
||||
"""Allocate a TCP port an ironic serial console, updating the allocation file."""
|
||||
allocations = read_allocations(module)
|
||||
result = update_allocation(module, allocations)
|
||||
if result['changed'] and not module.check_mode:
|
||||
write_allocations(module, allocations)
|
||||
return result
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
nodes=dict(required=True, type='list'),
|
||||
allocation_pool_start=dict(required=True, type='int'),
|
||||
allocation_pool_end=dict(required=True, type='int'),
|
||||
allocation_file=dict(required=True, type='str'),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
# Fail if there were any exceptions when importing modules.
|
||||
if IMPORT_ERRORS:
|
||||
module.fail_json(msg="Import errors: %s" %
|
||||
", ".join([repr(e) for e in IMPORT_ERRORS]))
|
||||
|
||||
try:
|
||||
results = allocate(module)
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to allocate TCP port: %s" % repr(e))
|
||||
else:
|
||||
module.exit_json(**results)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
73
ansible/roles/console-allocation/tasks/main.yml
Normal file
73
ansible/roles/console-allocation/tasks/main.yml
Normal file
@ -0,0 +1,73 @@
|
||||
---
|
||||
# Facts may not be available for the Ansible control host, so read the OS
|
||||
# release manually.
|
||||
- name: Check the OS release
|
||||
local_action:
|
||||
module: shell . /etc/os-release && echo $ID
|
||||
changed_when: False
|
||||
register: console_allocation_os_release
|
||||
|
||||
- name: Include RedHat family-specific variables
|
||||
include_vars: "RedHat.yml"
|
||||
when: console_allocation_os_release.stdout in ['centos', 'fedora', 'rhel']
|
||||
|
||||
- name: Include Debian family-specific variables
|
||||
include_vars: "Debian.yml"
|
||||
when: console_allocation_os_release.stdout in ['debian', 'ubuntu']
|
||||
|
||||
# Note: Currently we install these using the system package manager rather than
|
||||
# pip to a virtualenv. This is because Yum is required elsewhere and cannot
|
||||
# easily be installed in a virtualenv.
|
||||
- name: Ensure package dependencies are installed
|
||||
local_action:
|
||||
module: package
|
||||
name: "{{ item }}"
|
||||
state: installed
|
||||
use: "{{ console_allocation_package_manager }}"
|
||||
become: True
|
||||
with_items: "{{ console_allocation_package_dependencies }}"
|
||||
run_once: True
|
||||
|
||||
- name: Validate allocation pool start
|
||||
vars:
|
||||
port: "{{ console_allocation_pool_start | int(default=-1) }}"
|
||||
fail:
|
||||
msg: >-
|
||||
You must must define an console_allocation_pool_start. This should
|
||||
be a valid TCP port.
|
||||
when: >-
|
||||
console_allocation_pool_end is none or
|
||||
port | int < 0 or port | int > 65535
|
||||
|
||||
- name: Validate allocation pool end
|
||||
vars:
|
||||
port: "{{ console_allocation_pool_end | int(default=-1) }}"
|
||||
fail:
|
||||
msg: >-
|
||||
You must must define an console_allocation_pool_end. This should
|
||||
be a valid TCP port.
|
||||
when: >-
|
||||
console_allocation_pool_end is none or
|
||||
port | int < 0 or port | int > 65535
|
||||
|
||||
- name: Validate that allocation start is less than allocation end
|
||||
fail:
|
||||
msg: >-
|
||||
console_allocation_start and console_allocation_end define a range
|
||||
of TCP ports. You have defined a range with a start that is less than
|
||||
the end
|
||||
when:
|
||||
- (console_allocation_pool_start | int) > (console_allocation_pool_end | int)
|
||||
|
||||
- name: Ensure Ironic serial console ports are allocated
|
||||
local_action:
|
||||
module: console_allocation
|
||||
allocation_file: "{{ console_allocation_filename }}"
|
||||
nodes: "{{ console_allocation_ironic_nodes }}"
|
||||
allocation_pool_start: "{{ console_allocation_pool_start }}"
|
||||
allocation_pool_end: "{{ console_allocation_pool_end }}"
|
||||
register: result
|
||||
|
||||
- name: Register a fact containing the console allocation result
|
||||
set_fact:
|
||||
console_allocation_result: "{{ result }}"
|
7
ansible/roles/console-allocation/vars/Debian.yml
Normal file
7
ansible/roles/console-allocation/vars/Debian.yml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
# Package manager to use.
|
||||
console_allocation_package_manager: apt
|
||||
|
||||
# List of packages to install.
|
||||
console_allocation_package_dependencies:
|
||||
- python-yaml
|
7
ansible/roles/console-allocation/vars/RedHat.yml
Normal file
7
ansible/roles/console-allocation/vars/RedHat.yml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
# Package manager to use.
|
||||
console_allocation_package_manager: yum
|
||||
|
||||
# List of packages to install.
|
||||
console_allocation_package_dependencies:
|
||||
- PyYAML
|
@ -203,6 +203,53 @@ according to their inventory host names, you can run the following command::
|
||||
This command will use the ``ipmi_address`` host variable from the inventory
|
||||
to map the inventory host name to the correct node.
|
||||
|
||||
|
||||
Ironic Serial Console
|
||||
---------------------
|
||||
|
||||
To access the baremetal nodes from within Horizon you need to enable the serial
|
||||
console. For this to work the you must set ``kolla_enable_nova_serialconsole_proxy``
|
||||
to ``true`` in ``etc/kayobe/kolla.yml``::
|
||||
|
||||
kolla_enable_nova_serialconsole_proxy: true
|
||||
|
||||
The console interface on the Ironic nodes is expected to be ``ipmitool-socat``, you
|
||||
can check this with::
|
||||
|
||||
openstack baremetal node show <node_id> --fields console_interface
|
||||
|
||||
where <node_id> should be the UUID or name of the Ironic node you want to check.
|
||||
|
||||
If you have set ``kolla_ironic_enabled_console_interfaces`` in ``etc/kayobe/ironic.yml``,
|
||||
it should include ``ipmitool-socat`` in the list of enabled interfaces.
|
||||
|
||||
The playbook to enable the serial console currently only works if the Ironic node
|
||||
name matches the inventory hostname.
|
||||
|
||||
Once these requirements have been satisfied, you can run::
|
||||
|
||||
(kayobe) $ kayobe baremetal compute serial console enable
|
||||
|
||||
This will reserve a TCP port for each node to use for the serial console interface.
|
||||
The allocations are stored in ``${KAYOBE_CONFIG_PATH}/console-allocation.yml``. The
|
||||
current implementation uses a global pool, which is specified by
|
||||
``ironic_serial_console_tcp_pool_start`` and ``ironic_serial_console_tcp_pool_end``;
|
||||
these variables can set in ``etc/kayobe/ironic.yml``.
|
||||
|
||||
To disable the serial console you can use::
|
||||
|
||||
(kayobe) $ kayobe baremetal compute serial console disable
|
||||
|
||||
The port allocated for each node is retained and must be manually removed from
|
||||
``${KAYOBE_CONFIG_PATH}/console-allocation.yml`` if you want it to be reused by another
|
||||
Ironic node with a different name.
|
||||
|
||||
You can optionally limit the nodes targeted by setting ``baremetal-compute-limit``::
|
||||
|
||||
(kayobe) $ kayobe baremetal compute serial console enable --baremetal-compute-limit sand-6-1
|
||||
|
||||
which should take the form of an `ansible host pattern <https://docs.ansible.com/ansible/latest/user_guide/intro_patterns.html>`_.
|
||||
|
||||
.. _update_deployment_image:
|
||||
|
||||
Update Deployment Image
|
||||
|
@ -106,6 +106,17 @@
|
||||
# List of kernel parameters to append for baremetal PXE boot.
|
||||
#kolla_ironic_pxe_append_params:
|
||||
|
||||
###############################################################################
|
||||
# Ironic Node Configuration
|
||||
|
||||
# This defines the start of the range of TCP ports to used for the IPMI socat
|
||||
# serial consoles
|
||||
#ironic_serial_console_tcp_pool_start:
|
||||
|
||||
# This defines the end of the range of TCP ports to used for the IPMI socat
|
||||
# serial consoles
|
||||
#ironic_serial_console_tcp_pool_end:
|
||||
|
||||
###############################################################################
|
||||
# Dummy variable to allow Ansible to accept this file.
|
||||
workaround_ansible_issue_8743: yes
|
||||
|
@ -1247,6 +1247,57 @@ class BaremetalComputeRename(KayobeAnsibleMixin, VaultMixin, Command):
|
||||
self.run_kayobe_playbooks(parsed_args, playbooks)
|
||||
|
||||
|
||||
class BaremetalComputeSerialConsoleBase(KayobeAnsibleMixin, VaultMixin,
|
||||
Command):
|
||||
|
||||
"""Base class for the baremetal serial console commands"""
|
||||
|
||||
@staticmethod
|
||||
def process_limit(parsed_args, extra_vars):
|
||||
if parsed_args.baremetal_compute_limit:
|
||||
extra_vars["console_compute_node_limit"] = (
|
||||
parsed_args.baremetal_compute_limit
|
||||
)
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(BaremetalComputeSerialConsoleBase, self).get_parser(
|
||||
prog_name)
|
||||
group = parser.add_argument_group("Baremetal Serial Consoles")
|
||||
group.add_argument("--baremetal-compute-limit",
|
||||
help="Limit the change to the hosts specified in "
|
||||
"this limit"
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
class BaremetalComputeSerialConsoleEnable(BaremetalComputeSerialConsoleBase):
|
||||
"""Enable Serial Console for Baremetal Compute Nodes"""
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.app.LOG.debug("Enabling serial console for ironic nodes")
|
||||
extra_vars = {}
|
||||
BaremetalComputeSerialConsoleBase.process_limit(parsed_args,
|
||||
extra_vars)
|
||||
extra_vars["cmd"] = "enable"
|
||||
playbooks = _build_playbook_list("baremetal-compute-serial-console")
|
||||
self.run_kayobe_playbooks(parsed_args, playbooks,
|
||||
extra_vars=extra_vars)
|
||||
|
||||
|
||||
class BaremetalComputeSerialConsoleDisable(BaremetalComputeSerialConsoleBase):
|
||||
"""Disable Serial Console for Baremetal Compute Nodes"""
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.app.LOG.debug("Disable serial console for ironic nodes")
|
||||
extra_vars = {}
|
||||
BaremetalComputeSerialConsoleBase.process_limit(parsed_args,
|
||||
extra_vars)
|
||||
extra_vars["cmd"] = "disable"
|
||||
playbooks = _build_playbook_list("baremetal-compute-serial-console")
|
||||
self.run_kayobe_playbooks(parsed_args, playbooks,
|
||||
extra_vars=extra_vars)
|
||||
|
||||
|
||||
class BaremetalComputeUpdateDeploymentImage(KayobeAnsibleMixin, VaultMixin,
|
||||
Command):
|
||||
"""Update the Ironic nodes to use the new kernel and ramdisk images."""
|
||||
|
@ -1150,6 +1150,100 @@ class TestCase(unittest.TestCase):
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_run.call_args_list)
|
||||
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_playbooks")
|
||||
def test_baremetal_compute_serial_console_enable(self, mock_run):
|
||||
command = commands.BaremetalComputeSerialConsoleEnable(TestApp(), [])
|
||||
parser = command.get_parser("test")
|
||||
parsed_args = parser.parse_args([])
|
||||
result = command.run(parsed_args)
|
||||
self.assertEqual(0, result)
|
||||
expected_calls = [
|
||||
mock.call(
|
||||
mock.ANY,
|
||||
[
|
||||
"ansible/baremetal-compute-serial-console.yml",
|
||||
|
||||
],
|
||||
extra_vars={
|
||||
"cmd": "enable",
|
||||
}
|
||||
),
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_run.call_args_list)
|
||||
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_playbooks")
|
||||
def test_baremetal_compute_serial_console_enable_with_limit(self,
|
||||
mock_run):
|
||||
command = commands.BaremetalComputeSerialConsoleEnable(TestApp(), [])
|
||||
parser = command.get_parser("test")
|
||||
parsed_args = parser.parse_args(["--baremetal-compute-limit",
|
||||
"sand-6-1"])
|
||||
result = command.run(parsed_args)
|
||||
self.assertEqual(0, result)
|
||||
expected_calls = [
|
||||
mock.call(
|
||||
mock.ANY,
|
||||
[
|
||||
"ansible/baremetal-compute-serial-console.yml",
|
||||
|
||||
],
|
||||
extra_vars={
|
||||
"cmd": "enable",
|
||||
"console_compute_node_limit": "sand-6-1",
|
||||
}
|
||||
),
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_run.call_args_list)
|
||||
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_playbooks")
|
||||
def test_baremetal_compute_serial_console_disable(self, mock_run):
|
||||
command = commands.BaremetalComputeSerialConsoleDisable(TestApp(), [])
|
||||
parser = command.get_parser("test")
|
||||
parsed_args = parser.parse_args([])
|
||||
result = command.run(parsed_args)
|
||||
self.assertEqual(0, result)
|
||||
expected_calls = [
|
||||
mock.call(
|
||||
mock.ANY,
|
||||
[
|
||||
"ansible/baremetal-compute-serial-console.yml",
|
||||
|
||||
],
|
||||
extra_vars={
|
||||
"cmd": "disable",
|
||||
}
|
||||
),
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_run.call_args_list)
|
||||
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_playbooks")
|
||||
def test_baremetal_compute_serial_console_disable_with_limit(self,
|
||||
mock_run):
|
||||
command = commands.BaremetalComputeSerialConsoleDisable(TestApp(), [])
|
||||
parser = command.get_parser("test")
|
||||
parsed_args = parser.parse_args(["--baremetal-compute-limit",
|
||||
"sand-6-1"])
|
||||
result = command.run(parsed_args)
|
||||
self.assertEqual(0, result)
|
||||
expected_calls = [
|
||||
mock.call(
|
||||
mock.ANY,
|
||||
[
|
||||
"ansible/baremetal-compute-serial-console.yml",
|
||||
|
||||
],
|
||||
extra_vars={
|
||||
"cmd": "disable",
|
||||
"console_compute_node_limit": "sand-6-1",
|
||||
}
|
||||
),
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_run.call_args_list)
|
||||
|
||||
@mock.patch.object(commands.KayobeAnsibleMixin,
|
||||
"run_kayobe_playbooks")
|
||||
def test_baremetal_compute_update_deployment_image(self, mock_run):
|
||||
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Added commands to enable and disable the Ironic serial console.
|
||||
This allows you to use the serial console from within Horizon.
|
@ -33,6 +33,8 @@ kayobe.cli=
|
||||
baremetal_compute_provide = kayobe.cli.commands:BaremetalComputeProvide
|
||||
baremetal_compute_rename = kayobe.cli.commands:BaremetalComputeRename
|
||||
baremetal_compute_update_deployment_image = kayobe.cli.commands:BaremetalComputeUpdateDeploymentImage
|
||||
baremetal_compute_serial_console_enable = kayobe.cli.commands:BaremetalComputeSerialConsoleEnable
|
||||
baremetal_compute_serial_console_disable = kayobe.cli.commands:BaremetalComputeSerialConsoleDisable
|
||||
control_host_bootstrap = kayobe.cli.commands:ControlHostBootstrap
|
||||
control_host_upgrade = kayobe.cli.commands:ControlHostUpgrade
|
||||
configuration_dump = kayobe.cli.commands:ConfigurationDump
|
||||
|
Loading…
Reference in New Issue
Block a user