Commit b1acdb0a authored by Jérome Perrin's avatar Jérome Perrin

component/userhosts: use github.com/figiel/hosts for compatibility with recent libc

In ubuntu 21.04 (libc6 2.33-0ubuntu5) or current debian testing
(libc6 2.32-5) no longer use open to open /etc/hosts, but what appears
as "openat" in strace output - but can not be replaced by defining an
openat function.

This uses https://github.com/figiel/hosts which uses another approach
of replacing getaddrinfo, gethostbyname* and inet_aton.

Users have been updated a bit, because there are some small differences:
 - the /etc/hosts replacement file is defined by HOSTS_FILE environment
   variable, not HOSTS
 - the library name is libuserhosts.so, not userhosts.so

Other notable differences, for which we did not need code change are:
 - the new library also try to load a file when HOSTS_FILE is not set
 - the new library still use original /etc/hosts file
 - the new library supports aliases to hostnames, not only ip addresses
parent e0262aaf
Pipeline #19234 failed with stage
[userhosts] [userhosts]
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
shared = true shared = true
url = https://lab.nexedi.com/nexedi/userhosts/repository/${:revision}/archive.tar.gz url = https://github.com/figiel/hosts/archive/${:revision}.tar.gz
revision = a05fe5a3a5cb7005351ef4ec41460089f3ce4d0a revision = fdb45fe219593d63453f4be55cfc2a1199c18f59
md5sum = 5a80b4d962d975f290a60cf790c3334d md5sum = 9ff5407132a2a67200ef1036a02f0ee2
configure-command = true configure-command = true
make-options = PREFIX=@@LOCATION@@ make-options = PREFIX=@@LOCATION@@
make-targets = check install make-targets = test install
...@@ -15,4 +15,4 @@ ...@@ -15,4 +15,4 @@
[template] [template]
filename = instance.cfg filename = instance.cfg
md5sum = 597c29546519aabe7259e416d0b92095 md5sum = ba6c572678687081ce111d3805be3cee
...@@ -35,10 +35,10 @@ repository = ${caucase-repository:location} ...@@ -35,10 +35,10 @@ repository = ${caucase-repository:location}
[caucase-test-runner] [caucase-test-runner]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
template = inline:#!/bin/sh template = inline:#!/bin/sh
export HOSTS="$(mktemp)" export HOSTS_FILE="$(mktemp)"
trap 'rm "$HOSTS"' EXIT trap 'rm "$HOSTS_FILE"' EXIT
printf '%s testhost\n%s testhost\n' "$SLAPOS_TEST_IPV4" "$SLAPOS_TEST_IPV6" > "$HOSTS" printf '%s testhost\n%s testhost\n' "$SLAPOS_TEST_IPV4" "$SLAPOS_TEST_IPV6" > "$HOSTS_FILE"
export CAUCASE_NETLOC=testhost:8000 LD_PRELOAD=${userhosts:location}/lib/userhosts.so:$LD_PRELOAD export CAUCASE_NETLOC=testhost:8000 LD_PRELOAD=${userhosts:location}/lib/libuserhosts.so:$LD_PRELOAD
exec python -m unittest discover -v exec python -m unittest discover -v
rendered = $${caucase:location}/host_setting.sh rendered = $${caucase:location}/host_setting.sh
......
...@@ -70,7 +70,7 @@ md5sum = 7a14019abf48ca100eb94d9add20f5ae ...@@ -70,7 +70,7 @@ md5sum = 7a14019abf48ca100eb94d9add20f5ae
[template] [template]
filename = instance.cfg.in filename = instance.cfg.in
md5sum = bbef65b4edeb342f08309604ca3717d5 md5sum = 0444d646607f8643e987bb62d1cbbc1d
[template-erp5] [template-erp5]
filename = instance-erp5.cfg.in filename = instance-erp5.cfg.in
...@@ -86,7 +86,7 @@ md5sum = bc821f9f9696953b10a03ad7b59a1936 ...@@ -86,7 +86,7 @@ md5sum = bc821f9f9696953b10a03ad7b59a1936
[template-zope] [template-zope]
filename = instance-zope.cfg.in filename = instance-zope.cfg.in
md5sum = f3121380ab4d31ba5f4984aec74d0a2f md5sum = 09895deebca3206425fada3caf1d92cf
[template-balancer] [template-balancer]
filename = instance-balancer.cfg.in filename = instance-balancer.cfg.in
......
...@@ -185,7 +185,7 @@ context = key host_dict hosts-parameter:host-dict ...@@ -185,7 +185,7 @@ context = key host_dict hosts-parameter:host-dict
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
mode = 755 mode = 755
template = inline:#!{{ parameter_dict['dash'] }}/bin/dash template = inline:#!{{ parameter_dict['dash'] }}/bin/dash
export HOSTS=${hosts:rendered} export HOSTS_FILE=${hosts:rendered}
export LD_PRELOAD={{ parameter_dict['userhosts'] }}:$LD_PRELOAD export LD_PRELOAD={{ parameter_dict['userhosts'] }}:$LD_PRELOAD
exec "$@" exec "$@"
rendered = ${directory:bin}/userhosts rendered = ${directory:bin}/userhosts
......
...@@ -110,7 +110,7 @@ link-binary = {{ dumps(zope_link_binary) }} ...@@ -110,7 +110,7 @@ link-binary = {{ dumps(zope_link_binary) }}
fonts = {{ dumps(zope_fonts) }} fonts = {{ dumps(zope_fonts) }}
fontconfig-includes = {{ dumps(zope_fontconfig_includes) }} fontconfig-includes = {{ dumps(zope_fontconfig_includes) }}
template-fonts-conf = {{ dumps(template_fonts_conf) }} template-fonts-conf = {{ dumps(template_fonts_conf) }}
userhosts = {{ userhosts_location }}/lib/userhosts.so userhosts = {{ userhosts_location }}/lib/libuserhosts.so
site-zcml = {{ site_zcml }} site-zcml = {{ site_zcml }}
extra-path-list = {{ dumps(extra_path_list) }} extra-path-list = {{ dumps(extra_path_list) }}
matplotlibrc = {{ matplotlibrc_location }} matplotlibrc = {{ matplotlibrc_location }}
......
  • I just noticed now, but unlike the previous userhost, this does not support the scenario on which caucase test relies on, which causes a test to be skipped (see test result):

    testHttpNetlocIPv6 (caucase.test.CaucaseTest) ... skipped "Cannot resolve 'testhost' as AF_INET6"

    This caucase test uses a host file like this

    127.0.0.1 testhost
    ::1 testhost

    but the approach in https://github.com/figiel/hosts/blob/fdb45fe219593d63453f4be55cfc2a1199c18f59/userhosts.c is to hook system calls like

           int getaddrinfo(const char *restrict node,
                           const char *restrict service,
                           const struct addrinfo *restrict hints,
                           struct addrinfo **restrict res);

    and, lookup the node from the first matching line in the hosts file:

    127.0.0.1 testhost     <--
    ::1 testhost

    and call the original method with the alias.

    With this example file, when called with

    getaddrinfo("testhost", service, hints, res)

    the "real" getaddrinfo will be called with the resolved value:

    getaddrinfo("127.0.0.1", service, hints, res)

    I don't see how this could easily support names with both IPv4 and IPv6 addresses like this with this approach.

    In this caucase test, it's used like this https://lab.nexedi.com/nexedi/caucase/blob/0d663926441f7be6413745f89b1d8756824bbb05/caucase/test.py#L3528-3532 so hints argument will contain AF_INET6 , we could add support for this exact case, but that seems nonsense because we won't be able to fully support a host files like that: with AF_UNSPEC it should return both 127.0.0.1 and ::1, which seems impossible with this approach.

    For now, we can say that such a hosts file is not supported by https://github.com/figiel/hosts/ and I don't know how we could make this test run again.

    This use case does not seem critically important, we use this only in caucase test and in ERP5. In ERP5 we are only using IPv4 so the problem is only in caucase test, maybe there's a way to change the caucase test to use another approach.

  • mentioned in merge request !1074 (merged)

    Toggle commit list
  • I don't see how this could easily support names with both IPv4 and IPv6 addresses like this with this approach.

    +1

    This is a bug in userhosts.c, and not immediately trivial to fix.

    This use case does not seem critically important, we use this only in caucase test and in ERP5. In ERP5 we are only using IPv4 so the problem is only in caucase test, maybe there's a way to change the caucase test to use another approach.

    The plain caucased software release (which I rely on) makes caucased listen on IPv6, so having this test skipped is not ideal.

Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment