sl12
July 15, 2020, 6:14pm
#1
I try to develop a new DHCP plugin.
At the find_record_by_mac function I have the following line:
return Proxy::DHCP::Record.new(ipaddress, mac_address,Proxy::DHCP::Subnet.new(subnet_address,"255.255.255.0"))
When I call “/unattended/built?token=xxx” I get the following error in the log:
proxy.log:
2020-07-15T20:02:28 d784b476 [I] Finished GET /dhcp/192.168.2.0/mac/56:6f:5f:b7:00:05 with 200 (261.72 ms)
production.log
2020-07-15T20:02:28 [W|app|d784b476] ProxyAPI operation FAILED
2020-07-15T20:02:28 [D|app|d784b476] Backtrace for 'ProxyAPI operation FAILED' error (ProxyAPI::ProxyException): ERF12-4395 [ProxyAPI::ProxyException]: DHCP-Eintrag für 56:6f:5f:b7:00:05 konnte nicht abgerufen werden ([NoMethodError]: undefined method `merge' for "192.168.2.60 / 56:6f:5f:b7:00:05":String) für Proxy https://theforeman.tkv.int:8443/dhcp
/usr/share/foreman/lib/proxy_api/dhcp.rb:56:in `rescue in record'
/usr/share/foreman/lib/proxy_api/dhcp.rb:45:in `record'
/usr/share/foreman/lib/net/dhcp/record.rb:57:in `conflicts'
...
Any idea how to solve this error ?
1 Like
ekohl
July 16, 2020, 11:59am
#2
I took the liberty to edit your post to add some code tags.
This suggests that it’s calling merge()
on a String
, but typically that’s called on a Hash
.
I wonder what the JSON returned by the proxy is. Can you share that?
1 Like
sl12
July 16, 2020, 6:27pm
#3
If I call the proxy with curl http://theforeman:8000/dhcp/192.168.2.0/mac/56:6f:5f:b7:00:03
I get the following string:
“192.168.2.60 / 56:6f:5f:b7:00:03”
Do I need to return something different in the find_record_by_mac function to get an JSON output ?
ekohl
July 17, 2020, 10:20am
#4
The code in between isn’t very strict in what it sends back which makes it easy to create an invalid API response:
Sadly, the API is barely specified and the specific API isn’t even mentioned on API - Smart Proxy - Foreman
Digging in the source, it appears the data types have the json serialization defined:
def to_json(*opts)
Hash[[:name, :ip, :mac, :subnet, :type].map { |s| [s, send(s)] }].merge(options).to_json(*opts)
end
def to_json(*opts)
Hash[[:name, :ip, :mac, :subnet, :starts, :ends, :state, :type].map { |s| [s, send(s)] }].merge(options).to_json(*opts)
end
So it’s recommended to use these data structures and return them instead of the raw Proxy::DHCP::Record
. Also note how both reservation and lease extend `Record.
lzap
July 17, 2020, 12:11pm
#5
Yeah, you need to explicitly call to_json
otherwise the object is converted to String via its to_s
implementation, which in this case returns IP / MAC
.
ekohl
July 17, 2020, 12:47pm
#6
No, this is wrong. The DHCP API already calls to_json
but you are calling Proxy::DHCP::Record
. This class has no to_json
defined so it falls back to to_s
.
sl12
July 18, 2020, 10:28am
#7
thanks.
using Proxy::DHCP::Reservation
in find_record_by_mac
did fix the problem.
ekohl
July 18, 2020, 2:07pm
#8
Out of interest, which DHCP server are you talking to? Any chance it will be relevant for others and you’ll open source it?
2 Likes
sl12
July 18, 2020, 2:58pm
#9
Univention Corporate Server (UCS) and yes I will publish it on github.
1 Like