Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

better support for CentOS; reboot if installer was unable to reload kernel module #27

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ additions. It searches the guest for a mounted ISO containing the
VBoxGuestAdditions, or an ISO file. When not found, it can download the
necessary ISO file directly from `download.virtualbox.org`.

Installation may require a reboot.

## Requirements

None, all prerequisites will be installed (and can be removed afterwards). If
Expand Down Expand Up @@ -51,6 +53,11 @@ virtualbox_version: auto
**virtualbox_x11**: A boolean stating whether VirtualBox guest additions will be
compiled with x11 support. If not specified, defaults to no.

**virtualbox_use_latest_kernel**: A boolean stating whether latest kernel must be
installed. If set to false, installation may fail due to kernel headers missing.
This is a common situation for Centos. If set to true, kernel will always be
updated to latest **and VM rebooted** if kernel version changed. Default is false.

## Dependencies

None.
Expand Down
1 change: 1 addition & 0 deletions defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ virtualbox_os_packages:
- virtualbox-guest-x11
virtualbox_remove_os_packages: false
virtualbox_version: auto
virtualbox_use_latest_kernel: false
162 changes: 104 additions & 58 deletions tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@

- name: Check if virtualbox_version could be determined
fail:
msg: "Could not determine virtualbox_version - please specify this variable"
msg: >-
Could not determine host VirtualBox version.
Probably you are running Ansible and VirtualBox from different hosts.
Please specify variable "virtualbox_version".
when: not host_vbox_version.stdout

- name: Override virtualbox_version if defaults set to auto
- name: Set virtualbox_version to host version
set_fact:
virtualbox_version: "{{ host_vbox_version.stdout }}"

Expand Down Expand Up @@ -79,12 +82,51 @@
ISO_path: "{{ file_path.stat.path if file_path.stat.exists else CD_path.stat.path }}"

- name: Check if VBoxGuest additions ISO is mounted
shell: mount -l 2>/dev/null|awk '/VBOXADDITIONS/{print $3}'
shell: mount -l 2>/dev/null|awk '/VBox_GAs/{print $3}'
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem OS-independent. There should be a nicer way of checking whether it's mounted - the current function is bit clunky

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ouch, that's not about OS. Looks like VirtualBox ISO volume name changed. And yes, mount detection fails for me a lot, too.

For both Debian and RPM distributions I have:

$ iso-info /usr/share/virtualbox/VBoxGuestAdditions.iso | grep '^Volume'
Volume      : VBox_GAs_6.1.18

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for that info, that helps. I'll try to find a cleaner way to detect a mounted disk: Maybe just probing for the file/binary?

args:
warn: False
register: mount_path
changed_when: mount_path is defined and not mount_path.stdout

- name: Check if VBoxGuest additions ISO is mounted
shell: mount -l 2>/dev/null|awk '/VBox_GAs/{print $3}'
args:
warn: False
register: mount_path

- name: Set package names for RedHat family OS
set_fact:
kernel_package_name: "kernel"
kernel_headers_name: "kernel-devel"
package_list_command: "rpm -qa"
when: ansible_os_family == "RedHat"

- block:
- name: Get Debian architecture
shell: "dpkg --print-architecture"
register: debian_architecture
changed_when: false
failed_when: not debian_architecture.stdout
- name: Set package names for Debian family OS
set_fact:
# apt requires to set at least architecture
kernel_package_name: "linux-image-{{ debian_architecture.stdout }}"
# headers package name will be appended with full version specification
kernel_headers_name: "linux-headers"
package_list_command: "dpkg -l"
when: ansible_os_family == "Debian"

- name: Update kernel
package:
name: "{{ kernel_package_name }}"
state: latest
register: kernel_updated
when: virtualbox_use_latest_kernel | bool

- name: Reboot VM into latest kernel
reboot:
when: kernel_updated.changed

- name: Mount VBoxGuestAdditions
mount:
name: /media/cdrom
Expand All @@ -95,62 +137,56 @@
register: mounted_ISO
when: mount_path is defined and not mount_path.stdout

- name: Check if VBoxGuest additions ISO is mounted
shell: mount -l 2>/dev/null|awk 'tolower($0) ~ /vbox.*additions/{print $3}'
args:
warn: False
register: mount_path

- name: Find out architecture
shell: uname -r | cut -d'-' -f3
register: kernel
changed_when: not kernel.stdout
- name: Save the current list of packages
shell: "{{ package_list_command }} > /tmp/before.txt"
when: virtualbox_keep is undefined or not virtualbox_keep
changed_when: false

- name: Save the current list of packages for Debians
block:
- name: Query current list
shell: dpkg-query -l > /tmp/before.txt
when: virtualbox_keep is undefined or not virtualbox_keep

- name: Install kernel headers for Debian
apt:
name: linux-headers-{{ kernel.stdout }}
update_cache: yes
cache_valid_time: 86400
install-recommends: no
state: present
when: kernel is defined and kernel.stdout is defined
- name: Get running kernel version
shell: "uname -r"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When no output redirection is necessary, it's safer to use the command module instead of the shell module.

register: kernel_version
failed_when: not kernel_version.stdout
changed_when: false

when: ansible_os_family == "Debian"
- name: Install kernel headers corresponding to running kernel
package:
name: "{{ kernel_headers_name }}-{{ kernel_version.stdout }}"
state: present
register: kernel_headers_installed
failed_when: false

- name: Save the current list of packages for CentOSes
block:
- name: Save the current list of packages for CentOSes
shell: rpm -qa > /tmp/before.txt
when: virtualbox_keep is undefined or not virtualbox_keep
- name: Check if kernel headers installed
fail:
msg: >-
Could not install package {{ kernel_headers_name }}-{{ kernel_version.stdout }}.
Probably, it's already removed from repositories. Try to set variable
virtualbox_use_latest_kernel to true. Latest kernel will be installed, and VM
will be reboot to it. Package manager returned: {{ kernel_headers_installed.msg }}
when: kernel_headers_installed.msg is defined and kernel_headers_installed.msg != ""

- block:
- name: Install EPEL repo.
yum:
name: https://dl.fedoraproject.org/pub/epel/epel-release-latest-{{ ansible_distribution_major_version }}.noarch.rpm
state: present

# those packages could be unsigned; in some case "no signature" == error
disable_gpg_check: True
- name: Import EPEL GPG key.
rpm_key:
key: /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-{{ ansible_distribution_major_version }}
state: present

- name: Install latest kernel and headers for CentOSes
yum:
name: ["kernel", "kernel-headers-{{ kernel.stdout }}", "kernel-devel", "elfutils-libelf-devel"]
state: latest # needed latest for dmks to find matching header
update_cache: yes
when: kernel is defined and kernel.stdout is defined

- name: Install elfutils
package:
name: "elfutils-libelf-devel"
when: ansible_os_family == "RedHat"

- name: Install necessary packages for compiling
package:
name: ["bzip2", "dkms", "gcc", "make"]
name:
- "bzip2"
- "dkms"
- "gcc"
- "make"
state: present

- name: Uninstall previous VBoxGuestAdditions
Expand All @@ -161,17 +197,27 @@
- name: Build and install x11 VBoxGuestAdditions from file
shell: /media/cdrom/VBoxLinuxAdditions.run
when: virtualbox_x11 is defined and virtualbox_x11
ignore_errors: yes
register: install_result
failed_when: install_result.rc != 0 and install_result.rc != 2

- name: Build and install VBoxGuestAdditions from file for Debians
- name: Build and install VBoxGuestAdditions from file
shell: /media/cdrom/VBoxLinuxAdditions.run --nox11
when: ( virtualbox_x11 is undefined or not virtualbox_x11 ) and ansible_os_family == "Debian"
ignore_errors: yes
when: virtualbox_x11 is undefined or not virtualbox_x11
register: install_result
failed_when: install_result.rc != 0 and install_result.rc != 2

- name: Build and install VBoxGuestAdditions from file for CentOSes
shell: /media/cdrom/VBoxLinuxAdditions.run --nox11
when: ( virtualbox_x11 is undefined or not virtualbox_x11 ) and ansible_os_family == "RedHat"
ignore_errors: yes
# VBoxLinuxAdditions.run returns status 2 when there was already running
# modules, and installer can't unload them (reboot required).
# Unfortunately, checksum errors return the same status 2.
# So, we also check if kernel module is actually built.

- name: Check if vboxguest.ko for running kernel is present
stat:
path: "/lib/modules/{{ kernel_version.stdout }}/misc/vboxguest.ko"
get_checksum: false
get_attributes: false
register: vboxguest_ko_path
failed_when: not vboxguest_ko_path.stat

- name: Unmount VBoxGuestAdditions
mount:
Expand All @@ -182,13 +228,8 @@
when: mounted_ISO is changed

- block:
- name: Check which packages were installed for Debians
shell: dpkg-query -l > /tmp/after.txt
when: ansible_os_family == "Debian"

- name: Check which packages were installed for CentOSes
shell: rpm -qa > /tmp/after.txt
when: ansible_os_family == "RedHat"
- name: Check which packages were installed
shell: "{{ package_list_command }} > /tmp/after.txt"

- name: Create a list of packages that were installed for compilation
shell: diff --ignore-all-space /tmp/before.txt /tmp/after.txt|awk '/>/{print $3}'
Expand Down Expand Up @@ -227,4 +268,9 @@
state=absent
when: mounted_ISO is changed

- name: Reboot to replace running modules
reboot:
when: install_result.rc == 2


when: (vbox_guest_version.stdout != virtualbox_version)