"""
This is some of the code behind 'cobbler sync'.
"""
from builtins import str
from builtins import object
import time
import cobbler.templar as templar
import cobbler.utils as utils
from cobbler.utils import _
from cobbler.cexceptions import CX
[docs]def register():
return "manage"
[docs]class DnsmasqManager(object):
"""
Handles conversion of internal state to the tftpboot tree layout
"""
def __init__(self, collection_mgr, logger, dhcp=None):
"""
Constructor
"""
self.logger = logger
self.collection_mgr = collection_mgr
self.api = collection_mgr.api
self.distros = collection_mgr.distros()
self.profiles = collection_mgr.profiles()
self.systems = collection_mgr.systems()
self.settings = collection_mgr.settings()
self.repos = collection_mgr.repos()
self.templar = templar.Templar(collection_mgr)
[docs] def what(self):
return "dnsmasq"
[docs] def write_dhcp_lease(self, port, host, ip, mac):
pass
[docs] def remove_dhcp_lease(self, port, host):
pass
[docs] def write_dhcp_file(self):
"""
DHCP files are written when manage_dhcp is set in
/etc/cobbler/settings.
"""
settings_file = "/etc/dnsmasq.conf"
template_file = "/etc/cobbler/dnsmasq.template"
try:
f2 = open(template_file, "r")
except:
raise CX(_("error writing template to file: %s") % template_file)
template_data = ""
template_data = f2.read()
f2.close()
system_definitions = {}
counter = 0
# we used to just loop through each system, but now we must loop
# through each network interface of each system.
for system in self.systems:
if not system.is_management_supported(cidr_ok=False):
continue
profile = system.get_conceptual_parent()
distro = profile.get_conceptual_parent()
for (name, interface) in list(system.interfaces.items()):
mac = interface["mac_address"]
ip = interface["ip_address"]
host = interface["dns_name"]
ipv6 = interface["ipv6_address"]
if not mac:
# can't write a DHCP entry for this system
continue
counter += 1
# In many reallife situations there is a need to control the IP address
# and hostname for a specific client when only the MAC address is available.
# In addition to that in some scenarios there is a need to explicitly
# label a host with the applicable architecture in order to correctly
# handle situations where we need something other than pxelinux.0.
# So we always write a dhcp-host entry with as much info as possible
# to allow maximum control and flexibility within the dnsmasq config
systxt = "dhcp-host=net:" + distro.arch.lower() + "," + mac
if host is not None and host != "":
systxt += "," + host
if ip is not None and ip != "":
systxt += "," + ip
if ipv6 is not None and ipv6 != "":
systxt += ",[%s]" % ipv6
systxt += "\n"
dhcp_tag = interface["dhcp_tag"]
if dhcp_tag == "":
dhcp_tag = "default"
if dhcp_tag not in system_definitions:
system_definitions[dhcp_tag] = ""
system_definitions[dhcp_tag] = system_definitions[dhcp_tag] + systxt
# we are now done with the looping through each interface of each system
metadata = {
"insert_cobbler_system_definitions": system_definitions.get("default", ""),
"date": time.asctime(time.gmtime()),
"cobbler_server": self.settings.server,
"next_server": self.settings.next_server,
}
# now add in other DHCP expansions that are not tagged with "default"
for x in list(system_definitions.keys()):
if x == "default":
continue
metadata["insert_cobbler_system_definitions_%s" % x] = system_definitions[x]
self.templar.render(template_data, metadata, settings_file, None)
[docs] def regen_ethers(self):
# dnsmasq knows how to read this database of MACs -> IPs, so we'll keep it up to date
# every time we add a system.
# read 'man ethers' for format info
fh = open("/etc/ethers", "w+")
for system in self.systems:
if not system.is_management_supported(cidr_ok=False):
continue
for (name, interface) in list(system.interfaces.items()):
mac = interface["mac_address"]
ip = interface["ip_address"]
if not mac:
# can't write this w/o a MAC address
continue
if ip is not None and ip != "":
fh.write(mac.upper() + "\t" + ip + "\n")
fh.close()
[docs] def regen_hosts(self):
# dnsmasq knows how to read this database for host info
# (other things may also make use of this later)
fh = open("/var/lib/cobbler/cobbler_hosts", "w+")
for system in self.systems:
if not system.is_management_supported(cidr_ok=False):
continue
for (name, interface) in list(system.interfaces.items()):
mac = interface["mac_address"]
host = interface["dns_name"]
ip = interface["ip_address"]
ipv6 = interface["ipv6_address"]
if not mac:
continue
if host is not None and host != "" and ipv6 is not None and ipv6 != "":
fh.write(ipv6 + "\t" + host + "\n")
elif host is not None and host != "" and ip is not None and ip != "":
fh.write(ip + "\t" + host + "\n")
fh.close()
[docs] def write_dns_files(self):
# already taken care of by the regen_hosts()
pass
[docs] def sync_dhcp(self):
restart_dhcp = str(self.settings.restart_dhcp).lower()
if restart_dhcp != "0":
rc = utils.subprocess_call(self.logger, "service dnsmasq restart")
if rc != 0:
error_msg = "service dnsmasq restart failed"
self.logger.error(error_msg)
raise CX(error_msg)
[docs]def get_manager(collection_mgr, logger):
return DnsmasqManager(collection_mgr, logger)