-
Notifications
You must be signed in to change notification settings - Fork 220
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Match the DHCP specification of last-wins leases #155
Conversation
Alright, tests pass - I think this might be mergable - but input on the direction we should be going is welcome |
@@ -91,7 +100,7 @@ def [] record | |||
end | |||
|
|||
def has_mac? mac | |||
records.each {|r| return r if r.mac == mac.downcase } | |||
records(:by_mac).each {|r| return r if r.mac == mac.downcase } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm what's the point of building the whole hash while we use it on this line only to iterate it. That's zero time saved and extra memory consumed. I must be missing something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you want to search it in O(1) rather than O(n) here :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In other words:
records(:by_mac)[mac.downcase]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm disregard the above, I see the point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For clarity to other reviewers: yeah, the issue is that the records hash is keyed on IP by default. That causes issues when you GET /dhcp/:network/:mac as the same IP might belong to two macs, and you'll only get one of them.
I considered altering the code to key on mac, but then you hit the same problem when you GET /dhcp/:network/:ip. So instead I re-index on the fly for mac-centric queries. It seems to work from my tests, but I'd appreciate confirmation from others.
Ok taking for testing together with theforeman/foreman#1430 in once. |
@lzap new version just been pushed - it turns out I was relying on implicit Hash sorting in ruby 1.9 which breaks on 1.8, so I've added explicit sorting of the records, to make sure we keep them in the order they were listed in the file. |
I've verified that this works in my environment in combination with the above mentioned foreman patch ( theforeman/foreman#1430 ) |
@lzap @mburns72h New extra commit added to handle the failure when deleting hosts - see the referenced Redmine issue for an explanation of why this is necessary. Please re-test and confirm |
Finally had time to finish my new discovery PR testing setup and reproduced: ERF12-4395 [ProxyAPI::ProxyException]: Unable to retrieve DHCP entry for 52:54:00:bf:fe:77 ([Net::LeaseConflict]: 52:54:00:bf:fe:77/192.168.100.14) for proxy https://foreman.virtual.lan:8443/dhcp Applying patches. Sorry for the delay. |
tested the update and it works as expected, hosts delete correctly |
Got this when testing:
And when I click on Refresh Facts, I get:
|
Hmmm so when I click on Refresh Facts, I get two requests:
I noticed the first one is missing the IP address. The discovered host has no facts with it. Not sure if this is different bug. Will investigate tomorrow. |
Ok got it, I was testing with 1.2 (old) discovery. I was able to reproduce the bug and then with both patches (this and theforeman/foreman#1430) it was working. +1 Good catch, work, report. Thanks guys. |
Looks sensible, but I'm concerned about the use of data structures inside the subnet and lack of tests for the first commit. |
@domcleal updated for your comments, thanks for the style cleanup |
@lzap can you retest? |
Ok testing now, please do not change the code anymore, only add more unit tests if needed :-) |
rescue | ||
nil | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm this could be in one block maybe? Or do I miss why is this in two?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
validate_mac and validate_ip return errors, so you need to rescue them individually, I think. Otherwise the raise in validate_mac will prevent the validate_ip check from running at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.load unless loaded? return has_mac?(record, type) if (validate_mac(record) rescue nil) return has_ip?(record, type) if (validate_ip(record) rescue nil)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thats a lot neater, done.
untested, looks fine |
I've just tested this. Provisioning do work, no conflicts at all. |
Merged as 2080b2e, ad2b465 for Foreman 1.5.1. Thanks @GregSutcliffe. |
Just sending this PR mainly to get the tests to run on Jenkins - I'm not entirely happy with it yet...
Discussion of the issue can be found here: http://projects.theforeman.org/issues/5648
This attempts to preserve the current proxy behaviour of indexing DHCP records by IP, and only re-indexes by mac (thus updating/removing duplicates) when specifically searching for a mac record.