ansible-collections / community.general

Ansible Community General Collection
https://galaxy.ansible.com/ui/repo/published/community/general/
GNU General Public License v3.0
812 stars 1.49k forks source link

[timezone] Fail to set timezone on chrooted Arch Linux #5663

Open C0rn3j opened 1 year ago

C0rn3j commented 1 year ago

Summary

Timezone fails if it's trying to run against chrooted Arch Linux.

- name: Set timezone to {{ timezone }}
  community.general.timezone:
    name: '{{ timezone }}'
tried to configure name using a file "/etc/sysconfig/clock", but could not write to it

In such configuration, timedatectl set-timezone will not work (due to the chroot), /etc/sysconfig/clock does not exist on Arch (nor does /etc/sysconfig) and /etc/localtime also does not exist on a fresh install.

The path that should be taken is the one that links /usr/share/zoneinfo/X/Y -> /etc/localtime, but for some reason it is not taken and the code is a bit hard to follow for me.

https://github.com/ansible-collections/community.general/blob/main/plugins/modules/timezone.py#L381

Issue Type

Bug Report

Component Name

timezone

Ansible Version

ansible [core 2.14.0]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/c0rn3j/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.10/site-packages/ansible
  ansible collection location = /home/c0rn3j/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.8 (main, Nov  1 2022, 14:18:21) [GCC 12.2.0] (/usr/bin/python)
  jinja version = 3.1.2
  libyaml = True

Community.general Version

$ ansible-galaxy collection list community.general
community.general 6.1.0  

Configuration

$ ansible-config dump --only-changed
CONFIG_FILE() = /etc/ansible/ansible.cfg

OS / Environment

Arch Linux

Steps to Reproduce

In Summary

Expected Results

Timezone gets set.

Actual Results

Error as per Summary

Code of Conduct

ansibullbot commented 1 year ago

Files identified in the description:

If these files are incorrect, please update the component name section of the description or use the !component bot command.

click here for bot help

ansibullbot commented 1 year ago

cc @indrajitr @jasperla @tmshn click here for bot help

mator commented 1 year ago

how do i run chroot archlinux?

C0rn3j commented 1 year ago

arch-chroot /path/to/arch/install

I suppose a light way would be to chroot into the bootstrap tarball and set it up.

https://wiki.archlinux.org/title/Install_Arch_Linux_from_existing_Linux#Method_A:_Using_the_bootstrap_tarball_(recommended)


Alternatively for a relatively simple VM setup that reproduces my case:

ISO - https://archlinux.org/download/

After booting the ISO in a UEFI VM:

curl https://gitlab.com/C0rn3j/arch/raw/master/install.sh -o i
chmod +x i
./i
> vda # device
> test # PC name
> test # root pass
> test # username
> test # user pass
> 8, 11, 1 # select my TZ
> 2 # no encryption
> 2 # no graphics
> 2 # no autologin
> 2 # wipe partitions

That should cause the fail (as it runs my playbook with the timezone task) and the system can be chrooted via arch-chroot /mnt/archinstall

One could also run archinstall from the ISO which launches a terminal installer, though am not actually too familiar with it.

I could also provide a SSH access to a VM that has the broken setup at the moment.

Sorry for complicated instructions, am sure there's some simpler way to do this but am not aware.

mator commented 1 year ago

unpacked archlinux-bootstrap-2022.12.01-x86_64.tar.gz to /s , chroot:

[root@archlinux mator]# tar -xf archlinux-bootstrap-2022.12.01-x86_64.tar.gz --numeric-owner -C /s
[root@archlinux mator]# arch-chroot /s/root.x86_64
[root@archlinux /]# date
Wed Dec  7 13:13:05 UTC 2022
[root@archlinux /]# timedatectl
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down

but if you do manual mount for "sys, proc and dev", as written at wiki.archlinux , then timedatectl does work, but operates on a parent (non-chroot) system, which is probably undesirable...

[root@archlinux mator]# cd /s/root.x86_64/
[root@archlinux root.x86_64]# mount --make-rslave --rbind /run run
[root@archlinux root.x86_64]# mount --make-rslave --rbind /sys sys
[root@archlinux root.x86_64]# mount --make-rslave --rbind /dev dev
[root@archlinux root.x86_64]# mount -t proc /proc proc
[root@archlinux root.x86_64]# cd ..
[root@archlinux s]# date
Wed Dec  7 16:24:21 MSK 2022
[root@archlinux s]# chroot root.x86_64/
[root@archlinux /]# date
Wed Dec  7 13:24:58 UTC 2022
[root@archlinux /]# timedatectl
               Local time: Wed 2022-12-07 16:25:12 MSK
           Universal time: Wed 2022-12-07 13:25:12 UTC
                 RTC time: Wed 2022-12-07 13:25:12
                Time zone: Europe/Moscow (MSK, +0300)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

so, I believe we need setup timezone not in a parent system, but chroot installed system, and it should be done via symlink, not via timedatectl...

Does someone knows how can we detect running in chroot environment? instead of my ugly hack of comparing count of lines in /proc/1/mountinfo and /proc/self/mountinfo

Wouterkoorn commented 1 year ago

Hi there, I would also like this fixed :)

I'm under the impression that a special clause for chroot is not what we need. We just need an extra elif block specific to Arch in this if-else statement: https://github.com/ansible-collections/community.general/blob/main/plugins/modules/timezone.py#L379

For Arch Linux, I think all this module should do, no matter if its chrooted or not, is the following:

Using the name parameter: run ln -sf /usr/share/zoneinfo/{name} /etc/localtime

if hwclock parameter is supplied: Write /etc/adjtime according to https://man.archlinux.org/man/hwclock.8#The_Adjtime_File

For hwclock: "UTC":

0.000000 0 0.000000
0
UTC

For hwclock: "local"

0.000000 0 0.000000
0
LOCAL

Finish by running hwclock --systohc on the end, no matter if hwclock was supplied or not. This will also update /etc/adjtime with most recent calibration time

russoz commented 1 year ago

Hi all, it does look more like a problem of how one's chroot is set up than a problem on the module itself IMO.

From https://docs.ansible.com/ansible/latest/collections/community/general/timezone_module.html

  • Several different tools are used depending on the OS/Distribution involved. For Linux it can use timedatectl or edit /etc/sysconfig/clock or /etc/timezone and hwclock. On SmartOS, sm-set-timezone, for macOS, systemsetup, for BSD, /etc/localtime is modified. On AIX, chtz is used.
  • Make sure that the zoneinfo files are installed with the appropriate OS package, like tzdata (usually always installed, when not using a minimal installation like Alpine Linux).

I would argue that the module should not be aware of whether it runs inside a chroot or not. It is already very complicated a module as it is, solving the timezone configuration in multiple different systems. I'd say if one wants to use this tool inside a chroot, then one is responsible for setting up the tooling and mounts and whatever else is required inside that chroot. Just my $0.02