cobbler / cobbler

Cobbler is a versatile Linux deployment server
https://cobbler.github.io
GNU General Public License v2.0
2.6k stars 653 forks source link

Cobbler sync error when distro kernel value is an HTTP url without an IP address #3664

Open rdswett opened 6 months ago

rdswett commented 6 months ago

Describe the bug

Generating a grub boot menu with a kernel set to an http path with a hostname causes an error.

When updating to version 3.3.4 from 3.3.3, cobbler sync started throwing errors about invalid remote file formats, and will no longer generate a grub menu if the kernel value of a defined distro is set to an http URL with a hostname instead of an IP address. A hostname is valid in grub, assuming your DHCP server provides a nameserver to the client.

This seems intentional as parse_grub_remote_file in grub.py uses netaddr.valid_ipv4() and valid_ipv6().

Steps to reproduce

  1. Define a distro
  2. set kernel to some HTTP url with a hostname
  3. run cobbler sync, and see the failure "Invalid remote file format "

Expected behavior

Cobbler sync should work and a valid grub menu should be produced and made available for PXE clients

Cobbler version

Cobbler 3.3.4 source: ?, ? build time: Mon Feb 26 00:00:00 2024

This is the version from EPEL for el9

Operating system

Rocky 9

Cobbler log

The system is air gapped from the network but the stack trace in cobbler.log is essentially:

tftpgen.py line 640 tftpgen.py line 778 grub.py line 33 Raises ValueError("Invalid remote file format %s\n is not a valid IP address" % (file_location, server))

Screenshots

N/A

Additional information

In this environment we locally mirror Rocky 9 repos and host them with an Apache HTTP server that uses a virtual host to serve out repos. This HTTP server has several functions and due to the way httpd configs are loaded, putting an IP address in the cobbler config doesn't work. There are, of course, work arounds to get the repos served off the IP address but this seems like a regression as it was working with the most previous version of cobbler and broke when we updated to 3.3.4

SchoolGuy commented 5 months ago

The line in grub.py you are addressing is present as of 3.3.0. The file was last changed three years ago. As such it is unlikely that this is caused by an upgrade from 3.3.3 to 3.3.4.

rdswett commented 5 months ago

I think the change that is causing the issue is in tftpgen.py on line 777, which was introduced in a pull request a few months ago. In 3.3.3 the kernel path was just taken as is, and in 3.3.4 an additional check was added and the call to the parse_grub_remote_file function.

SchoolGuy commented 5 months ago

@rdswett it would be cool if you could link the PR. In any case I will see what I can do about your bug in the coming weeks.

rdswett commented 5 months ago

Git claims it is this one https://github.com/cobbler/cobbler/pull/3477, thanks for looking into it!

SchoolGuy commented 5 months ago

@tpw56j if you have the time I would be thrilled if you could take a look at this bug.

tpw56j commented 5 months ago

I tested.

# cobbler distro add --name=distro_test1 --remote-boot-kernel='http://192.168.0.2/vmlinuz' \
--remote-boot-initrd='http://192.168.0.2/initrd.img' --breed=redhat --os-version=rhel9
# cobbler distro report --name=distro_test1
Name                           : distro_test1
Architecture                   : x86_64
Automatic Installation Template Metadata : {}
TFTP Boot Files                : {}
Boot loaders                   : <<inherit>>
Breed                          : redhat
Comment                        : 
Fetchable Files                : {}
Initrd                         : 
Kernel                         : 
Kernel Options                 : {}
Kernel Options (Post Install)  : {}
OS Version                     : rhel9
Owners                         : <<inherit>>
Redhat Management Key          : <<inherit>>
Remote Boot Initrd             : http://192.168.0.2/initrd.img
Remote Boot Kernel             : http://192.168.0.2/vmlinuz
Template Files                 : {}

# cobbler profile add --name=profile_test1 --distro=distro_test1

Correct grub menu with loading via http:

menuentry 'profile_test1' --class gnu-linux --class gnu --class os {
  echo 'Loading kernel ...'
  clinux (http,192.168.0.2)/vmlinuz   inst.ks.sendmac inst.ks=http://192.168.122.1/cblr/svc/op/autoinstall/profile/profile_test1
  echo 'Loading initial ramdisk ...'
  cinitrd (http,192.168.0.2)/initrd.img
  echo '...done'
}

But using the hostname does result in an error:

 cobbler distro add --name=distro_test2 --remote-boot-kernel='http://www.example.com/vmlinuz' \
--remote-boot-initrd='http://192.168.0.2/initrd.img' --breed=redhat --os-version=rhel9
exception on server: Invalid remote file format http://www.example.com/vmlinuz
www.example.com is not a valid IP address

  File "/usr/lib/python3.12/site-packages/cobbler/remote.py", line 3928, in _dispatch
    return method_handle(*params)
           ^^^^^^^^^^^^^^^^^^^^^^

  File "/usr/lib/python3.12/site-packages/cobbler/remote.py", line 2135, in xapi_object_edit
    self.modify_item(object_type, handle, key, value, token)  # type: ignore
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "/usr/lib/python3.12/site-packages/cobbler/remote.py", line 1862, in modify_item
    setattr(obj, attribute, arg)

  File "/usr/lib/python3.12/site-packages/cobbler/items/item.py", line 371, in __setattr__
    super().__setattr__(name, value)

  File "/usr/lib/python3.12/site-packages/cobbler/items/distro.py", line 312, in remote_boot_kernel
    parsed_url = grub.parse_grub_remote_file(remote_boot_kernel)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "/usr/lib/python3.12/site-packages/cobbler/grub.py", line 41, in parse_grub_remote_file
    raise ValueError(

Maybe we should remove the IP address check in grub.py?

SchoolGuy commented 5 months ago

Hm... I am not 100% sure if that is the right way as we rebuild the URL for remote boot purposes. As such having a valid hostname or IP is desirable in my eyes.