Exemplo n.º 1
0
    def _output_opts_file(self):
        """Write a dnsmasq compatible options file."""
        options, subnet_index_map = self._generate_opts_per_subnet()
        options += self._generate_opts_per_port(subnet_index_map)

        name = self.get_conf_file_name('opts')
        utils.replace_file(name, '\n'.join(options))
        return name
Exemplo n.º 2
0
    def _output_hosts_file(self):
        """Writes a dnsmasq compatible dhcp hosts file.

        The generated file is sent to the --dhcp-hostsfile option of dnsmasq,
        and lists the hosts on the network which should receive a dhcp lease.
        Each line in this file is in the form::

            'mac_address,FQDN,ip_address'

        IMPORTANT NOTE: a dnsmasq instance does not resolve hosts defined in
        this file if it did not give a lease to a host listed in it (e.g.:
        multiple dnsmasq instances on the same network if this network is on
        multiple network nodes). This file is only defining hosts which
        should receive a dhcp lease, the hosts resolution in itself is
        defined by the `_output_addn_hosts_file` method.
        """
        buf = six.StringIO()
        filename = self.get_conf_file_name('host')

        LOG.debug('Building host file: %s', filename)
        dhcp_enabled_subnet_ids = [s.id for s in self.network.subnets
                                   if s.enable_dhcp]
        # NOTE(ihrachyshka): the loop should not log anything inside it, to
        # avoid potential performance drop when lots of hosts are dumped
        for host_tuple in self._iter_hosts():
            port, alloc, hostname, name, no_dhcp, no_opts = host_tuple
            if port.device_owner == 'network:dhcp':
                continue
            if no_dhcp:
                if not no_opts and getattr(port, 'extra_dhcp_opts', False):
                    buf.write('%s,%s%s\n' %
                              (port.mac_address, 'set:', port.id))
                continue

            # don't write ip address which belongs to a dhcp disabled subnet.
            if alloc.subnet_id not in dhcp_enabled_subnet_ids:
                continue

            ip_address = self._format_address_for_dnsmasq(alloc.ip_address)

            if getattr(port, 'extra_dhcp_opts', False):
                buf.write('%s,%s,%s,%s%s\n' %
                          (port.mac_address, name, ip_address,
                           'set:', port.id))
            else:
                buf.write('%s,%s,%s\n' %
                          (port.mac_address, name, ip_address))

        utils.replace_file(filename, buf.getvalue())
        LOG.debug('Done building host file %s', filename)
        return filename
Exemplo n.º 3
0
    def _output_init_lease_file(self):
        """Write a fake lease file to bootstrap dnsmasq.

        The generated file is passed to the --dhcp-leasefile option of dnsmasq.
        This is used as a bootstrapping mechanism to avoid NAKing active leases
        when a dhcp server is scheduled to another agent. Using a leasefile
        will also prevent dnsmasq from NAKing or ignoring renewals after a
        restart.

        Format is as follows:
        epoch-timestamp mac_addr ip_addr hostname client-ID
        """
        filename = self.get_conf_file_name('leases')
        buf = six.StringIO()

        LOG.debug('Building initial lease file: %s', filename)
        # we make up a lease time for the database entry
        if self.conf.dhcp_lease_duration == -1:
            # Even with an infinite lease, a client may choose to renew a
            # previous lease on reboot or interface bounce so we should have
            # an entry for it.
            # Dnsmasq timestamp format for an infinite lease is  is 0.
            timestamp = 0
        else:
            timestamp = int(time.time()) + self.conf.dhcp_lease_duration
        dhcp_enabled_subnet_ids = [s.id for s in self.network.subnets
                                   if s.enable_dhcp]
        for host_tuple in self._iter_hosts():
            port, alloc, hostname, name, no_dhcp, no_opts = host_tuple
            # don't write ip address which belongs to a dhcp disabled subnet
            # or an IPv6 SLAAC/stateless subnet
            if port.device_owner == 'network:dhcp':
                continue
            if no_dhcp or alloc.subnet_id not in dhcp_enabled_subnet_ids:
                continue

            ip_address = self._format_address_for_dnsmasq(alloc.ip_address)
            # all that matters is the mac address and IP. the hostname and
            # client ID will be overwritten on the next renewal.
            buf.write('%s %s %s * *\n' %
                      (timestamp, port.mac_address, ip_address))
        contents = buf.getvalue()
        utils.replace_file(filename, contents)
        LOG.debug('Done building initial lease file %s with contents:\n%s',
                  filename, contents)
        return filename
Exemplo n.º 4
0
    def _output_addn_hosts_file(self):
        """Writes a dnsmasq compatible additional hosts file.

        The generated file is sent to the --addn-hosts option of dnsmasq,
        and lists the hosts on the network which should be resolved even if
        the dnsmaq instance did not give a lease to the host (see the
        `_output_hosts_file` method).
        Each line in this file is in the same form as a standard /etc/hosts
        file.
        """
        buf = six.StringIO()
        for host_tuple in self._iter_hosts():
            port, alloc, hostname, fqdn, no_dhcp, no_opts = host_tuple
            # It is compulsory to write the `fqdn` before the `hostname` in
            # order to obtain it in PTR responses.
            if alloc:
                buf.write('%s\t%s %s\n' % (alloc.ip_address, fqdn, hostname))
        addn_hosts = self.get_conf_file_name('addn_hosts')
        utils.replace_file(addn_hosts, buf.getvalue())
        return addn_hosts
Exemplo n.º 5
0
 def interface_name(self, value):
     interface_file_path = self.get_conf_file_name('interface')
     utils.replace_file(interface_file_path, value)