diff --git a/bootstrapvz/providers/kvm/README.rst b/bootstrapvz/providers/kvm/README.rst index 232a0aa..a79d5d7 100644 --- a/bootstrapvz/providers/kvm/README.rst +++ b/bootstrapvz/providers/kvm/README.rst @@ -16,10 +16,16 @@ Provider - ``virtio``: Specifies which virtio kernel modules to install. ``optional`` +- ``console``: Specifies which console should be used for stdout and stderr of init process + to show startup messages and act as a console in single-user mode. Regardless of + this setting output of kernel messages generated by ``printk()`` and seen by ``dmesg`` + goes to both virtual and serial console. Valid options: ```virtual``` or ```serial``` (default). + ``optional`` - ``logicalvolume``: Specifies the logical volume where the disk image will be built. - ``volumegroup``: Specifies the volume group where the logical volume will be stored. +- ``volumegroup``: Specifies the volume group where the logical volume will be stored. These options should only be used if ``lvm`` was given as a disk backend. + Example: .. code-block:: yaml @@ -30,6 +36,7 @@ Example: virtio: - virtio_blk - virtio_net + console: virtual volume: backing: lvm logicalvolume: lvtest diff --git a/bootstrapvz/providers/kvm/__init__.py b/bootstrapvz/providers/kvm/__init__.py index e993383..4104af0 100644 --- a/bootstrapvz/providers/kvm/__init__.py +++ b/bootstrapvz/providers/kvm/__init__.py @@ -1,5 +1,6 @@ from bootstrapvz.common import task_groups import tasks.packages +import tasks.boot from bootstrapvz.common.tasks import image, loopback, initd, ssh, logicalvolume @@ -31,6 +32,16 @@ def resolve_tasks(taskset, manifest): from tasks import virtio taskset.update([virtio.VirtIO]) + if manifest.provider.get('console', False): + if manifest.provider['console'] == 'virtual': + taskset.update([tasks.boot.SetGrubConsolOutputDeviceToVirtual]) + + from bootstrapvz.common.releases import jessie + if manifest.release >= jessie: + taskset.update([tasks.boot.SetGrubConsolOutputDeviceToVirtual, + tasks.boot.SetSystemdTTYVTDisallocate, + ]) + def resolve_rollback_tasks(taskset, manifest, completed, counter_task): taskset.update(task_groups.get_standard_rollback_tasks(completed)) diff --git a/bootstrapvz/providers/kvm/assets/noclear.conf b/bootstrapvz/providers/kvm/assets/noclear.conf new file mode 100644 index 0000000..59c004f --- /dev/null +++ b/bootstrapvz/providers/kvm/assets/noclear.conf @@ -0,0 +1,3 @@ +# https://wiki.debian.org/systemd#Missing_startup_messages_on_console.28tty1.29_after_the_boot +[Service] +TTYVTDisallocate=no diff --git a/bootstrapvz/providers/kvm/manifest-schema.yml b/bootstrapvz/providers/kvm/manifest-schema.yml index 931c3cf..503c0c5 100644 --- a/bootstrapvz/providers/kvm/manifest-schema.yml +++ b/bootstrapvz/providers/kvm/manifest-schema.yml @@ -18,6 +18,11 @@ properties: - virtio_net - virtio_ring minItems: 1 + console: + type: string + enum: + - serial + - virtual system: type: object properties: diff --git a/bootstrapvz/providers/kvm/tasks/boot.py b/bootstrapvz/providers/kvm/tasks/boot.py new file mode 100644 index 0000000..123d2e3 --- /dev/null +++ b/bootstrapvz/providers/kvm/tasks/boot.py @@ -0,0 +1,43 @@ +from bootstrapvz.base import Task +from bootstrapvz.common import phases +from bootstrapvz.common.tasks import grub +from bootstrapvz.common.tools import rel_path + +assets = rel_path(__file__, '../assets') + + +class SetGrubConsolOutputDeviceToVirtual(Task): + description = 'Setting the init process terminal output device to `tty0\'' + phase = phases.system_modification + predecessors = [grub.SetGrubConsolOutputDeviceToSerial] + successors = [grub.WriteGrubConfig] + + @classmethod + def run(cls, info): + info.grub_config['GRUB_CMDLINE_LINUX'].append('console=tty0') + + +class SetGrubSystemdShowStatus(Task): + description = 'Setting systemd show_status' + phase = phases.system_modification + successors = [grub.WriteGrubConfig] + + @classmethod + def run(cls, info): + info.grub_config['GRUB_CMDLINE_LINUX'].append('systemd.show_status=1') + + +class SetSystemdTTYVTDisallocate(Task): + description = 'Setting systemd TTYVTDisallocate to no\'' + phase = phases.system_modification + + @classmethod + def run(cls, info): + import os.path + from shutil import copy + + src = os.path.join(assets, 'noclear.conf') + dst_dir = os.path.join(info.root, 'etc/systemd/system/getty@tty1.service.d') + dst = os.path.join(dst_dir, 'noclear.conf') + os.mkdir(dst_dir, 0755) + copy(src, dst) diff --git a/manifests/examples/kvm/stretch-console.yml b/manifests/examples/kvm/stretch-console.yml new file mode 100644 index 0000000..9184e00 --- /dev/null +++ b/manifests/examples/kvm/stretch-console.yml @@ -0,0 +1,29 @@ +--- +name: debian-{system.release}-{system.architecture}-{%Y}{%m}{%d} +provider: + name: kvm + virtio_modules: + - virtio_blk + - virtio_net + - virtio_rng + console: virtual +bootstrapper: + workspace: /target +system: + release: stretch + architecture: amd64 + bootloader: grub + charmap: UTF-8 + locale: en_US + timezone: UTC +volume: + backing: raw + partitions: + type: msdos + root: + filesystem: ext4 + size: 2GiB + mountopts: + - defaults + - noatime + - errors=remount-ro