{#
Copyright 2017-present Open Networking Foundation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
#}

# dhcpd.conf
# Managed by Ansible!

{% if dns_search %}
option domain-name "{{ dns_search[0] }}";
option domain-search "{{ dns_search | join('", "') }}";
{% endif %}

{% if dns_servers %}
option domain-name-servers {{ dns_servers | join(", ") }};
{% endif %}

{% for subnet in dhcpd_subnets %}
subnet {{ subnet.cidr | ipaddr('network') }} netmask {{ subnet.cidr | ipaddr('netmask') }} {
  option routers {{ subnet.router | default(subnet.cidr | ipaddr('1') | ipaddr('address')) }};
  range {{ subnet.cidr | ipaddr(subnet.dhcp_first | default("129")) | ipaddr('address') }} {{ subnet.cidr | ipaddr(subnet.dhcp_last | default("254")) | ipaddr('address') }};
{% if subnet.dns_search is defined %}
  option domain-name {{ subnet.dns_search [0] }};
  option domain-search {{ subnet.dns_search| join(", ") }};
{% endif %}
{% if subnet.dns_servers is defined %}
  option domain-name-servers {{ subnet.dns_servers | join(", ") }};
{% endif %}
  default-lease-time {{ subnet.lease_time | default("240") }};
  max-lease-time {{ subnet.max_lease_time | default("480") }};
{% if subnet.pxe_filename is defined %}
  filename "{{ subnet.pxe_filename }}";
  next-server {{ subnet.tftp_server | default(subnet.cidr | ipaddr('1') | ipaddr('address')) }};
{% endif %}
{% if subnet.static_nodes is defined %}
  # hosts from list: static_nodes
{% for node in subnet.static_nodes %}
  host {{ node.name }} {
    option host-name "{{ node.name }}";
{% set host_ipaddr = (subnet.cidr | ipaddr(node.ipv4_last_octet) | ipaddr('address')) %}
    fixed-address {{ host_ipaddr }};
    hardware ethernet {{ node.hwaddr | default(vtn_net_management_host_hwaddr_prefix ~ (host_ipaddr | ip4_hex)) | hwaddr('linux') }};
{% if node.pxe_filename is defined %}
    filename "{{ node.pxe_filename }}";
    next-server {{ subnet.tftp_server | default(subnet.cidr | ipaddr('1') | ipaddr('address')) }};
{% endif %}
  }
{% endfor %}
{% endif %}
{% if subnet.other_static is defined %}
{% for hostlist in subnet.other_static %}
  # hosts from list: {{ hostlist }}
{% set nodes = vars[hostlist] %}
{% for node in nodes %}
  host {{ node.name }} {
    option host-name "{{ node.name }}";
{% set host_ipaddr = (subnet.cidr | ipaddr(node.ipv4_last_octet) | ipaddr('address')) %}
    fixed-address {{ host_ipaddr }};
    hardware ethernet {{ node.hwaddr | default(vtn_net_management_host_hwaddr_prefix ~ (host_ipaddr | ip4_hex)) | hwaddr('linux') }};
{% if node.pxe_filename is defined %}
    filename "{{ subnet.pxe_filename }}";
    next-server {{ subnet.tftp_server | default(subnet.cidr | ipaddr('1') | ipaddr('address')) }};
{% endif %}
  }
{% endfor %}
{% endfor %}
{% endif %}
}

{% endfor %}
