import tempfile
import time
import shutil
+import pipes
from subprocess import Popen, TimeoutExpired, PIPE
from .pidfile import PidFileError, InvalidPidFileError, PidFileInUseError, PidFile
-__version__ = '0.3.2'
+__version__ = '0.4.1'
LOG = logging.getLogger(__name__)
self.generate_slave_cfg_file()
self.compare_files()
+ try:
+ self.replace_configfiles()
+ if not self.check_namedconf():
+ self.restore_configfiles()
+ self.exit(99)
+ self.apply_config()
+ except Exception:
+ self.restore_configfiles()
+ raise
+
finally:
self.cleanup()
self.pidfile = None
return True
+ # -------------------------------------------------------------------------
+ def replace_configfiles(self):
+
+ if not self.files2replace:
+ LOG.debug("No replacement of any config files necessary.")
+ return
+
+ LOG.debug("Start replacing of config files ...")
+
+ for tgt_file in self.files2replace.keys():
+
+ backup_file = tgt_file + self.backup_suffix
+
+ if os.path.exists(tgt_file):
+ self.moved_files[tgt_file] = backup_file
+ LOG.info("Copying {!r} => {!r} ...".format(tgt_file, backup_file))
+ if not self.simulate:
+ shutil.copy2(tgt_file, backup_file)
+
+ if self.verbose > 1:
+ LOG.debug("All backuped config files:\n{}".format(pp(self.moved_files)))
+
+ for tgt_file in self.files2replace.keys():
+ src_file = self.files2replace[tgt_file]
+ LOG.info("Copying {!r} => {!r} ...".format(src_file, tgt_file))
+ if not self.simulate:
+ shutil.copy2(src_file, tgt_file)
+
+ # -------------------------------------------------------------------------
+ def restore_configfiles(self):
+
+ LOG.error("Restoring of original config files because of an exception.")
+
+ for tgt_file in self.moved_files.keys():
+ backup_file = self.moved_files[tgt_file]
+ LOG.info("Moving {!r} => {!r} ...".format(backup_file, tgt_file))
+ if not self.simulate:
+ if os.path.exists(backup_file):
+ os.rename(backup_file, tgt_file)
+ else:
+ LOG.error("Could not find backup file {!r}.".format(backup_file))
+
+ # -------------------------------------------------------------------------
+ def check_namedconf(self):
+
+ LOG.info("Checking syntax correctness of named.conf ...")
+ cmd = shlex.split(self.cmd_checkconf)
+ if 'named-checkconf' in self.cmd_checkconf and self.verbose > 2:
+ cmd.append('-p')
+ cmd_str = ' '.join(map(lambda x: pipes.quote(x), cmd))
+ LOG.debug("Executing: {}".format(cmd_str))
+
+ std_out = None
+ std_err = None
+ ret_val = None
+
+ with Popen(cmd, stdout=PIPE, stderr=PIPE) as proc:
+ try:
+ std_out, std_err = proc.communicate(timeout=10)
+ except TimeoutExpired:
+ proc.kill()
+ std_out, std_err = proc.communicate()
+ ret_val = proc.wait()
+
+ LOG.debug("Return value: {!r}".format(ret_val))
+ if std_out and std_out.strip():
+ s = to_str(std_out.strip())
+ LOG.warn("Output on STDOUT: {}".format(s))
+ if std_err and std_err.strip():
+ s = to_str(std_err.strip())
+ LOG.warn("Output on STDERR: {}".format(s))
+
+ if ret_val:
+ return False
+
+ return True
+
+ # -------------------------------------------------------------------------
+ def apply_config(self):
+
+ if not self.reload_necessary and not self.restart_necessary:
+ LOG.info("Reload or restart of named is not necessary.")
+ return
+
+ running = self.named_running()
+ if not running:
+ LOG.warn("Named is not running, please start it manually.")
+ return
+
+ if self.restart_necessary:
+ self.restart_named()
+ else:
+ self.reload_named()
+
+ # -------------------------------------------------------------------------
+ def named_running(self):
+
+ LOG.debug("Checking, whether named is running ...")
+
+ cmd = shlex.split(self.cmd_status)
+ cmd_str = ' '.join(map(lambda x: pipes.quote(x), cmd))
+ LOG.debug("Executing: {}".format(cmd_str))
+
+ std_out = None
+ std_err = None
+ ret_val = None
+
+ with Popen(cmd, stdout=PIPE, stderr=PIPE) as proc:
+ try:
+ std_out, std_err = proc.communicate(timeout=10)
+ except TimeoutExpired:
+ proc.kill()
+ std_out, std_err = proc.communicate()
+ ret_val = proc.wait()
+
+ LOG.debug("Return value: {!r}".format(ret_val))
+ if std_out and std_out.strip():
+ s = to_str(std_out.strip())
+ LOG.debug("Output on STDOUT:\n{}".format(s))
+ if std_err and std_err.strip():
+ s = to_str(std_err.strip())
+ LOG.warn("Output on STDERR: {}".format(s))
+
+ if ret_val:
+ return False
+
+ return True
+
+ # -------------------------------------------------------------------------
+ def start_named(self):
+
+ LOG.info("Starting named ...")
+
+ cmd = shlex.split(self.cmd_start)
+ cmd_str = ' '.join(map(lambda x: pipes.quote(x), cmd))
+ LOG.debug("Executing: {}".format(cmd_str))
+
+ if self.simulate:
+ return
+
+ std_out = None
+ std_err = None
+ ret_val = None
+
+ with Popen(cmd, stdout=PIPE, stderr=PIPE) as proc:
+ try:
+ std_out, std_err = proc.communicate(timeout=30)
+ except TimeoutExpired:
+ proc.kill()
+ std_out, std_err = proc.communicate()
+ ret_val = proc.wait()
+
+ LOG.debug("Return value: {!r}".format(ret_val))
+ if std_out and std_out.strip():
+ s = to_str(std_out.strip())
+ LOG.debug("Output on STDOUT:\n{}".format(s))
+ if std_err and std_err.strip():
+ s = to_str(std_err.strip())
+ LOG.error("Output on STDERR: {}".format(s))
+
+ if ret_val:
+ return False
+
+ return True
+
+ # -------------------------------------------------------------------------
+ def restart_named(self):
+
+ LOG.info("Restarting named ...")
+
+ cmd = shlex.split(self.cmd_restart)
+ cmd_str = ' '.join(map(lambda x: pipes.quote(x), cmd))
+ LOG.debug("Executing: {}".format(cmd_str))
+
+ if self.simulate:
+ return
+
+ std_out = None
+ std_err = None
+ ret_val = None
+
+ with Popen(cmd, stdout=PIPE, stderr=PIPE) as proc:
+ try:
+ std_out, std_err = proc.communicate(timeout=30)
+ except TimeoutExpired:
+ proc.kill()
+ std_out, std_err = proc.communicate()
+ ret_val = proc.wait()
+
+ LOG.debug("Return value: {!r}".format(ret_val))
+ if std_out and std_out.strip():
+ s = to_str(std_out.strip())
+ LOG.debug("Output on STDOUT:\n{}".format(s))
+ if std_err and std_err.strip():
+ s = to_str(std_err.strip())
+ LOG.error("Output on STDERR: {}".format(s))
+
+ if ret_val:
+ return False
+
+ return True
+
+ # -------------------------------------------------------------------------
+ def reload_named(self):
+
+ LOG.info("Reloading named ...")
+
+ cmd = shlex.split(self.cmd_reload)
+ cmd_str = ' '.join(map(lambda x: pipes.quote(x), cmd))
+ LOG.debug("Executing: {}".format(cmd_str))
+
+ if self.simulate:
+ return
+
+ std_out = None
+ std_err = None
+ ret_val = None
+
+ with Popen(cmd, stdout=PIPE, stderr=PIPE) as proc:
+ try:
+ std_out, std_err = proc.communicate(timeout=30)
+ except TimeoutExpired:
+ proc.kill()
+ std_out, std_err = proc.communicate()
+ ret_val = proc.wait()
+
+ LOG.debug("Return value: {!r}".format(ret_val))
+ if std_out and std_out.strip():
+ s = to_str(std_out.strip())
+ LOG.debug("Output on STDOUT:\n{}".format(s))
+ if std_err and std_err.strip():
+ s = to_str(std_err.strip())
+ LOG.error("Output on STDERR: {}".format(s))
+
+ if ret_val:
+ return False
+
+ return True
+
# =============================================================================