Merge lp:~james-page/ubuntu/natty/cobbler/fix-764391 into lp:ubuntu/natty/cobbler

Proposed by James Page
Status: Merged
Merge reported by: Sebastien Bacher
Merged at revision: not available
Proposed branch: lp:~james-page/ubuntu/natty/cobbler/fix-764391
Merge into: lp:ubuntu/natty/cobbler
Diff against target: 1187 lines (+1035/-24)
13 files modified
.pc/40_ubuntu_bind9_management.patch/cobbler/action_check.py (+482/-0)
.pc/40_ubuntu_bind9_management.patch/cobbler/modules/manage_bind.py (+332/-0)
.pc/40_ubuntu_bind9_management.patch/cobbler/modules/sync_post_restart_services.py (+66/-0)
.pc/40_ubuntu_bind9_management.patch/templates/etc/named.template (+31/-0)
.pc/applied-patches (+1/-0)
cobbler/action_check.py (+1/-1)
cobbler/modules/manage_bind.py (+3/-3)
cobbler/modules/sync_post_restart_services.py (+1/-1)
debian/changelog (+11/-0)
debian/control (+1/-0)
debian/patches/40_ubuntu_bind9_management.patch (+103/-0)
debian/patches/series (+1/-0)
templates/etc/named.template (+2/-19)
To merge this branch: bzr merge lp:~james-page/ubuntu/natty/cobbler/fix-764391
Reviewer Review Type Date Requested Status
Dave Walker (community) Approve
Review via email: mp+58112@code.launchpad.net

Description of the change

Fix up management of bind9 on Ubuntu as paths/daemon names where Redhat-esq.

To post a comment you must log in.
Revision history for this message
Dave Walker (davewalker) wrote :

lgtm, uploaded to natty queue.

Thanks.

Revision history for this message
Dave Walker (davewalker) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory '.pc/40_ubuntu_bind9_management.patch'
2=== added directory '.pc/40_ubuntu_bind9_management.patch/cobbler'
3=== added file '.pc/40_ubuntu_bind9_management.patch/cobbler/action_check.py'
4--- .pc/40_ubuntu_bind9_management.patch/cobbler/action_check.py 1970-01-01 00:00:00 +0000
5+++ .pc/40_ubuntu_bind9_management.patch/cobbler/action_check.py 2011-04-18 12:44:31 +0000
6@@ -0,0 +1,482 @@
7+"""
8+Validates whether the system is reasonably well configured for
9+serving up content. This is the code behind 'cobbler check'.
10+
11+Copyright 2006-2009, Red Hat, Inc
12+Michael DeHaan <mdehaan@redhat.com>
13+
14+This program is free software; you can redistribute it and/or modify
15+it under the terms of the GNU General Public License as published by
16+the Free Software Foundation; either version 2 of the License, or
17+(at your option) any later version.
18+
19+This program is distributed in the hope that it will be useful,
20+but WITHOUT ANY WARRANTY; without even the implied warranty of
21+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22+GNU General Public License for more details.
23+
24+You should have received a copy of the GNU General Public License
25+along with this program; if not, write to the Free Software
26+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27+02110-1301 USA
28+"""
29+
30+import os
31+import re
32+import action_sync
33+import utils
34+import glob
35+from utils import _
36+import clogger
37+
38+class BootCheck:
39+
40+ def __init__(self,config,logger=None):
41+ """
42+ Constructor
43+ """
44+ self.config = config
45+ self.settings = config.settings()
46+ if logger is None:
47+ logger = clogger.Logger()
48+ self.logger = logger
49+
50+
51+ def run(self):
52+ """
53+ Returns None if there are no errors, otherwise returns a list
54+ of things to correct prior to running application 'for real'.
55+ (The CLI usage is "cobbler check" before "cobbler sync")
56+ """
57+ status = []
58+ self.checked_dist = utils.check_dist()
59+ self.check_name(status)
60+ self.check_selinux(status)
61+ if self.settings.manage_dhcp:
62+ mode = self.config.api.get_sync().dhcp.what()
63+ if mode == "isc":
64+ self.check_dhcpd_bin(status)
65+ self.check_dhcpd_conf(status)
66+ self.check_service(status,"dhcpd")
67+ elif mode == "dnsmasq":
68+ self.check_dnsmasq_bin(status)
69+ self.check_service(status,"dnsmasq")
70+
71+ if self.settings.manage_dns:
72+ mode = self.config.api.get_sync().dns.what()
73+ if mode == "bind":
74+ self.check_bind_bin(status)
75+ self.check_service(status,"named")
76+ elif mode == "dnsmasq" and not self.settings.manage_dhcp:
77+ self.check_dnsmasq_bin(status)
78+ self.check_service(status,"dnsmasq")
79+
80+ mode = self.config.api.get_sync().tftpd.what()
81+ if mode == "in_tftpd":
82+ self.check_tftpd_bin(status)
83+ self.check_tftpd_dir(status)
84+ self.check_tftpd_conf(status)
85+ elif mode == "tftpd_py":
86+ self.check_ctftpd_bin(status)
87+ self.check_ctftpd_dir(status)
88+ self.check_ctftpd_conf(status)
89+
90+ self.check_service(status, "cobblerd")
91+
92+ self.check_bootloaders(status)
93+ self.check_rsync_conf(status)
94+ self.check_httpd(status)
95+ self.check_iptables(status)
96+ self.check_yum(status)
97+ self.check_debmirror(status)
98+ self.check_for_ksvalidator(status)
99+ self.check_for_default_password(status)
100+ self.check_for_unreferenced_repos(status)
101+ self.check_for_unsynced_repos(status)
102+ self.check_for_cman(status)
103+
104+ return status
105+
106+ def check_for_ksvalidator(self, status):
107+ if self.checked_dist in ["debian", "ubuntu"]:
108+ return
109+
110+ if not os.path.exists("/usr/bin/ksvalidator"):
111+ status.append("ksvalidator was not found, install pykickstart")
112+
113+ return True
114+
115+ def check_for_cman(self, status):
116+ # not doing rpm -q here to be cross-distro friendly
117+ if not os.path.exists("/sbin/fence_ilo") and not os.path.exists("/usr/sbin/fence_ilo"):
118+ status.append("fencing tools were not found, and are required to use the (optional) power management features. install cman or fence-agents to use them")
119+ return True
120+
121+ def check_service(self, status, which, notes=""):
122+ if notes != "":
123+ notes = " (NOTE: %s)" % notes
124+ rc = 0
125+ if self.checked_dist == "redhat" or self.checked_dist == "suse":
126+ if os.path.exists("/etc/rc.d/init.d/%s" % which):
127+ rc = utils.subprocess_call(self.logger,"/sbin/service %s status > /dev/null 2>/dev/null" % which, shell=True)
128+ if rc != 0:
129+ status.append(_("service %s is not running%s") % (which,notes))
130+ return False
131+ elif self.checked_dist in ["debian", "ubuntu"]:
132+ # we still use /etc/init.d
133+ if os.path.exists("/etc/init.d/%s" % which):
134+ rc = utils.subprocess_call(self.logger,"/etc/init.d/%s status /dev/null 2>/dev/null" % which, shell=True)
135+ if rc != 0:
136+ status.append(_("service %s is not running%s") % which,notes)
137+ return False
138+ elif self.checked_dist == "ubuntu":
139+ if os.path.exists("/etc/init/%s.conf" % which):
140+ rc = utils.subprocess_call(self.logger,"status %s > /dev/null 2>&1" % which, shell=True)
141+ if rc != 0:
142+ status.append(_("service %s is not running%s") % (which,notes))
143+ else:
144+ status.append(_("Unknown distribution type, cannot check for running service %s" % which))
145+ return False
146+ return True
147+
148+ def check_iptables(self, status):
149+ if os.path.exists("/etc/rc.d/init.d/iptables"):
150+ rc = utils.subprocess_call(self.logger,"/sbin/service iptables status >/dev/null 2>/dev/null", shell=True)
151+ if rc == 0:
152+ status.append(_("since iptables may be running, ensure 69, 80, and %(xmlrpc)s are unblocked") % { "xmlrpc" : self.settings.xmlrpc_port })
153+
154+ def check_yum(self,status):
155+ if self.checked_dist in ["debian", "ubuntu"]:
156+ return
157+
158+ if not os.path.exists("/usr/bin/createrepo"):
159+ status.append(_("createrepo package is not installed, needed for cobbler import and cobbler reposync, install createrepo?"))
160+ if not os.path.exists("/usr/bin/reposync"):
161+ status.append(_("reposync is not installed, need for cobbler reposync, install/upgrade yum-utils?"))
162+ if not os.path.exists("/usr/bin/yumdownloader"):
163+ status.append(_("yumdownloader is not installed, needed for cobbler repo add with --rpm-list parameter, install/upgrade yum-utils?"))
164+ if self.settings.reposync_flags.find("-l"):
165+ if self.checked_dist == "redhat" or self.checked_dist == "suse":
166+ yum_utils_ver = utils.subprocess_get(self.logger,"/usr/bin/rpmquery --queryformat=%{VERSION} yum-utils", shell=True)
167+ if yum_utils_ver < "1.1.17":
168+ status.append(_("yum-utils need to be at least version 1.1.17 for reposync -l, current version is %s") % yum_utils_ver )
169+
170+ def check_debmirror(self,status):
171+ if not os.path.exists("/usr/bin/debmirror"):
172+ status.append(_("debmirror package is not installed, it will be required to manage debian deployments and repositories"))
173+ if os.path.exists("/etc/debmirror.conf"):
174+ f = open("/etc/debmirror.conf")
175+ re_dists = re.compile(r'@dists=')
176+ re_arches = re.compile(r'@arches=')
177+ for line in f.readlines():
178+ if re_dists.search(line) and not line.strip().startswith("#"):
179+ status.append(_("comment 'dists' on /etc/debmirror.conf for proper debian support"))
180+ if re_arches.search(line) and not line.strip().startswith("#"):
181+ status.append(_("comment 'arches' on /etc/debmirror.conf for proper debian support"))
182+
183+
184+ def check_name(self,status):
185+ """
186+ If the server name in the config file is still set to localhost
187+ kickstarts run from koan will not have proper kernel line
188+ parameters.
189+ """
190+ if self.settings.server == "127.0.0.1":
191+ status.append(_("The 'server' field in /etc/cobbler/settings must be set to something other than localhost, or kickstarting features will not work. This should be a resolvable hostname or IP for the boot server as reachable by all machines that will use it."))
192+ if self.settings.next_server == "127.0.0.1":
193+ status.append(_("For PXE to be functional, the 'next_server' field in /etc/cobbler/settings must be set to something other than 127.0.0.1, and should match the IP of the boot server on the PXE network."))
194+
195+ def check_selinux(self,status):
196+ """
197+ Suggests various SELinux rules changes to run Cobbler happily with
198+ SELinux in enforcing mode. FIXME: this method could use some
199+ refactoring in the future.
200+ """
201+ if self.checked_dist in ["debian", "ubuntu"]:
202+ return
203+
204+ enabled = self.config.api.is_selinux_enabled()
205+ if enabled:
206+ data2 = utils.subprocess_get(self.logger,"/usr/sbin/getsebool -a",shell=True)
207+ for line in data2.split("\n"):
208+ if line.find("httpd_can_network_connect ") != -1:
209+ if line.find("off") != -1:
210+ status.append(_("Must enable a selinux boolean to enable vital web services components, run: setsebool -P httpd_can_network_connect true"))
211+ if line.find("rsync_disable_trans ") != -1:
212+ if line.find("on") != -1:
213+ status.append(_("Must enable the cobbler import and replicate commands, run: setsebool -P rsync_disable_trans=1"))
214+
215+ data3 = utils.subprocess_get(self.logger,"/usr/sbin/semanage fcontext -l | grep public_content_t",shell=True)
216+
217+ rule1 = False
218+ rule2 = False
219+ rule3 = False
220+ selinux_msg = "/usr/sbin/semanage fcontext -a -t public_content_t \"%s\""
221+ for line in data3.split("\n"):
222+ if line.startswith("/tftpboot/.*"):
223+ rule1 = True
224+ if line.startswith("/var/lib/tftpboot/.*"):
225+ rule2 = True
226+ if line.startswith("/var/www/cobbler/images/.*"):
227+ rule3 = True
228+
229+ rules = []
230+ if os.path.exists("/tftpboot") and not rule1:
231+ rules.append(selinux_msg % "/tftpboot/.*")
232+ else:
233+ if not rule2:
234+ rules.append(selinux_msg % "/var/lib/tftpboot/.*")
235+ if not rule3:
236+ rules.append(selinux_msg % "/var/www/cobbler/images/.*")
237+ if len(rules) > 0:
238+ status.append("you need to set some SELinux content rules to ensure cobbler serves content correctly in your SELinux environment, run the following: %s" % " && ".join(rules))
239+
240+ # now check to see that the Django sessions path is accessible
241+ # by Apache
242+
243+ data4 = utils.subprocess_get(self.logger,"/usr/sbin/semanage fcontext -l | grep httpd_sys_content_rw_t",shell=True)
244+ selinux_msg = "you need to set some SELinux rules if you want to use cobbler-web (an optional package), run the following: /usr/sbin/semanage fcontext -a -t httpd_sys_content_rw_t \"%s\""
245+ rule4 = False
246+ for line in data4.split("\n"):
247+ if line.startswith("/var/lib/cobbler/webui_sessions/.*"):
248+ rule4 = True
249+ if not rule4:
250+ status.append(selinux_msg % "/var/lib/cobbler/webui_sessions/.*")
251+
252+
253+ def check_for_default_password(self,status):
254+ default_pass = self.settings.default_password_crypted
255+ if default_pass == "$1$mF86/UHC$WvcIcX2t6crBz2onWxyac.":
256+ status.append(_("The default password used by the sample templates for newly installed machines (default_password_crypted in /etc/cobbler/settings) is still set to 'cobbler' and should be changed, try: \"openssl passwd -1 -salt 'random-phrase-here' 'your-password-here'\" to generate new one"))
257+
258+
259+ def check_for_unreferenced_repos(self,status):
260+ repos = []
261+ referenced = []
262+ not_found = []
263+ for r in self.config.api.repos():
264+ repos.append(r.name)
265+ for p in self.config.api.profiles():
266+ my_repos = p.repos
267+ if my_repos != "<<inherit>>":
268+ referenced.extend(my_repos)
269+ for r in referenced:
270+ if r not in repos and r != "<<inherit>>":
271+ not_found.append(r)
272+ if len(not_found) > 0:
273+ status.append(_("One or more repos referenced by profile objects is no longer defined in cobbler: %s") % ", ".join(not_found))
274+
275+ def check_for_unsynced_repos(self,status):
276+ need_sync = []
277+ for r in self.config.repos():
278+ if r.mirror_locally == 1:
279+ lookfor = os.path.join(self.settings.webdir, "repo_mirror", r.name)
280+ if not os.path.exists(lookfor):
281+ need_sync.append(r.name)
282+ if len(need_sync) > 0:
283+ status.append(_("One or more repos need to be processed by cobbler reposync for the first time before kickstarting against them: %s") % ", ".join(need_sync))
284+
285+
286+ def check_httpd(self,status):
287+ """
288+ Check if Apache is installed.
289+ """
290+ if self.checked_dist in [ "suse", "redhat" ]:
291+ rc = utils.subprocess_get(self.logger,"httpd -v")
292+ else:
293+ rc = utils.subprocess_get(self.logger,"apache2 -v")
294+ if rc.find("Server") == -1:
295+ status.append("Apache (httpd) is not installed and/or in path")
296+
297+
298+ def check_dhcpd_bin(self,status):
299+ """
300+ Check if dhcpd is installed
301+ """
302+ if not os.path.exists("/usr/sbin/dhcpd"):
303+ status.append("dhcpd is not installed")
304+
305+ def check_dnsmasq_bin(self,status):
306+ """
307+ Check if dnsmasq is installed
308+ """
309+ rc = utils.subprocess_get(self.logger,"dnsmasq --help")
310+ if rc.find("Valid options") == -1:
311+ status.append("dnsmasq is not installed and/or in path")
312+
313+ def check_bind_bin(self,status):
314+ """
315+ Check if bind is installed.
316+ """
317+ rc = utils.subprocess_get(self.logger,"named -v")
318+ # it should return something like "BIND 9.6.1-P1-RedHat-9.6.1-6.P1.fc11"
319+ if rc.find("BIND") == -1:
320+ status.append("named is not installed and/or in path")
321+
322+ def check_bootloaders(self,status):
323+ """
324+ Check if network bootloaders are installed
325+ """
326+ # FIXME: move zpxe.rexx to loaders
327+
328+ bootloaders = {
329+ "elilo" : [ "/var/lib/cobbler/loaders/elilo*.efi" ],
330+ "menu.c32" : [ "/usr/share/syslinux/menu.c32",
331+ "/usr/lib/syslinux/menu.c32",
332+ "/var/lib/cobbler/loaders/menu.c32" ],
333+ "yaboot" : [ "/var/lib/cobbler/loaders/yaboot*" ],
334+ "pxelinux.0" : [ "/usr/share/syslinux/pxelinux.0",
335+ "/usr/lib/syslinux/pxelinux.0",
336+ "/var/lib/cobbler/loaders/pxelinux.0" ],
337+ "efi" : [ "/var/lib/cobbler/loaders/grub-x86.efi",
338+ "/var/lib/cobbler/loaders/grub-x86_64.efi" ],
339+ }
340+
341+ # look for bootloaders at the glob locations above
342+ found_bootloaders = []
343+ items = bootloaders.keys()
344+ for loader_name in items:
345+ patterns = bootloaders[loader_name]
346+ for pattern in patterns:
347+ matches = glob.glob(pattern)
348+ if len(matches) > 0:
349+ found_bootloaders.append(loader_name)
350+ not_found = []
351+
352+ # invert the list of what we've found so we can report on what we haven't found
353+ for loader_name in items:
354+ if loader_name not in found_bootloaders:
355+ not_found.append(loader_name)
356+
357+ if len(not_found) > 0:
358+ status.append("some network boot-loaders are missing from /var/lib/cobbler/loaders, you may run 'cobbler get-loaders' to download them, or, if you only want to handle x86/x86_64 netbooting, you may ensure that you have installed a *recent* version of the syslinux package installed and can ignore this message entirely. Files in this directory, should you want to support all architectures, should include pxelinux.0, menu.c32, elilo.efi, and yaboot. The 'cobbler get-loaders' command is the easiest way to resolve these requirements.")
359+
360+ def check_tftpd_bin(self,status):
361+ """
362+ Check if tftpd is installed
363+ """
364+ if self.checked_dist in ["debian", "ubuntu"]:
365+ return
366+
367+ if not os.path.exists("/etc/xinetd.d/tftp"):
368+ status.append("missing /etc/xinetd.d/tftp, install tftp-server?")
369+
370+ def check_tftpd_dir(self,status):
371+ """
372+ Check if cobbler.conf's tftpboot directory exists
373+ """
374+ if self.checked_dist in ["debian", "ubuntu"]:
375+ return
376+
377+ bootloc = utils.tftpboot_location()
378+ if not os.path.exists(bootloc):
379+ status.append(_("please create directory: %(dirname)s") % { "dirname" : bootloc })
380+
381+
382+ def check_tftpd_conf(self,status):
383+ """
384+ Check that configured tftpd boot directory matches with actual
385+ Check that tftpd is enabled to autostart
386+ """
387+ if self.checked_dist in ["debian", "ubuntu"]:
388+ return
389+
390+ if os.path.exists("/etc/xinetd.d/tftp"):
391+ f = open("/etc/xinetd.d/tftp")
392+ re_disable = re.compile(r'disable.*=.*yes')
393+ for line in f.readlines():
394+ if re_disable.search(line) and not line.strip().startswith("#"):
395+ status.append(_("change 'disable' to 'no' in %(file)s") % { "file" : "/etc/xinetd.d/tftp" })
396+ else:
397+ status.append("missing configuration file: /etc/xinetd.d/tftp")
398+
399+ def check_ctftpd_bin(self,status):
400+ """
401+ Check if the Cobbler tftp server is installed
402+ """
403+ if self.checked_dist in ["debian", "ubuntu"]:
404+ return
405+
406+ if not os.path.exists("/etc/xinetd.d/ctftp"):
407+ status.append("missing /etc/xinetd.d/ctftp")
408+
409+ def check_ctftpd_dir(self,status):
410+ """
411+ Check if cobbler.conf's tftpboot directory exists
412+ """
413+ if self.checked_dist in ["debian", "ubuntu"]:
414+ return
415+
416+ bootloc = utils.tftpboot_location()
417+ if not os.path.exists(bootloc):
418+ status.append(_("please create directory: %(dirname)s") % { "dirname" : bootloc })
419+
420+ def check_ctftpd_conf(self,status):
421+ """
422+ Check that configured tftpd boot directory matches with actual
423+ Check that tftpd is enabled to autostart
424+ """
425+ if self.checked_dist in ["debian", "ubuntu"]:
426+ return
427+
428+ if os.path.exists("/etc/xinetd.d/tftp"):
429+ f = open("/etc/xinetd.d/tftp")
430+ re_disable = re.compile(r'disable.*=.*no')
431+ for line in f.readlines():
432+ if re_disable.search(line) and not line.strip().startswith("#"):
433+ status.append(_("change 'disable' to 'yes' in %(file)s") % { "file" : "/etc/xinetd.d/tftp" })
434+ if os.path.exists("/etc/xinetd.d/ctftp"):
435+ f = open("/etc/xinetd.d/ctftp")
436+ re_disable = re.compile(r'disable.*=.*yes')
437+ for line in f.readlines():
438+ if re_disable.search(line) and not line.strip().startswith("#"):
439+ status.append(_("change 'disable' to 'no' in %(file)s") % { "file" : "/etc/xinetd.d/ctftp" })
440+ else:
441+ status.append("missing configuration file: /etc/xinetd.d/ctftp")
442+
443+ def check_rsync_conf(self,status):
444+ """
445+ Check that rsync is enabled to autostart
446+ """
447+ if self.checked_dist in ["debian", "ubuntu"]:
448+ return
449+
450+ if os.path.exists("/etc/xinetd.d/rsync"):
451+ f = open("/etc/xinetd.d/rsync")
452+ re_disable = re.compile(r'disable.*=.*yes')
453+ for line in f.readlines():
454+ if re_disable.search(line) and not line.strip().startswith("#"):
455+ status.append(_("change 'disable' to 'no' in %(file)s") % { "file" : "/etc/xinetd.d/rsync" })
456+ else:
457+ status.append(_("file %(file)s does not exist") % { "file" : "/etc/xinetd.d/rsync" })
458+
459+
460+ def check_dhcpd_conf(self,status):
461+ """
462+ NOTE: this code only applies if cobbler is *NOT* set to generate
463+ a dhcp.conf file
464+
465+ Check that dhcpd *appears* to be configured for pxe booting.
466+ We can't assure file correctness. Since a cobbler user might
467+ have dhcp on another server, it's okay if it's not there and/or
468+ not configured correctly according to automated scans.
469+ """
470+ if not (self.settings.manage_dhcp == 0):
471+ return
472+
473+ if os.path.exists(self.settings.dhcpd_conf):
474+ match_next = False
475+ match_file = False
476+ f = open(self.settings.dhcpd_conf)
477+ for line in f.readlines():
478+ if line.find("next-server") != -1:
479+ match_next = True
480+ if line.find("filename") != -1:
481+ match_file = True
482+ if not match_next:
483+ status.append(_("expecting next-server entry in %(file)s") % { "file" : self.settings.dhcpd_conf })
484+ if not match_file:
485+ status.append(_("missing file: %(file)s") % { "file" : self.settings.dhcpd_conf })
486+ else:
487+ status.append(_("missing file: %(file)s") % { "file" : self.settings.dhcpd_conf })
488+
489
490=== added directory '.pc/40_ubuntu_bind9_management.patch/cobbler/modules'
491=== added file '.pc/40_ubuntu_bind9_management.patch/cobbler/modules/manage_bind.py'
492--- .pc/40_ubuntu_bind9_management.patch/cobbler/modules/manage_bind.py 1970-01-01 00:00:00 +0000
493+++ .pc/40_ubuntu_bind9_management.patch/cobbler/modules/manage_bind.py 2011-04-18 12:44:31 +0000
494@@ -0,0 +1,332 @@
495+"""
496+This is some of the code behind 'cobbler sync'.
497+
498+Copyright 2006-2009, Red Hat, Inc
499+Michael DeHaan <mdehaan@redhat.com>
500+John Eckersberg <jeckersb@redhat.com>
501+
502+This program is free software; you can redistribute it and/or modify
503+it under the terms of the GNU General Public License as published by
504+the Free Software Foundation; either version 2 of the License, or
505+(at your option) any later version.
506+
507+This program is distributed in the hope that it will be useful,
508+but WITHOUT ANY WARRANTY; without even the implied warranty of
509+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
510+GNU General Public License for more details.
511+
512+You should have received a copy of the GNU General Public License
513+along with this program; if not, write to the Free Software
514+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
515+02110-1301 USA
516+"""
517+
518+import os
519+import os.path
520+import shutil
521+import time
522+import sys
523+import glob
524+import traceback
525+import errno
526+import re
527+from shlex import shlex
528+
529+
530+import utils
531+from cexceptions import *
532+import templar
533+
534+import item_distro
535+import item_profile
536+import item_repo
537+import item_system
538+
539+from utils import _
540+
541+
542+def register():
543+ """
544+ The mandatory cobbler module registration hook.
545+ """
546+ return "manage"
547+
548+
549+class BindManager:
550+
551+ def what(self):
552+ return "bind"
553+
554+ def __init__(self,config,logger):
555+ """
556+ Constructor
557+ """
558+ self.logger = logger
559+ self.config = config
560+ self.api = config.api
561+ self.distros = config.distros()
562+ self.profiles = config.profiles()
563+ self.systems = config.systems()
564+ self.settings = config.settings()
565+ self.repos = config.repos()
566+ self.templar = templar.Templar(config)
567+
568+ def regen_hosts(self):
569+ pass # not used
570+
571+ def __forward_zones(self):
572+ """
573+ Returns a map of zones and the records that belong
574+ in them
575+ """
576+ zones = {}
577+ forward_zones = self.settings.manage_forward_zones
578+ if type(forward_zones) != type([]):
579+ # gracefully handle when user inputs only a single zone
580+ # as a string instead of a list with only a single item
581+ forward_zones = [forward_zones]
582+
583+ for zone in forward_zones:
584+ zones[zone] = {}
585+
586+ for system in self.systems:
587+ for (name, interface) in system.interfaces.iteritems():
588+ host = interface["dns_name"]
589+ ip = interface["ip_address"]
590+ if not system.is_management_supported(cidr_ok=False):
591+ continue
592+ if not host or not ip:
593+ # gotsta have some dns_name and ip or else!
594+ continue
595+ if host.find(".") == -1:
596+ continue
597+
598+ # match the longest zone!
599+ # e.g. if you have a host a.b.c.d.e
600+ # if manage_forward_zones has:
601+ # - c.d.e
602+ # - b.c.d.e
603+ # then a.b.c.d.e should go in b.c.d.e
604+ best_match = ''
605+ for zone in zones.keys():
606+ if re.search('\.%s$' % zone, host) and len(zone) > len(best_match):
607+ best_match = zone
608+
609+ if best_match == '': # no match
610+ continue
611+
612+ # strip the zone off the dns_name and append the
613+ # remainder + ip to the zone list
614+ host = re.sub('\.%s$' % best_match, '', host)
615+
616+ zones[best_match][host] = ip
617+
618+ return zones
619+
620+ def __reverse_zones(self):
621+ """
622+ Returns a map of zones and the records that belong
623+ in them
624+ """
625+ zones = {}
626+ reverse_zones = self.settings.manage_reverse_zones
627+ if type(reverse_zones) != type([]):
628+ # gracefully handle when user inputs only a single zone
629+ # as a string instead of a list with only a single item
630+ reverse_zones = [reverse_zones]
631+
632+ for zone in reverse_zones:
633+ zones[zone] = {}
634+
635+ for sys in self.systems:
636+ for (name, interface) in sys.interfaces.iteritems():
637+ host = interface["dns_name"]
638+ ip = interface["ip_address"]
639+ if not sys.is_management_supported(cidr_ok=False):
640+ continue
641+ if not host or not ip:
642+ # gotsta have some dns_name and ip or else!
643+ continue
644+
645+ # match the longest zone!
646+ # e.g. if you have an ip 1.2.3.4
647+ # if manage_reverse_zones has:
648+ # - 1.2
649+ # - 1.2.3
650+ # then 1.2.3.4 should go in 1.2.3
651+ best_match = ''
652+ for zone in zones.keys():
653+ if re.search('^%s\.' % zone, ip) and len(zone) > len(best_match):
654+ best_match = zone
655+
656+ if best_match == '': # no match
657+ continue
658+
659+ # strip the zone off the front of the ip
660+ # reverse the rest of the octets
661+ # append the remainder + dns_name
662+ ip = ip.replace(best_match, '', 1)
663+ if ip[0] == '.': # strip leading '.' if it's there
664+ ip = ip[1:]
665+ tokens = ip.split('.')
666+ tokens.reverse()
667+ ip = '.'.join(tokens)
668+ zones[best_match][ip] = host + '.'
669+
670+ return zones
671+
672+
673+ def __write_named_conf(self):
674+ """
675+ Write out the named.conf main config file from the template.
676+ """
677+ settings_file = "/etc/named.conf"
678+ template_file = "/etc/cobbler/named.template"
679+ forward_zones = self.settings.manage_forward_zones
680+ reverse_zones = self.settings.manage_reverse_zones
681+
682+ metadata = {'forward_zones': self.__forward_zones().keys(),
683+ 'reverse_zones': [],
684+ 'zone_include': ''}
685+
686+ for zone in metadata['forward_zones']:
687+ txt = """
688+zone "%(zone)s." {
689+ type master;
690+ file "%(zone)s";
691+};
692+""" % {'zone': zone}
693+ metadata['zone_include'] = metadata['zone_include'] + txt
694+
695+ for zone in self.__reverse_zones().keys():
696+ tokens = zone.split('.')
697+ tokens.reverse()
698+ arpa = '.'.join(tokens) + '.in-addr.arpa'
699+ metadata['reverse_zones'].append((zone, arpa))
700+ txt = """
701+zone "%(arpa)s." {
702+ type master;
703+ file "%(zone)s";
704+};
705+""" % {'arpa': arpa, 'zone': zone}
706+ metadata['zone_include'] = metadata['zone_include'] + txt
707+
708+ try:
709+ f2 = open(template_file,"r")
710+ except:
711+ raise CX(_("error reading template from file: %s") % template_file)
712+ template_data = ""
713+ template_data = f2.read()
714+ f2.close()
715+
716+ if self.logger is not None:
717+ self.logger.info("generating %s" % settings_file)
718+ self.templar.render(template_data, metadata, settings_file, None)
719+
720+ def __ip_sort(self, ips):
721+ """
722+ Sorts IP addresses (or partial addresses) in a numerical fashion per-octet
723+ """
724+ # strings to integer octet chunks so we can sort numerically
725+ octets = map(lambda x: [int(i) for i in x.split('.')], ips)
726+ octets.sort()
727+ # integers back to strings
728+ octets = map(lambda x: [str(i) for i in x], octets)
729+ return ['.'.join(i) for i in octets]
730+
731+ def __pretty_print_host_records(self, hosts, rectype='A', rclass='IN'):
732+ """
733+ Format host records by order and with consistent indentation
734+ """
735+ names = [k for k,v in hosts.iteritems()]
736+ if not names: return '' # zones with no hosts
737+
738+ if rectype == 'PTR':
739+ names = self.__ip_sort(names)
740+ else:
741+ names.sort()
742+
743+ max_name = max([len(i) for i in names])
744+
745+ s = ""
746+ for name in names:
747+ spacing = " " * (max_name - len(name))
748+ my_name = "%s%s" % (name, spacing)
749+ my_host = hosts[name]
750+ s += "%s %s %s %s\n" % (my_name, rclass, rectype, my_host)
751+ return s
752+
753+ def __write_zone_files(self):
754+ """
755+ Write out the forward and reverse zone files for all configured zones
756+ """
757+ default_template_file = "/etc/cobbler/zone.template"
758+ cobbler_server = self.settings.server
759+ serial = int(time.time())
760+ forward = self.__forward_zones()
761+ reverse = self.__reverse_zones()
762+
763+ try:
764+ f2 = open(default_template_file,"r")
765+ except:
766+ raise CX(_("error reading template from file: %s") % default_template_file)
767+ default_template_data = ""
768+ default_template_data = f2.read()
769+ f2.close()
770+
771+ for (zone, hosts) in forward.iteritems():
772+ metadata = {
773+ 'cobbler_server': cobbler_server,
774+ 'serial': serial,
775+ 'host_record': ''
776+ }
777+
778+ # grab zone-specific template if it exists
779+ try:
780+ fd = open('/etc/cobbler/zone_templates/%s' % zone)
781+ template_data = fd.read()
782+ fd.close()
783+ except:
784+ template_data = default_template_data
785+
786+ metadata['host_record'] = self.__pretty_print_host_records(hosts)
787+
788+ zonefilename='/var/named/' + zone
789+ if self.logger is not None:
790+ self.logger.info("generating (forward) %s" % zonefilename)
791+ self.templar.render(template_data, metadata, zonefilename, None)
792+
793+ for (zone, hosts) in reverse.iteritems():
794+ metadata = {
795+ 'cobbler_server': cobbler_server,
796+ 'serial': serial,
797+ 'host_record': ''
798+ }
799+
800+ # grab zone-specific template if it exists
801+ try:
802+ fd = open('/etc/cobbler/zone_templates/%s' % zone)
803+ template_data = fd.read()
804+ fd.close()
805+ except:
806+ template_data = default_template_data
807+
808+ metadata['host_record'] = self.__pretty_print_host_records(hosts, rectype='PTR')
809+
810+ zonefilename='/var/named/' + zone
811+ if self.logger is not None:
812+ self.logger.info("generating (reverse) %s" % zonefilename)
813+ self.templar.render(template_data, metadata, zonefilename, None)
814+
815+
816+ def write_dns_files(self):
817+ """
818+ BIND files are written when manage_dns is set in
819+ /var/lib/cobbler/settings.
820+ """
821+
822+ self.__write_named_conf()
823+ self.__write_zone_files()
824+
825+def get_manager(config,logger):
826+ return BindManager(config,logger)
827
828=== added file '.pc/40_ubuntu_bind9_management.patch/cobbler/modules/sync_post_restart_services.py'
829--- .pc/40_ubuntu_bind9_management.patch/cobbler/modules/sync_post_restart_services.py 1970-01-01 00:00:00 +0000
830+++ .pc/40_ubuntu_bind9_management.patch/cobbler/modules/sync_post_restart_services.py 2011-04-18 12:44:31 +0000
831@@ -0,0 +1,66 @@
832+import distutils.sysconfig
833+import sys
834+import os
835+import traceback
836+import cexceptions
837+import os
838+import sys
839+import xmlrpclib
840+import cobbler.module_loader as module_loader
841+import cobbler.utils as utils
842+
843+plib = distutils.sysconfig.get_python_lib()
844+mod_path="%s/cobbler" % plib
845+sys.path.insert(0, mod_path)
846+
847+def register():
848+ # this pure python trigger acts as if it were a legacy shell-trigger, but is much faster.
849+ # the return of this method indicates the trigger type
850+ return "/var/lib/cobbler/triggers/sync/post/*"
851+
852+def run(api,args,logger):
853+
854+ settings = api.settings()
855+
856+ manage_dhcp = str(settings.manage_dhcp).lower()
857+ manage_dns = str(settings.manage_dns).lower()
858+ manage_tftpd = str(settings.manage_tftpd).lower()
859+ restart_dhcp = str(settings.restart_dhcp).lower()
860+ restart_dns = str(settings.restart_dns).lower()
861+
862+ which_dhcp_module = module_loader.get_module_from_file("dhcp","module",just_name=True).strip()
863+ which_dns_module = module_loader.get_module_from_file("dns","module",just_name=True).strip()
864+
865+ # special handling as we don't want to restart it twice
866+ has_restarted_dnsmasq = False
867+
868+ rc = 0
869+ if manage_dhcp != "0":
870+ if which_dhcp_module == "manage_isc":
871+ if restart_dhcp != "0":
872+ rc = utils.subprocess_call(logger, "dhcpd -t -q", shell=True)
873+ if rc != 0:
874+ logger.error("dhcpd -t failed")
875+ return 1
876+ rc = utils.subprocess_call(logger,"service isc-dhcp-server restart", shell=True)
877+ elif which_dhcp_module == "manage_dnsmasq":
878+ if restart_dhcp != "0":
879+ rc = utils.subprocess_call(logger, "service dnsmasq restart")
880+ has_restarted_dnsmasq = True
881+ else:
882+ logger.error("unknown DHCP engine: %s" % which_dhcp_module)
883+ rc = 411
884+
885+ if manage_dns != "0" and restart_dns != "0":
886+ if which_dns_module == "manage_bind":
887+ rc = utils.subprocess_call(logger, "service named restart", shell=True)
888+ elif which_dns_module == "manage_dnsmasq" and not has_restarted_dnsmasq:
889+ rc = utils.subprocess_call(logger, "service dnsmasq restart", shell=True)
890+ elif which_dns_module == "manage_dnsmasq" and has_restarted_dnsmasq:
891+ rc = 0
892+ else:
893+ logger.error("unknown DNS engine: %s" % which_dns_module)
894+ rc = 412
895+
896+ return rc
897+
898
899=== added directory '.pc/40_ubuntu_bind9_management.patch/templates'
900=== added directory '.pc/40_ubuntu_bind9_management.patch/templates/etc'
901=== added file '.pc/40_ubuntu_bind9_management.patch/templates/etc/named.template'
902--- .pc/40_ubuntu_bind9_management.patch/templates/etc/named.template 1970-01-01 00:00:00 +0000
903+++ .pc/40_ubuntu_bind9_management.patch/templates/etc/named.template 2011-04-18 12:44:31 +0000
904@@ -0,0 +1,31 @@
905+options {
906+ listen-on port 53 { 127.0.0.1; };
907+ directory "/var/named";
908+ dump-file "/var/named/data/cache_dump.db";
909+ statistics-file "/var/named/data/named_stats.txt";
910+ memstatistics-file "/var/named/data/named_mem_stats.txt";
911+ allow-query { localhost; };
912+ recursion yes;
913+};
914+
915+logging {
916+ channel default_debug {
917+ file "data/named.run";
918+ severity dynamic;
919+ };
920+};
921+
922+#for $zone in $forward_zones
923+zone "${zone}." {
924+ type master;
925+ file "$zone";
926+};
927+
928+#end for
929+#for $zone, $arpa in $reverse_zones
930+zone "${arpa}." {
931+ type master;
932+ file "$zone";
933+};
934+
935+#end for
936
937=== modified file '.pc/applied-patches'
938--- .pc/applied-patches 2011-04-15 12:47:39 +0000
939+++ .pc/applied-patches 2011-04-18 12:44:31 +0000
940@@ -10,3 +10,4 @@
941 37_koan_install_tree.patch
942 38_koan_qcreate_ubuntu_support.patch
943 39_cw_remove_vhost.patch
944+40_ubuntu_bind9_management.patch
945
946=== modified file 'cobbler/action_check.py'
947--- cobbler/action_check.py 2011-01-18 12:03:14 +0000
948+++ cobbler/action_check.py 2011-04-18 12:44:31 +0000
949@@ -66,7 +66,7 @@
950 mode = self.config.api.get_sync().dns.what()
951 if mode == "bind":
952 self.check_bind_bin(status)
953- self.check_service(status,"named")
954+ self.check_service(status,"bind9")
955 elif mode == "dnsmasq" and not self.settings.manage_dhcp:
956 self.check_dnsmasq_bin(status)
957 self.check_service(status,"dnsmasq")
958
959=== modified file 'cobbler/modules/manage_bind.py'
960--- cobbler/modules/manage_bind.py 2011-01-18 12:03:14 +0000
961+++ cobbler/modules/manage_bind.py 2011-04-18 12:44:31 +0000
962@@ -180,7 +180,7 @@
963 """
964 Write out the named.conf main config file from the template.
965 """
966- settings_file = "/etc/named.conf"
967+ settings_file = "/etc/bind/named.conf.local"
968 template_file = "/etc/cobbler/named.template"
969 forward_zones = self.settings.manage_forward_zones
970 reverse_zones = self.settings.manage_reverse_zones
971@@ -291,7 +291,7 @@
972
973 metadata['host_record'] = self.__pretty_print_host_records(hosts)
974
975- zonefilename='/var/named/' + zone
976+ zonefilename='/etc/bind/db.' + zone
977 if self.logger is not None:
978 self.logger.info("generating (forward) %s" % zonefilename)
979 self.templar.render(template_data, metadata, zonefilename, None)
980@@ -313,7 +313,7 @@
981
982 metadata['host_record'] = self.__pretty_print_host_records(hosts, rectype='PTR')
983
984- zonefilename='/var/named/' + zone
985+ zonefilename='/etc/bind/db.' + zone
986 if self.logger is not None:
987 self.logger.info("generating (reverse) %s" % zonefilename)
988 self.templar.render(template_data, metadata, zonefilename, None)
989
990=== modified file 'cobbler/modules/sync_post_restart_services.py'
991--- cobbler/modules/sync_post_restart_services.py 2011-01-28 14:39:12 +0000
992+++ cobbler/modules/sync_post_restart_services.py 2011-04-18 12:44:31 +0000
993@@ -53,7 +53,7 @@
994
995 if manage_dns != "0" and restart_dns != "0":
996 if which_dns_module == "manage_bind":
997- rc = utils.subprocess_call(logger, "service named restart", shell=True)
998+ rc = utils.subprocess_call(logger, "service bind9 restart", shell=True)
999 elif which_dns_module == "manage_dnsmasq" and not has_restarted_dnsmasq:
1000 rc = utils.subprocess_call(logger, "service dnsmasq restart", shell=True)
1001 elif which_dns_module == "manage_dnsmasq" and has_restarted_dnsmasq:
1002
1003=== modified file 'debian/changelog'
1004--- debian/changelog 2011-04-15 12:47:39 +0000
1005+++ debian/changelog 2011-04-18 12:44:31 +0000
1006@@ -1,3 +1,14 @@
1007+cobbler (2.1.0-0ubuntu7) natty; urgency=low
1008+
1009+ * Fixed management of bind9 (LP: #764391):
1010+ - debian/patches/40_ubuntu_bind9_management.patch:
1011+ - Manage bind9 instead of named daemon.
1012+ - Generate configuration in /etc/bind.
1013+ - Use default bind9 configuration as much as possible.
1014+ - debian/control: Added Suggests: bind9 to cobbler.
1015+
1016+ -- James Page <james.page@canonical.com> Mon, 18 Apr 2011 11:15:59 +0100
1017+
1018 cobbler (2.1.0-0ubuntu6) natty; urgency=low
1019
1020 * Fix DocumentRoot conflict with default vhost (LP: #760012)
1021
1022=== modified file 'debian/control'
1023--- debian/control 2011-04-04 12:55:44 +0000
1024+++ debian/control 2011-04-18 12:44:31 +0000
1025@@ -34,6 +34,7 @@
1026 cobbler-web,
1027 debmirror
1028 Suggests: createrepo,
1029+ bind9,
1030 dhcp3-server,
1031 genisoimage,
1032 cman,
1033
1034=== added file 'debian/patches/40_ubuntu_bind9_management.patch'
1035--- debian/patches/40_ubuntu_bind9_management.patch 1970-01-01 00:00:00 +0000
1036+++ debian/patches/40_ubuntu_bind9_management.patch 2011-04-18 12:44:31 +0000
1037@@ -0,0 +1,103 @@
1038+Description: Enable management of Ubuntu bind9 with manage_dns setting.
1039+ - Generate /etc/bind/named.conf.local to plug into the standard Ubuntu bind9
1040+ install and preserve the bind9 default installation configuration.
1041+ - Generate /etc/bind/db.$zone to align to bind9 zone file names.
1042+ - Restart/check bind9 rather than named.
1043+Author: James Page <james.page@canonical.com>
1044+Forwarded: not-needed
1045+
1046+Index: fix-764391/templates/etc/named.template
1047+===================================================================
1048+--- fix-764391.orig/templates/etc/named.template 2011-04-18 10:46:43.057345158 +0100
1049++++ fix-764391/templates/etc/named.template 2011-04-18 10:47:23.426906461 +0100
1050+@@ -1,31 +1,14 @@
1051+-options {
1052+- listen-on port 53 { 127.0.0.1; };
1053+- directory "/var/named";
1054+- dump-file "/var/named/data/cache_dump.db";
1055+- statistics-file "/var/named/data/named_stats.txt";
1056+- memstatistics-file "/var/named/data/named_mem_stats.txt";
1057+- allow-query { localhost; };
1058+- recursion yes;
1059+-};
1060+-
1061+-logging {
1062+- channel default_debug {
1063+- file "data/named.run";
1064+- severity dynamic;
1065+- };
1066+-};
1067+-
1068+ #for $zone in $forward_zones
1069+ zone "${zone}." {
1070+ type master;
1071+- file "$zone";
1072++ file "/etc/bind/db.$zone";
1073+ };
1074+
1075+ #end for
1076+ #for $zone, $arpa in $reverse_zones
1077+ zone "${arpa}." {
1078+ type master;
1079+- file "$zone";
1080++ file "/etc/bind/db.$zone";
1081+ };
1082+
1083+ #end for
1084+Index: fix-764391/cobbler/modules/manage_bind.py
1085+===================================================================
1086+--- fix-764391.orig/cobbler/modules/manage_bind.py 2011-04-18 10:47:46.226932274 +0100
1087++++ fix-764391/cobbler/modules/manage_bind.py 2011-04-18 10:49:00.526931926 +0100
1088+@@ -180,7 +180,7 @@
1089+ """
1090+ Write out the named.conf main config file from the template.
1091+ """
1092+- settings_file = "/etc/named.conf"
1093++ settings_file = "/etc/bind/named.conf.local"
1094+ template_file = "/etc/cobbler/named.template"
1095+ forward_zones = self.settings.manage_forward_zones
1096+ reverse_zones = self.settings.manage_reverse_zones
1097+@@ -291,7 +291,7 @@
1098+
1099+ metadata['host_record'] = self.__pretty_print_host_records(hosts)
1100+
1101+- zonefilename='/var/named/' + zone
1102++ zonefilename='/etc/bind/db.' + zone
1103+ if self.logger is not None:
1104+ self.logger.info("generating (forward) %s" % zonefilename)
1105+ self.templar.render(template_data, metadata, zonefilename, None)
1106+@@ -313,7 +313,7 @@
1107+
1108+ metadata['host_record'] = self.__pretty_print_host_records(hosts, rectype='PTR')
1109+
1110+- zonefilename='/var/named/' + zone
1111++ zonefilename='/etc/bind/db.' + zone
1112+ if self.logger is not None:
1113+ self.logger.info("generating (reverse) %s" % zonefilename)
1114+ self.templar.render(template_data, metadata, zonefilename, None)
1115+Index: fix-764391/cobbler/action_check.py
1116+===================================================================
1117+--- fix-764391.orig/cobbler/action_check.py 2011-04-18 10:50:24.566792922 +0100
1118++++ fix-764391/cobbler/action_check.py 2011-04-18 10:50:49.546726457 +0100
1119+@@ -66,7 +66,7 @@
1120+ mode = self.config.api.get_sync().dns.what()
1121+ if mode == "bind":
1122+ self.check_bind_bin(status)
1123+- self.check_service(status,"named")
1124++ self.check_service(status,"bind9")
1125+ elif mode == "dnsmasq" and not self.settings.manage_dhcp:
1126+ self.check_dnsmasq_bin(status)
1127+ self.check_service(status,"dnsmasq")
1128+Index: fix-764391/cobbler/modules/sync_post_restart_services.py
1129+===================================================================
1130+--- fix-764391.orig/cobbler/modules/sync_post_restart_services.py 2011-04-18 10:55:38.985302648 +0100
1131++++ fix-764391/cobbler/modules/sync_post_restart_services.py 2011-04-18 10:55:56.105188050 +0100
1132+@@ -53,7 +53,7 @@
1133+
1134+ if manage_dns != "0" and restart_dns != "0":
1135+ if which_dns_module == "manage_bind":
1136+- rc = utils.subprocess_call(logger, "service named restart", shell=True)
1137++ rc = utils.subprocess_call(logger, "service bind9 restart", shell=True)
1138+ elif which_dns_module == "manage_dnsmasq" and not has_restarted_dnsmasq:
1139+ rc = utils.subprocess_call(logger, "service dnsmasq restart", shell=True)
1140+ elif which_dns_module == "manage_dnsmasq" and has_restarted_dnsmasq:
1141
1142=== modified file 'debian/patches/series'
1143--- debian/patches/series 2011-04-15 12:47:39 +0000
1144+++ debian/patches/series 2011-04-18 12:44:31 +0000
1145@@ -10,3 +10,4 @@
1146 37_koan_install_tree.patch
1147 38_koan_qcreate_ubuntu_support.patch
1148 39_cw_remove_vhost.patch
1149+40_ubuntu_bind9_management.patch
1150
1151=== modified file 'templates/etc/named.template'
1152--- templates/etc/named.template 2011-01-18 12:03:14 +0000
1153+++ templates/etc/named.template 2011-04-18 12:44:31 +0000
1154@@ -1,31 +1,14 @@
1155-options {
1156- listen-on port 53 { 127.0.0.1; };
1157- directory "/var/named";
1158- dump-file "/var/named/data/cache_dump.db";
1159- statistics-file "/var/named/data/named_stats.txt";
1160- memstatistics-file "/var/named/data/named_mem_stats.txt";
1161- allow-query { localhost; };
1162- recursion yes;
1163-};
1164-
1165-logging {
1166- channel default_debug {
1167- file "data/named.run";
1168- severity dynamic;
1169- };
1170-};
1171-
1172 #for $zone in $forward_zones
1173 zone "${zone}." {
1174 type master;
1175- file "$zone";
1176+ file "/etc/bind/db.$zone";
1177 };
1178
1179 #end for
1180 #for $zone, $arpa in $reverse_zones
1181 zone "${arpa}." {
1182 type master;
1183- file "$zone";
1184+ file "/etc/bind/db.$zone";
1185 };
1186
1187 #end for

Subscribers

People subscribed via source and target branches

to all changes: