Discovery Plugin / Capsule and DNS SRV Record
So I'm trying to get the SRV option working for identifying the capsule name for newly discovered hosts . Been hacking at it for a bit, and I know I'm close, but need to close this last gap./
Have the following for the SRV record
# cat /var/named/dynamic/db.example.com
$TTL 10800
@ IN SOA capsule.example.com. root.example.com. (
1 ;Serial
86400 ;Refresh
3600 ;Retry
604800 ;Expire
3600 ;Negative caching TTL
)
@ IN NS capsule.example.com.
capsule.example.com. IN A 192.168.250.2
_x-foreman._tcp SRV 0 5 9090 capsule.example.com.
And the following is returned when I query for it by the FQDN
# dig @192.168.250.2 srv _x-foreman._tcp
[root@capsule ~]# dig @192.168.250.2 srv _x-foreman._tcp.example.com
; <<>> DiG 9.9.4-RedHat-9.9.4-29.el7_2.3 <<>> @192.168.250.2 srv _x-foreman._tcp.example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41900
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;_x-foreman._tcp.example.com. IN SRV
;; ANSWER SECTION:
_x-foreman._tcp.example.com. 10800 IN SRV 0 5 9090 capsule.example.com.
;; AUTHORITY SECTION:
example.com. 10800 IN NS capsule.example.com.
;; ADDITIONAL SECTION:
capsule.example.com. 10800 IN A 192.168.250.2
;; Query time: 0 msec
;; SERVER: 192.168.250.2#53(192.168.250.2)
;; WHEN: Tue Aug 09 14:17:02 EDT 2016
;; MSG SIZE rcvd: 132
But the capsule won't retrieve the record when it boots and pulls DHCP / DNS information.
The APPEND Line is as follows:
APPEND initrd=boot/fdi-image-rhel_7-img rootflags=loop root=live:/fdi.iso rootfstype=auto ro rd.live.image acpi=force rd.luks=0 rd.md=0 rd.dm=0 rd.lvm=0 rd.bootif=0 rd.neednet=0 nomodeset proxy.type=proxy
The documentation seems to contradict itself, or its incorrect and should read "The proxy.type variable must be set to proxy in this case":
As an alternative to the above procedure, you can omit the proxy.url variable from the PXE-boot template. In this case, the Discovery image searches the DNS configuration file for an SRV record named x-foreman.tcp. The proxy.url variable must be set to proxy in this case. The DNS server must also be suitably configured. For example, the following configuration statement specifies the Capsule to be used with HTTPS:
On the client side I've got the following as the only real error message:
"Could not determine instance type, add foreman.url or proxy.url kernel...."
Anything glaringly obvious to anyone? Thanks!
Responses
Hello Will!
I have doublechecked our code and it should really work with both types, you just need to specify it:
https://github.com/theforeman/foreman-discovery-image/blob/eac3d6d424eb9bdebc1d35116c47623c7e649eb7/root/usr/lib64/ruby/vendor_ruby/discovery.rb#L127-L143
I will fix our documentation there. The error message you see is because SRV was not fetched properly. It is not obvious from your second comment if you were able to get it working or not, but it should work.
Edit: It looks like our docs is correct: https://theforeman.org/plugins/foreman_discovery/6.0/index.html#3.1.1DefaultPXEtemplate Note in downstream we do not recommend to use "foreman" (direct) connection at all and Satellite 6 comes preinstalled with Tempates proxy feature. For this reason, our documentation team prefer to be more strict on this.
You should be able to handle this via DNS Views, which allow you to return different records based upon the querying host.
I have stumbled across the same problem. I had followed the same approach as Will and added the _x-foreman._tcp to the corresponding zone (in this thread its example.com).
Testing with dig and including the fqdn for the service works. Again, as Will has shown. However, the code snippet from shows that the SRV lookup doesn't include the domain name.
result = resolver.getresources("_x-foreman._tcp", type).first
I was assuming that the lookup would have been restricted to the current domain. I'm not a fan of Will's hack either, although it is effective, its also all kinds of wrong. Having to add entries in for a host (capsule.example.com) is wrong In regards to DNS views, I haven't looked at that. My preference is to keep the DNS configuration as simple as possible.
Can the code perform a resource lookup with "_x-foreman._tcp" + domainName, then fall back to the currrent code if no result is found?
Another problem I've found is that the code will only use HTTPS on fixed ports, 443,8443 or 9090. Would be good if there was a proxy.protocol parameter that allowed this to be controlled on the initrd line.
Hello, I created a ticket:
http://projects.theforeman.org/issues/16419
and a patch for upstream:
https://github.com/theforeman/foreman-discovery-image/pull/78
I also made a FDI scratchbuild with this patch:
http://downloads.theforeman.org/discovery/lzap/scratch/
Could you test it please if it works? It adds new parameter 'fdi.srv.scheme' - set it to https or http accordingly.
Hi Givaldo and others,
Firstly, thanks Lukas for the quick response earlier and apologies for the lack of response. I was pulled (or diverted) to another project and this got moth balled.
I'm now working on the discovery functionality again, and I have worked out why the "." zone works, and why the FDI doesn't work.
In short, NetworkManager defaults the /etc/resolv.conf in the FDI to not having an options entry, resulting in the search domains not being appended. By adding options ndots:5 to the file it all works. The FDI image needs to do this in a NetworkManager friendly way.
[root@fdi ~]# cat /etc/resolv.conf
# Generated by NetworkManager
search sandbox.net
nameserver 10.245.2.3
This means that ndots is defaulting to 1, which means that the domains in the search path are not used.
Taking the snippet of discovery code, and adding the config output line, the ndots=>1 can be seen and the lookup failed:
irb(main):001:0> require 'resolv'
=> true
irb(main):002:0> resolver = Resolv::DNS.new
=> #<Resolv::DNS:0x000000019d79d8 @mutex=#<Mutex:0x000000019d79b0>, @config=#<Resolv::DNS::Config:0x000000019d7988 @mutex=#<Mutex:0x000000019d7960>, @config_info=nil, @initialized=nil, @timeouts=nil>, @initialized=nil>
irb(main):003:0> Resolv::DNS::Config.default_config_hash
=> {:nameserver=>["10.245.2.3"], :search=>["sandbox.net"], :ndots=>1}
irb(main):004:0> type = Resolv::DNS::Resource::IN::SRV
=> Resolv::DNS::Resource::IN::SRV
irb(main):005:0> result = resolver.getresources("_x-foreman._tcp", type)
=> []
irb(main):006:0> quit
Udating the /etc/resolv.conf with options ndots:5 and rerunning:
echo "options ndots:5" >> /etc/resolv.conf
[root@fdi ~]# irb
irb(main):001:0> require 'resolv'
=> true
irb(main):002:0> resolver = Resolv::DNS.new
=> #<Resolv::DNS:0x00000002b7bef0 @mutex=#<Mutex:0x00000002b7bec8>, @config=#<Resolv::DNS::Config:0x00000002b7bea0 @mutex=#<Mutex:0x00000002b7be78>, @config_info=nil, @initialized=nil, @timeouts=nil>, @initialized=nil>
irb(main):003:0> Resolv::DNS::Config.default_config_hash
=> {:nameserver=>["10.245.2.3"], :search=>["sandbox.net"], :ndots=>5}
irb(main):004:0> type = Resolv::DNS::Resource::IN::SRV
=> Resolv::DNS::Resource::IN::SRV
irb(main):005:0> result = resolver.getresources("_x-foreman._tcp", type)
=> [#<Resolv::DNS::Resource::IN::SRV:0x00000002b8cd40 @priority=0, @weight=5, @port=9090, @target=#<Resolv::DNS::Name: capsule.sandbox.net.>, @ttl=10800>]
irb(main):006:0> quit
Looking at the FDI image, the /etc/sysconfig/network-scripts/network-functions will preserve the options line:
network-functions: s=$(/bin/grep '^[\ \ ]*option' /etc/resolv.conf 2>/dev/null);
network-functions: (echo "$s" > /etc/resolv.conf;) >/dev/null 2>&1;
IMO using grep for string matches isn't a good idea, but it works.
My experience with NetworkManager is limited and many people have similar issues based on various forums. Using nmcli can set the value, but for FDI the device name can change based on the host itself. Something like the following should suffice for FDI:
for device in `nmcli -f device -t d s`; do test "lo" != "$device" && nmcli d modify $device +ipv4.dns-options ndots:5; done
I have tested this by enabling SSH on the host being disocvered, ran the command, and then click RESEND.
The other, possibly easier option is to modify the discovery code to add the ndots:5 option to the config. There is no science behind the choice of 5 btw.
[root@fdi ~]# irb
irb(main):001:0> require 'resolv'
=> true
irb(main):002:0> resolv_conf = Resolv::DNS::Config.default_config_hash
=> {:nameserver=>["10.245.2.3"], :search=>["sandbox.net"], :ndots=>1}
irb(main):003:0> # output the new values
irb(main):004:0* resolv_conf
=> {:nameserver=>["10.245.2.3"], :search=>["sandbox.net"], :ndots=>1}
irb(main):005:0> resolv_conf[:ndots] = 5 unless resolv_conf[:ndots] > 1
=> 5
irb(main):006:0> resolver = Resolv::DNS.new(resolv_conf)
=> #<Resolv::DNS:0x00000001a9fed8 @mutex=#<Mutex:0x00000001a9feb0>, @config=#<Resolv::DNS::Config:0x00000001a9fe88 @mutex=#<Mutex:0x00000001a9fe60>, @config_info={:nameserver=>["10.245.2.3"], :search=>["sandbox.net"], :ndots=>5}, @initialized=nil, @timeouts=nil>, @initialized=nil>
irb(main):007:0> #Note, this is outputing the value from /etc/resolv.conf
irb(main):008:0* Resolv::DNS::Config.default_config_hash
=> {:nameserver=>["10.245.2.3"], :search=>["sandbox.net"], :ndots=>1}
irb(main):009:0> type = Resolv::DNS::Resource::IN::SRV
=> Resolv::DNS::Resource::IN::SRV
irb(main):010:0> result = resolver.getresources("_x-foreman._tcp", type)
=> [#<Resolv::DNS::Resource::IN::SRV:0x00000001ab5be8 @priority=0, @weight=5, @port=9090, @target=#<Resolv::DNS::Name: capsule.sandbox.net.>, @ttl=10800>]
irb(main):011:0> quit
The actual code change for discovery.rb would be:
resolv_conf = Resolv::DNS::Config.default_config_hash
resolv_conf[:ndots] = 5 unless resolv_conf[:ndots] > 1
resolver = Resolv::DNS.new(resolv_conf)
As a reference for others, I stumbled across https://unix.stackexchange.com/questions/318649/purpose-of-ipv4-dns-option-in-nmcli which pointed me in the right direction.
Welcome! Check out the Getting Started with Red Hat page for quick tours and guides for common tasks.
