Bug 2110066

Summary: DNS integration with OpenStack/cloud-init/NetworkManager is not working
Product: Red Hat Enterprise Linux 8 Reporter: Igor Raits <igor.raits>
Component: cloud-initAssignee: Virtualization Maintenance <virt-maint>
Status: CLOSED ERRATA QA Contact: xiachen
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: CentOS StreamCC: bstinson, eesposit, eterrell, huzhao, igor.raits, jaroslav.pulchart, jgreguske, jwboyer, lkundrak, lrintel, xiachen, xiliang, yacao
Target Milestone: rcKeywords: Triaged
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: cloud-init-22.1-5.el8 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2022-11-08 09:32:17 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
network_data.json
none
target/etc/NetworkManager/system-connections/cloud-init-eth0.nmconnection none

Description Igor Raits 2022-07-23 06:46:49 UTC
Created attachment 1898875 [details]
network_data.json

Description of problem:
After last update of the cloud-init, DNS servers injected by the OpenStack are ignored and not written into resolv.conf (neither stored in the NetworkManager).

See the network_data.json for the extract from the VM (attached as a file).
# python3 /usr/lib/python3.6/site-packages/cloudinit/cmd/devel/net_convert.py -p  /mnt/openstack/latest/network_data.json -k network_data.json -d target -O network-manager -D centos

This command above produces valid nmconnection files but they are missing the DNS settings and no resolv.conf is generated in the target directory.

Version-Release number of selected component (if applicable):
cloud-init-22.1-3.el8.noarch

How reproducible:
Always.

Steps to Reproduce:
1. Configure OpenStack to inject IP and DNS from the subnet
2. Prepare image with latest cloud-init
3. Deploy the VM and check what's configured by cloud-init

Actual results:
No DNS servers are configured.

Expected results:
DNS servers are set according to the network_data.json provided by the OpenStack.

Additional info:
I've attached some files, will be happy to test any patches if needed.

Comment 1 Igor Raits 2022-07-23 06:47:22 UTC
Created attachment 1898876 [details]
target/etc/NetworkManager/system-connections/cloud-init-eth0.nmconnection

Comment 2 Igor Raits 2022-07-23 06:57:15 UTC
@lrintel @lkundrak any chance you would have few minutes to look on this issue (as an author of the NM integration patches)?

Thanks a lot in advance!

Comment 3 xiachen 2022-07-25 06:54:49 UTC
@igor.raits

Thank you for reporting this bug, could you upload cloud-init.log and resolv.conf to this bug please?

Comment 4 xiachen 2022-07-25 08:26:42 UTC
After Bug 2059872 fix (cloud-init-22.1-2.el8), /etc/resolv.conf is handled by NetworkManager, not cloud-init.

I tested on openstack with cloud-init-22.1-3.el8.noarch,/etc/resolv.conf would be updated with dns information by NetworkManger in 28 mins after cloud-init run done.

At the beginning, I got that no dns in /etc/resolv.conf as the bug description.
ls -l /etc/resolv.conf
-rw-r--r--. 1 root root 30 Jul 25 03:42  /etc/resolv.conf
cat /etc/resolv.conf
#Generated by NetworkManager

but 28mins later, the dns information is updated into /etc/resolv.conf and also shown by nmcli command.

ls -l /etc/resolv.conf 
-rw-r--r--. 1 root root 51 Jul 25 04:10 /etc/resolv.conf
cat /etc/resolv.conf 
# Generated by NetworkManager
nameserver 10.2.32.1

nmcli conn show "cloud-init eth0"
IP4.DNS[1]:                             10.2.32.1

Comment 5 Igor Raits 2022-07-25 10:48:43 UTC
Hi,

I will get cloud-init.log later today but resolv.conf is very simple - it is completely empty :)
I think you don't even need cloud-init.log because in the code of cloud-init you can see it uses only dns_nameservers field to prepare DNS servers in which case it is empty in my network_data.json where there is another way how OpenStack specifies the nameservers.

Comment 6 xiachen 2022-07-27 06:39:58 UTC
@igor.raits

Yes, I agree with you that the code cloudinit/net/network_manager.py does not handle the OpenStack specifies type 'nameserver', it uses only dns_nameservers and dns_search.

Could you check that if resolv.conf be updated in a couple of minutes after first boot?
On my openstack env, it would take 6mins~28mins, the dns information would be updated into resolv.conf by NM, depending on the network environment. 
As I mentioned in comment#4, now resolv.conf is handled by NetworkManager not Cloud-init. I don't know why it takes a long time when getting the dns information.

@lkundrak @Emanuele @Eduardo
Can you help to check this issue please? Should dns be handled by cloud-init as before(sysconfig) or be handled by NM totally?

thanks
Amy


(In reply to Igor Raits from comment #5)
> Hi,
> 
> I will get cloud-init.log later today but resolv.conf is very simple - it is
> completely empty :)
> I think you don't even need cloud-init.log because in the code of cloud-init
> you can see it uses only dns_nameservers field to prepare DNS servers in
> which case it is empty in my network_data.json where there is another way
> how OpenStack specifies the nameservers.

Comment 7 Eduardo Otubo 2022-08-09 11:52:30 UTC
(In reply to xiachen from comment #6)
> @igor.raits
> 
> Yes, I agree with you that the code cloudinit/net/network_manager.py does
> not handle the OpenStack specifies type 'nameserver', it uses only
> dns_nameservers and dns_search.
> 
> Could you check that if resolv.conf be updated in a couple of minutes after
> first boot?
> On my openstack env, it would take 6mins~28mins, the dns information would
> be updated into resolv.conf by NM, depending on the network environment. 
> As I mentioned in comment#4, now resolv.conf is handled by NetworkManager
> not Cloud-init. I don't know why it takes a long time when getting the dns
> information.
> 
> @lkundrak @Emanuele @Eduardo
> Can you help to check this issue please? Should dns be handled by cloud-init
> as before(sysconfig) or be handled by NM totally?
> 
> thanks
> Amy
> 
> 
> (In reply to Igor Raits from comment #5)
> > Hi,
> > 
> > I will get cloud-init.log later today but resolv.conf is very simple - it is
> > completely empty :)
> > I think you don't even need cloud-init.log because in the code of cloud-init
> > you can see it uses only dns_nameservers field to prepare DNS servers in
> > which case it is empty in my network_data.json where there is another way
> > how OpenStack specifies the nameservers.

@xiachen before answering that question, can you confirm this is a regression caused by NM patches?

@igor.raits what kind of DNS information comes in your json data? Can you share that and the cloud-init logs? Thanks!

Comment 9 xiachen 2022-08-10 06:55:07 UTC
@Eduardo,

yes, it caused by NM patches. Because of NM patches, on openstack, below codes in sysconfig.py don't work as before. 
network_data.json

https://github.com/canonical/cloud-init/blob/main/cloudinit/net/sysconfig.py

    @staticmethod
    def _render_dns(network_state, existing_dns_path=None):
        # skip writing resolv.conf if network_state doesn't include any input.
        if not any(
            [
                len(network_state.dns_nameservers),
                len(network_state.dns_searchdomains),
            ]
        ):
            return None
        content = resolv_conf.ResolvConf("")
        if existing_dns_path and os.path.isfile(existing_dns_path):
            content = resolv_conf.ResolvConf(util.load_file(existing_dns_path))
        for nameserver in network_state.dns_nameservers:
            content.add_nameserver(nameserver)
        for searchdomain in network_state.dns_searchdomains:
            content.add_search_domain(searchdomain)
        header = _make_header(";")
        content_str = str(content)
        if not content_str.startswith(header):
            content_str = header + "\n" + content_str
        return content_str

    @staticmethod
    def _render_networkmanager_conf(network_state, templates=None):
        content = networkmanager_conf.NetworkManagerConf("")

        # If DNS server information is provided, configure
        # NetworkManager to not manage dns, so that /etc/resolv.conf
        # does not get clobbered.
        if network_state.dns_nameservers:
            content.set_section_keypair("main", "dns", "none")

        if len(content) == 0:
            return None
        out = "".join([_make_header(), "\n", "\n".join(content.write()), "\n"])
        return out


you can see network_data.json attached in bug description.

Comment 16 xiachen 2022-08-19 14:35:05 UTC
Test cloud-init-22.1-5.el8, PASS
move to VERIFIED.

Comment 18 errata-xmlrpc 2022-11-08 09:32:17 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory (cloud-init bug fix and enhancement update), and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2022:7523