mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
virt: cleanup the consoles and serials support
This commit is contained in:
parent
a859c6cc84
commit
6cb22d64c5
6 changed files with 183 additions and 111 deletions
1
changelog/58844.added
Normal file
1
changelog/58844.added
Normal file
|
@ -0,0 +1 @@
|
|||
Enhance console and serial support in virt module
|
|
@ -184,10 +184,6 @@ VIRT_STATE_NAME_MAP = {
|
|||
6: "crashed",
|
||||
}
|
||||
|
||||
default_port = 23023
|
||||
default_serial_type = "tcp"
|
||||
default_console_type = "tcp"
|
||||
|
||||
|
||||
def __virtual__():
|
||||
if not HAS_LIBVIRT:
|
||||
|
@ -1027,70 +1023,57 @@ def _gen_xml(
|
|||
context["boot"]["kernel"] = "/usr/lib/grub2/x86_64-xen/grub.xen"
|
||||
context["boot_dev"] = []
|
||||
|
||||
context["serials"] = []
|
||||
if serials is not None:
|
||||
for serial in serials:
|
||||
serial_type = serial.get("type") or default_serial_type
|
||||
if not serial_type:
|
||||
raise SaltInvocationError("Missing type in serial")
|
||||
default_port = 23023
|
||||
default_chardev_type = "tcp"
|
||||
|
||||
serial_context = {"type": serial_type}
|
||||
if serial_context["type"] == "tcp":
|
||||
serial_context["port"] = serial.get("port", default_port)
|
||||
serial_context["protocol"] = serial.get("protocol", "telnet")
|
||||
context["serials"].append(serial_context)
|
||||
chardev_types = ["serial", "console"]
|
||||
for chardev_type in chardev_types:
|
||||
context[chardev_type + "s"] = []
|
||||
parameter_value = locals()[chardev_type + "s"]
|
||||
if parameter_value is not None:
|
||||
for chardev in parameter_value:
|
||||
chardev_context = chardev
|
||||
chardev_context["type"] = chardev.get("type", default_chardev_type)
|
||||
|
||||
context["consoles"] = []
|
||||
if consoles is not None:
|
||||
for console in consoles:
|
||||
console_type = console.get("type") or default_console_type
|
||||
if not console_type:
|
||||
raise SaltInvocationError("Missing type in console")
|
||||
|
||||
console_context = {"type": console_type}
|
||||
if console_context["type"] == "tcp":
|
||||
console_context["port"] = console.get("port", default_port)
|
||||
console_context["protocol"] = console.get("protocol", "telnet")
|
||||
context["consoles"].append(console_context)
|
||||
if chardev_context["type"] == "tcp":
|
||||
chardev_context["port"] = chardev.get("port", default_port)
|
||||
chardev_context["protocol"] = chardev.get("protocol", "telnet")
|
||||
context[chardev_type + "s"].append(chardev_context)
|
||||
|
||||
# processing of deprecated parameters
|
||||
old_port = kwargs.get("telnet_port")
|
||||
if old_port:
|
||||
salt.utils.versions.warn_until(
|
||||
"Aluminium",
|
||||
"Phosphorus",
|
||||
"'telnet_port' parameter has been deprecated, use the 'serials' and 'consoles' parameters instead. "
|
||||
"It will be removed in {version}.",
|
||||
"'telnet_port' parameter has been deprecated, use the 'serials' parameter with a value "
|
||||
"like ``{{{{'type': 'tcp', 'protocol': 'telnet', 'port': {}}}}}`` instead and a similar `consoles` parameter. "
|
||||
"It will be removed in {{version}}.".format(old_port),
|
||||
)
|
||||
|
||||
old_serial_type = kwargs.get("serial_type")
|
||||
if old_serial_type:
|
||||
salt.utils.versions.warn_until(
|
||||
"Aluminium",
|
||||
"'serial_type' parameter has been deprecated, use the 'serials' and 'consoles' parameters instead. "
|
||||
"It will be removed in {version}.",
|
||||
"Phosphorus",
|
||||
"'serial_type' parameter has been deprecated, use the 'serials' parameter with a value "
|
||||
"like ``{{{{'type': '{}', 'protocol': 'telnet' }}}}`` instead and a similar `consoles` parameter. "
|
||||
"It will be removed in {{version}}.".format(old_serial_type),
|
||||
)
|
||||
serial_context = {"type": serial_type}
|
||||
serial_context = {"type": old_serial_type}
|
||||
if serial_context["type"] == "tcp":
|
||||
serial_context["port"] = old_port if old_port is not None else default_port
|
||||
serial_context["protocol"] = serial.get("protocol", "telnet")
|
||||
serial_context["port"] = old_port or default_port
|
||||
serial_context["protocol"] = "telnet"
|
||||
context["serials"].append(serial_context)
|
||||
|
||||
old_console = kwargs.get("console")
|
||||
if old_console:
|
||||
salt.utils.versions.warn_until(
|
||||
"Aluminium",
|
||||
"'console' parameter has been deprecated, use the 'serials' and 'consoles' parameters instead. "
|
||||
"It will be removed in {version}.",
|
||||
)
|
||||
if old_console is True:
|
||||
console_context = {
|
||||
"type": old_serial_type if old_serial_type else default_console_type
|
||||
}
|
||||
if console_context["type"] == "tcp":
|
||||
console_context["port"] = old_port if old_port else default_port
|
||||
console_context["protocol"] = console.get("protocol", "telnet")
|
||||
context["consoles"].append(console_context)
|
||||
# end processing of deprecated parameters
|
||||
old_console = kwargs.get("console")
|
||||
if old_console:
|
||||
salt.utils.versions.warn_until(
|
||||
"Phosphorus",
|
||||
"'console' parameter has been deprecated, use the 'serials' and 'consoles' parameters instead. "
|
||||
"It will be removed in {version}.",
|
||||
)
|
||||
if old_console is True:
|
||||
context["consoles"].append(serial_context)
|
||||
|
||||
context["disks"] = []
|
||||
disk_bus_map = {"virtio": "vd", "xen": "xvd", "fdc": "fd", "ide": "hd"}
|
||||
|
@ -2275,13 +2258,13 @@ def init(
|
|||
|
||||
:param serials:
|
||||
Dictionary providing details on the serials connection to create. (Default: ``None``)
|
||||
See :ref:`init-serials-def` for more details on the possible values.
|
||||
See :ref:`init-chardevs-def` for more details on the possible values.
|
||||
|
||||
.. versionadded:: Aluminium
|
||||
|
||||
:param consoles:
|
||||
Dictionary providing details on the consoles device to create. (Default: ``None``)
|
||||
See :ref:`init-consoles-def` for more details on the possible values.
|
||||
See :ref:`init-chardevs-def` for more details on the possible values.
|
||||
|
||||
.. versionadded:: Aluminium
|
||||
|
||||
|
@ -2657,40 +2640,42 @@ def init(
|
|||
By default, not setting the ``listen`` part of the dictionary will default to
|
||||
listen on all addresses.
|
||||
|
||||
.. _init-serials-def:
|
||||
.. _init-chardevs-def:
|
||||
|
||||
.. rubric:: Serials Definitions
|
||||
.. rubric:: Serials and Consoles Definitions
|
||||
|
||||
Serial dictionaries can contain the following properties:
|
||||
|
||||
type
|
||||
Type of the serial connection, like ``'tcp'``, ``'pty'``.
|
||||
Type of the serial connection, like ``'tcp'``, ``'pty'``, ``'file'``, ``'udp'``, ``'dev'``,
|
||||
``'pipe'``, ``'unix'``.
|
||||
|
||||
port
|
||||
The serial port number.
|
||||
path
|
||||
Path to the source device. Can be a log file, a host character device to pass through,
|
||||
a unix socket, a named pipe path.
|
||||
|
||||
host
|
||||
The serial UDP or TCP host name.
|
||||
(Default: 23023)
|
||||
|
||||
Protocol
|
||||
Name of connection protocol.
|
||||
(Default: telnet)
|
||||
|
||||
.. _init-consoles-def:
|
||||
|
||||
.. rubric:: Consoles Definitions
|
||||
|
||||
Consol dictionaries can contain the following properties:
|
||||
|
||||
type
|
||||
Type of the serial connection, like ``'tcp'``, ``'pty'``.
|
||||
|
||||
port
|
||||
The serial port number.
|
||||
The serial UDP or TCP port number.
|
||||
(Default: 23023)
|
||||
|
||||
Protocol
|
||||
Name of connection protocol.
|
||||
protocol
|
||||
Name of the TCP connection protocol.
|
||||
(Default: telnet)
|
||||
|
||||
tls
|
||||
Boolean value indicating whether to use hypervisor TLS certificates environment for TCP devices.
|
||||
|
||||
target_port
|
||||
The guest device port number starting from 0
|
||||
|
||||
target_type
|
||||
The guest device type. Common values are ``serial``, ``virtio`` or ``usb-serial``, but more are documented in
|
||||
`the libvirt documentation <https://libvirt.org/formatdomain.html#consoles-serial-parallel-channel-devices>`_.
|
||||
|
||||
.. rubric:: CLI Example
|
||||
|
||||
.. code-block:: bash
|
||||
|
@ -3135,21 +3120,21 @@ def _serial_or_concole_equal(old, new):
|
|||
|
||||
def _diff_serial_list(old, new):
|
||||
"""
|
||||
Compare serial definitions to extract the changes
|
||||
Compare serial definitions to extract the changes
|
||||
|
||||
:param old: list of ElementTree nodes representing the old serials
|
||||
:param new: list of ElementTree nodes representing the new serials
|
||||
"""
|
||||
:param old: list of ElementTree nodes representing the old serials
|
||||
:param new: list of ElementTree nodes representing the new serials
|
||||
"""
|
||||
return _diff_lists(old, new, _serial_or_concole_equal)
|
||||
|
||||
|
||||
def _diff_console_list(old, new):
|
||||
"""
|
||||
Compare console definitions to extract the changes
|
||||
Compare console definitions to extract the changes
|
||||
|
||||
:param old: list of ElementTree nodes representing the old consoles
|
||||
:param new: list of ElementTree nodes representing the new consoles
|
||||
"""
|
||||
:param old: list of ElementTree nodes representing the old consoles
|
||||
:param new: list of ElementTree nodes representing the new consoles
|
||||
"""
|
||||
return _diff_lists(old, new, _serial_or_concole_equal)
|
||||
|
||||
|
||||
|
@ -3273,13 +3258,13 @@ def update(
|
|||
|
||||
:param serials:
|
||||
Dictionary providing details on the serials connection to create. (Default: ``None``)
|
||||
See :ref:`init-serials-def` for more details on the possible values.
|
||||
See :ref:`init-chardevs-def` for more details on the possible values.
|
||||
|
||||
.. versionadded:: Aluminium
|
||||
|
||||
:param consoles:
|
||||
Dictionary providing details on the consoles device to create. (Default: ``None``)
|
||||
See :ref:`init-consoles-def` for more details on the possible values.
|
||||
See :ref:`init-chardevs-def` for more details on the possible values.
|
||||
|
||||
.. versionadded:: Aluminium
|
||||
|
||||
|
|
|
@ -567,12 +567,12 @@ def defined(
|
|||
|
||||
:param serials:
|
||||
Dictionary providing details on the serials connection to create. (Default: ``None``)
|
||||
See :ref:`init-serials-def` for more details on the possible values.
|
||||
See :ref:`init-chardevs-def` for more details on the possible values.
|
||||
|
||||
.. versionadded:: Aluminium
|
||||
:param consoles:
|
||||
Dictionary providing details on the consoles device to create. (Default: ``None``)
|
||||
See :ref:`init-consoles-def` for more details on the possible values.
|
||||
See :ref:`init-chardevs-def` for more details on the possible values.
|
||||
|
||||
.. versionadded:: Aluminium
|
||||
|
||||
|
@ -841,12 +841,12 @@ def running(
|
|||
.. versionadded:: 3000
|
||||
:param serials:
|
||||
Dictionary providing details on the serials connection to create. (Default: ``None``)
|
||||
See :ref:`init-serials-def` for more details on the possible values.
|
||||
See :ref:`init-chardevs-def` for more details on the possible values.
|
||||
|
||||
.. versionadded:: Aluminium
|
||||
:param consoles:
|
||||
Dictionary providing details on the consoles device to create. (Default: ``None``)
|
||||
See :ref:`init-consoles-def` for more details on the possible values.
|
||||
See :ref:`init-chardevs-def` for more details on the possible values.
|
||||
|
||||
.. versionadded:: Aluminium
|
||||
|
||||
|
|
16
salt/templates/virt/libvirt_chardevs.jinja
Normal file
16
salt/templates/virt/libvirt_chardevs.jinja
Normal file
|
@ -0,0 +1,16 @@
|
|||
{% macro chardev(dev) -%}
|
||||
{% if dev.type == "unix" -%}
|
||||
<source mode="bind" path="{{ dev.path }}"/>
|
||||
{% elif dev.type in ["udp", "tcp"] -%}
|
||||
<source mode="bind" host="{{ dev.get('host', '0.0.0.0') }}" service="{{ dev.port }}"
|
||||
{% if dev.get('tls') is not none %}tls="{{'yes' if dev.tls else 'no'}}"{% endif %}/>
|
||||
{% elif dev.type in ["pipe", "dev", "pty", "file"] and dev.path -%}
|
||||
<source path="{{ dev.path }}"/>
|
||||
{%- endif %}
|
||||
{% if dev.type == "tcp" -%}
|
||||
<protocol type="{{ dev.protocol }}"/>
|
||||
{%- endif %}
|
||||
{% if "target_port" in dev or "target_type" in dev -%}
|
||||
<target port="{{ dev.get('target_port', 0) }}" {% if dev.target_type %}type="{{ dev.target_type }}"{% endif %}/>
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
|
@ -2,6 +2,7 @@
|
|||
{%- macro opt_attribute(obj, name, conv=none) %}
|
||||
{%- if obj.get(name) is not none %} {{ name }}='{{ obj[name] if conv is none else conv(obj[name]) }}'{% endif -%}
|
||||
{%- endmacro %}
|
||||
{%- import 'libvirt_chardevs.jinja' as libvirt_chardevs -%}
|
||||
<domain type='{{ hypervisor }}'>
|
||||
<name>{{ name }}</name>
|
||||
{%- if cpu %}
|
||||
|
@ -302,34 +303,24 @@
|
|||
address='{{ graphics.listen.address }}'
|
||||
{% endif %}/>
|
||||
</graphics>
|
||||
|
||||
{% if graphics.type == "spice" -%}
|
||||
<channel type='spicevmc'>
|
||||
<target type='virtio' name='com.redhat.spice.0'/>
|
||||
</channel>
|
||||
{%- endif %}
|
||||
{% endif %}
|
||||
|
||||
{% for serial in serials %}
|
||||
{% if serial.type == 'pty' %}
|
||||
<serial type='pty'>
|
||||
<target port='0'/>
|
||||
{%- for serial in serials %}
|
||||
<serial type='{{ serial.type }}'>
|
||||
{{ libvirt_chardevs.chardev(serial) }}
|
||||
</serial>
|
||||
{% elif serial.type == 'tcp' %}
|
||||
<serial type='tcp'>
|
||||
<source mode='bind' host='' service='{{ serial.port }}'/>
|
||||
<protocol type='{{ serial.protocol }}'/>
|
||||
<target port='0'/>
|
||||
</serial>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{%- endfor %}
|
||||
|
||||
{% for console in consoles %}
|
||||
{% if console.type == 'pty' %}
|
||||
<console type='pty'>
|
||||
<target type='serial' port='0'/>
|
||||
{%- for console in consoles %}
|
||||
<console type='{{ console.type }}'>
|
||||
{{ libvirt_chardevs.chardev(console) }}
|
||||
</console>
|
||||
{% elif console.type == 'tcp' %}
|
||||
<console type='tcp'>
|
||||
<source mode='bind' host='' service='{{ console.port }}'/>
|
||||
<protocol type='{{ console.protocol }}'/>
|
||||
<target type='serial' port='0'/>
|
||||
</console>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{%- if hypervisor in ["qemu", "kvm"] %}
|
||||
<channel type='unix'>
|
||||
|
|
|
@ -268,8 +268,87 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
|||
root = ET.fromstring(xml_data)
|
||||
self.assertEqual(root.find("devices/serial").attrib["type"], "tcp")
|
||||
self.assertEqual(root.find("devices/serial/source").attrib["service"], "23023")
|
||||
self.assertFalse("tls" in root.find("devices/serial/source").keys())
|
||||
self.assertEqual(root.find("devices/serial/protocol").attrib["type"], "telnet")
|
||||
|
||||
def test_gen_xml_for_chardev_types(self):
|
||||
"""
|
||||
Test virt._gen_xml() consoles and serials of various types
|
||||
"""
|
||||
diskp = virt._disk_profile(self.mock_conn, "default", "kvm", [], "hello")
|
||||
nicp = virt._nic_profile("default", "kvm")
|
||||
xml_data = virt._gen_xml(
|
||||
self.mock_conn,
|
||||
"hello",
|
||||
1,
|
||||
512,
|
||||
diskp,
|
||||
nicp,
|
||||
"kvm",
|
||||
"hvm",
|
||||
"x86_64",
|
||||
consoles=[
|
||||
{"type": "pty", "path": "/dev/pts/2", "target_port": 2},
|
||||
{"type": "pty", "target_type": "usb-serial"},
|
||||
{"type": "stdio"},
|
||||
{"type": "file", "path": "/path/to/serial.log"},
|
||||
],
|
||||
serials=[
|
||||
{"type": "pipe", "path": "/tmp/mypipe"},
|
||||
{"type": "udp", "host": "127.0.0.1", "port": 1234},
|
||||
{"type": "tcp", "port": 22223, "protocol": "raw", "tls": True},
|
||||
{"type": "unix", "path": "/path/to/socket"},
|
||||
],
|
||||
)
|
||||
root = ET.fromstring(xml_data)
|
||||
|
||||
self.assertEqual(root.find("devices/console[1]").attrib["type"], "pty")
|
||||
self.assertEqual(
|
||||
root.find("devices/console[1]/source").attrib["path"], "/dev/pts/2"
|
||||
)
|
||||
self.assertEqual(root.find("devices/console[1]/target").attrib["port"], "2")
|
||||
|
||||
self.assertEqual(root.find("devices/console[2]").attrib["type"], "pty")
|
||||
self.assertIsNone(root.find("devices/console[2]/source"))
|
||||
self.assertEqual(
|
||||
root.find("devices/console[2]/target").attrib["type"], "usb-serial"
|
||||
)
|
||||
|
||||
self.assertEqual(root.find("devices/console[3]").attrib["type"], "stdio")
|
||||
self.assertIsNone(root.find("devices/console[3]/source"))
|
||||
|
||||
self.assertEqual(root.find("devices/console[4]").attrib["type"], "file")
|
||||
self.assertEqual(
|
||||
root.find("devices/console[4]/source").attrib["path"], "/path/to/serial.log"
|
||||
)
|
||||
|
||||
self.assertEqual(root.find("devices/serial[1]").attrib["type"], "pipe")
|
||||
self.assertEqual(
|
||||
root.find("devices/serial[1]/source").attrib["path"], "/tmp/mypipe"
|
||||
)
|
||||
|
||||
self.assertEqual(root.find("devices/serial[2]").attrib["type"], "udp")
|
||||
self.assertEqual(root.find("devices/serial[2]/source").attrib["mode"], "bind")
|
||||
self.assertEqual(
|
||||
root.find("devices/serial[2]/source").attrib["service"], "1234"
|
||||
)
|
||||
self.assertEqual(
|
||||
root.find("devices/serial[2]/source").attrib["host"], "127.0.0.1"
|
||||
)
|
||||
|
||||
self.assertEqual(root.find("devices/serial[3]").attrib["type"], "tcp")
|
||||
self.assertEqual(root.find("devices/serial[3]/source").attrib["mode"], "bind")
|
||||
self.assertEqual(
|
||||
root.find("devices/serial[3]/source").attrib["service"], "22223"
|
||||
)
|
||||
self.assertEqual(root.find("devices/serial[3]/source").attrib["tls"], "yes")
|
||||
self.assertEqual(root.find("devices/serial[3]/protocol").attrib["type"], "raw")
|
||||
|
||||
self.assertEqual(root.find("devices/serial[4]").attrib["type"], "unix")
|
||||
self.assertEqual(
|
||||
root.find("devices/serial[4]/source").attrib["path"], "/path/to/socket"
|
||||
)
|
||||
|
||||
def test_gen_xml_no_nic_console(self):
|
||||
"""
|
||||
Test virt._gen_xml() console
|
||||
|
|
Loading…
Add table
Reference in a new issue