Not a solution per say, but a reasonable work around. Call the attached
script in a frequent cron job.
On Monday, August 15, 2016 at 11:02:50 AM UTC-5, Alvin Starr wrote:
>
> I have looked at this a bit more and your right.
> Its hard to believe that the ISC develpers would be that short sighted to
> not extend the design so that changes made to the primary are copied to the
> secondary.
>
> I can see 3 possible solutions.
> 1) fix the ISC DHCP server.
> Fixing the DHCP server would be a major pain and there may be some
> fundamental reason that its not possible to copy the static entries
>
> 2) change dhcp_isc_main.rb to contact both primary and secondary DHCP
> servers.
> Looking at the code it would be possible to change the omcmd routine
> to talk to a secondary server.
> This would require adding configuration items to handle the secondary.
> The problem I can see here is what to do in the case of an error
> condition from one server and not the other?
>
> 3) replace omshell with a shell that writes to both servers.
> An omshell wrapper could parse the dhcpd.conf file and determine if
> there is a secondary server.
> If there is a secondary server the commands could be piped to both
> servers.
> Once again there is the issue of what to do about errors in one server
> and not the other.
> This solution would also likely require a small patch to dhcp_isc_main.rb
> to allow for changing.
>
> I could supply a patch to the dhcp_isc_main.rb and do some testing on my
> environment so that it would pass the initial sniff test but I am not in a
> position to do a full pull request and then submit the patches via usual
> developer channel.
>
>
>
>
> On 08/11/2016 06:40 PM, [email protected] <javascript:> wrote:
>
> DHCP will not replicate the static leases as I said before, you need twice
> the omapi using omshell.
>
> I have discussed this with the ISC guys.
>
>
> Op vrijdag 12 augustus 2016 00:26:15 UTC+2 schreef Alvin Starr:
>>
>> We have slightly different problems but are both limited by the nature of
>> foremans dhcp-proxy.
>>
>> If you create static leases using omshell then I believe the data will be
>> replicated to a failover dhcp server.
>> Forman will create new hosts using omshell.
>>
>> The comment about DNS is only because foreman can cleanly interact with
>> DNS remotely.
>>
>>
>> On 08/11/2016 06:05 PM, [email protected] wrote:
>>
>> You are completely wrong.
>>
>> What we like to have is a second DHCP with a proxy where is talked to
>> using OMAPI by foreman so we have a replication about the static leases.
>>
>> DHCP itself is unable to sync them this way and for Failover we need to
>> have 2 writes to 2 DHCP servers which are in clutser mode.
>>
>> DNS is not involved here.
>>
>> Op donderdag 11 augustus 2016 23:50:43 UTC+2 schreef Alvin Starr:
>>>
>>> A standalone DHCP server without lots of extra software installed.
>>> I do not want to install the whole forman-proxy on the DHCP or DNS ser
>>> vers
>>>
>>>
>>> As an aside the isc_dhcp proxy does not parse correctly formatted
>>> dhcpd.conf files(I just filed a bug report).
>>>
>>>
>>> Looking at omapi I could be convinced that it is impossible to get the
>>> current dhcp config information remotely.
>>>
>>>
>>> On 08/11/2016 05:26 PM, [email protected] wrote:
>>>
>>> What do you mean by a standalone DHCP server ? The proxy handles that
>>> when you installed the proxy on the DHCP server.
>>>
>>> This goes about a second DHCP server that knows the same static leases
>>> as the proxy knows for failover whent the primary, with proxy, fails.
>>>
>>> Op donderdag 11 augustus 2016 22:39:40 UTC+2 schreef Alvin Starr:
>>>>
>>>> I have wondered about the same problem.
>>>> Since foreman needs to read and write the leases and config files it
>>>> means that you cannot have a remote standalone DHCP server.
>>>>
>>>>
>>>> On 08/11/2016 04:32 PM, [email protected] wrote:
>>>>
>>>> Is this me or does no-one care about DHCP redundancy ?
>>>>
>>>>
>>>>
>>>> Op zaterdag 16 januari 2016 20:06:30 UTC+1 schreef Matt .:
>>>>>
>>>>> Hi,
>>>>>
>>>>> I was wondering if someone has a workaround for DHCP sync with
>>>>> failover.
>>>>>
>>>>> As foreman writes to the leases file directly this is an issue for
>>>>> syncing.
>>>>>
>>>>> Can't we write to a config file we include to the dhcpd.conf and
>>>>> reload dhcp when the proxy did something to dhcp ?
>>>>>
>>>>> Ideas are welcome.
>>>>>
>>>>> Cheers,
>>>>>
>>>>> Matt
>>>>>
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "Foreman users" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>> an email to [email protected].
>>>> To post to this group, send email to [email protected].
>>>> Visit this group at <https://groups.google.com/group/foreman-users>
>>>> https://groups.google.com/group/foreman-users.
>>>> For more options, visit <https://groups.google.com/d/optout>
>>>> https://groups.google.com/d/optout.
>>>>
>>>>
>>>> --
>>>> Alvin Starr || voice: (905)513-7688
>>>> Netvel Inc. || Cell: (416)[email protected]
>>>> ||
>>>>
>>>>
>>> --
>>> Alvin Starr || voice: (905)513-7688
>>> Netvel Inc. || Cell: (416)[email protected]
>>> ||
>>>
>>>
>> --
>> Alvin Starr || voice: (905)513-7688
>> Netvel Inc. || Cell: (416)[email protected]
>> ||
>>
>>
> --
> Alvin Starr || voice: (905)513-7688
> Netvel Inc. || Cell: (416)[email protected]
> <javascript:> ||
>
>
--
You received this message because you are subscribed to the Google Groups
"Foreman users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/foreman-users.
For more options, visit https://groups.google.com/d/optout.
#!/usr/bin/env python3
import json
from urllib.request import Request, urlopen
from sys import argv, stderr
def pp_json(data):
pretty_json = json.dumps(data, sort_keys=True, indent=2, separators=(",", ": "))
print(pretty_json)
def key_by(data, key):
keyed_data = dict()
for a_dict in data:
keyed_data[a_dict[key]] = a_dict
return keyed_data
# Thanks to Dave and Raj: http://stackoverflow.com/a/6312600/5347993
class RequestWithMethod(Request):
def __init__(self, *args, **kwargs):
self._method = kwargs.pop('method', None)
Request.__init__(self, *args, **kwargs)
def get_method(self):
return self._method if self._method else super(RequestWithMethod, self).get_method()
# TODO: Support HTTPS
protocol = "http"
# Template for dhcp API base URLs
base_url_template = "{0}://{1}/dhcp/{2}"
lease_url_template = "{0}/{1}"
# "Parse" arguments
dhcp_primary = argv[1]
dhcp_secondary = argv[2]
subnet = argv[3]
# Get the base urls
dhcp_primary_base_url = base_url_template.format(protocol, dhcp_primary, subnet)
dhcp_secondary_base_url = base_url_template.format(protocol, dhcp_secondary, subnet)
# Fetch the current records
with urlopen(dhcp_primary_base_url) as primary_records_socket:
primary_records_json = primary_records_socket.read().decode("utf8")
with urlopen(dhcp_secondary_base_url) as secondary_records_socket:
secondary_records_json = secondary_records_socket.read().decode("utf8")
# Parse the JSON
primary_records = json.loads(primary_records_json)
secondary_records = json.loads(secondary_records_json)
# We just care about the reservations
primary_reservations = primary_records[ "reservations"]
secondary_reservations = secondary_records["reservations"]
# Key for faster lookup
keyed_primary_reservations = key_by(primary_reservations, "ip")
keyed_secondary_reservations = key_by(secondary_reservations, "ip")
# Items to change in secondary
delete_ip_on_secondary = dict()
add_lease_on_secondary = dict()
for ip, lease in keyed_secondary_reservations.items():
if ip not in keyed_primary_reservations:
# Queue for deletion
delete_ip_on_secondary[ip] = lease
for ip, lease in keyed_primary_reservations.items():
primary_lease_url = lease_url_template.format(dhcp_primary_base_url, ip)
secondary_lease_url = lease_url_template.format(dhcp_primary_base_url, ip)
# Obtain detail about reservation from primary
with urlopen(primary_lease_url) as primary_lease_socket:
primary_detail_lease_json = primary_lease_socket.read().decode("utf8")
# Parse the detailed lease
primary_detail_lease = json.loads(primary_detail_lease_json)
if ip in keyed_secondary_reservations:
# Obtain detail about reservation from secondary
with urlopen(secondary_lease_url) as secondary_lease_socket:
secondary_detail_lease_json = secondary_lease_socket.read().decode("utf8")
# Parse the secondary detailed lease
secondary_detail_lease = json.loads(secondary_detail_lease_json)
# Continue if they are the same
if set(primary_detail_lease.items()) == set(secondary_detail_lease.items()):
continue
# Queue for update
delete_ip_on_secondary[ip] = lease
add_lease_on_secondary[ip] = primary_detail_lease
else:
# Queue for addition
add_lease_on_secondary[ip] = primary_detail_lease
for ip, lease in delete_ip_on_secondary.items():
secondary_lease_url = lease_url_template.format(dhcp_secondary_base_url, ip)
delete_request = RequestWithMethod(secondary_lease_url,
method="DELETE")
# Delete the lease
with urlopen(delete_request) as lease_delete_socket:
delete_response = lease_delete_socket.read().decode("utf8")
# Notify about deletion
print("Deleted reservation for {0} ({1}):\n".format(ip, lease["hostname"]),
delete_response,
file=stderr)
for ip, detail_lease in add_lease_on_secondary.items():
secondary_lease_url = dhcp_secondary_base_url
# This does not belong
del detail_lease["subnet"]
# This does belong
detail_lease["name"] = detail_lease["hostname"]
post_data = ""
# Encode Request
for k, v in detail_lease.items():
if post_data:
post_data += "&"
post_data += "{0}={1}".format(k, v)
post_request = RequestWithMethod(secondary_lease_url,
data=post_data.encode("utf8"),
method="POST")
# Add the lease
with urlopen(post_request) as lease_post_socket:
post_response = lease_post_socket.read().decode("utf8")
# Notify about addition
print("Added reservation for {0} ({1}):\n".format(ip, lease["hostname"]),
post_response,
file=stderr)
exit(0)
# vim: set ts=4 sw=4 et syn=python: