def testPidFileFunctions(self): pid_file = self.f_dpn("test") fd = utils.WritePidFile(self.f_dpn("test")) self.failUnless(os.path.exists(pid_file), "PID file should have been created") read_pid = utils.ReadPidFile(pid_file) self.failUnlessEqual(read_pid, os.getpid()) self.failUnless(utils.IsProcessAlive(read_pid)) self.failUnlessRaises(errors.PidFileLockError, utils.WritePidFile, self.f_dpn("test")) os.close(fd) utils.RemoveFile(self.f_dpn("test")) self.failIf(os.path.exists(pid_file), "PID file should not exist anymore") self.failUnlessEqual( utils.ReadPidFile(pid_file), 0, "ReadPidFile should return 0 for missing pid file") fh = open(pid_file, "w") fh.write("blah\n") fh.close() self.failUnlessEqual( utils.ReadPidFile(pid_file), 0, "ReadPidFile should return 0 for invalid pid file") # but now, even with the file existing, we should be able to lock it fd = utils.WritePidFile(self.f_dpn("test")) os.close(fd) utils.RemoveFile(self.f_dpn("test")) self.failIf(os.path.exists(pid_file), "PID file should not exist anymore")
def testRemoveSymlink(self): """Test that RemoveFile does remove symlinks""" symlink = self.tmpdir + "/symlink" os.symlink("no-such-file", symlink) utils.RemoveFile(symlink) if os.path.exists(symlink): self.fail("File '%s' not removed" % symlink) os.symlink(self.tmpfile, symlink) utils.RemoveFile(symlink) if os.path.exists(symlink): self.fail("File '%s' not removed" % symlink)
def testKill(self): pid_file = self.f_dpn("child") r_fd, w_fd = os.pipe() new_pid = os.fork() if new_pid == 0: #child utils.WritePidFile(self.f_dpn("child")) os.write(w_fd, "a") signal.pause() os._exit(0) return # else we are in the parent # wait until the child has written the pid file os.read(r_fd, 1) read_pid = utils.ReadPidFile(pid_file) self.failUnlessEqual(read_pid, new_pid) self.failUnless(utils.IsProcessAlive(new_pid)) # Try writing to locked file try: utils.WritePidFile(pid_file) except errors.PidFileLockError as err: errmsg = str(err) self.assertTrue(errmsg.endswith(" %s" % new_pid), msg=("Error message ('%s') didn't contain correct" " PID (%s)" % (errmsg, new_pid))) else: self.fail("Writing to locked file didn't fail") utils.KillProcess(new_pid, waitpid=True) self.failIf(utils.IsProcessAlive(new_pid)) utils.RemoveFile(self.f_dpn("child")) self.failUnlessRaises(errors.ProgrammerError, utils.KillProcess, 0)
def testStartInstance(self): (inst, disks) = self._MakeInstance() pathutils.LOG_XEN_DIR = self.tmpdir for failcreate in [False, True]: for paused in [False, True]: run_cmd = compat.partial(self._StartInstanceCommand, inst, paused, failcreate) hv = self._GetHv(run_cmd=run_cmd) # Ensure instance is not listed self.assertTrue(inst.name not in hv.ListInstances()) # Remove configuration cfgfile = utils.PathJoin(self.tmpdir, inst.name) utils.RemoveFile(cfgfile) if failcreate: self.assertRaises(errors.HypervisorError, hv.StartInstance, inst, disks, paused) # Check whether a stale config file is left behind self.assertFalse(os.path.exists(cfgfile)) else: hv.StartInstance(inst, disks, paused) # Check if configuration was updated lines = utils.ReadFile(cfgfile).splitlines() if constants.HV_VNC_PASSWORD_FILE in inst.hvparams: self.assertTrue(("vncpasswd = '%s'" % self.vncpw) in lines) else: extra = inst.hvparams[constants.HV_KERNEL_ARGS] self.assertTrue(("extra = '%s'" % extra) in lines)
def InitSSHSetup(error_fn=errors.OpPrereqError, _homedir_fn=None, _suffix=""): """Setup the SSH configuration for the node. This generates a dsa keypair for root, adds the pub key to the permitted hosts and adds the hostkey to its own known hosts. """ priv_key, pub_key, auth_keys = GetUserFiles(constants.SSH_LOGIN_USER, _homedir_fn=_homedir_fn) for name in priv_key, pub_key: if os.path.exists(name): utils.CreateBackup(name) if len(_suffix) == 0: utils.RemoveFile(name) new_priv_key_name = priv_key + _suffix new_pub_key_name = priv_key + _suffix + ".pub" result = utils.RunCmd( ["ssh-keygen", "-t", "dsa", "-f", new_priv_key_name, "-q", "-N", ""]) if result.failed: raise error_fn("Could not generate ssh keypair, error %s" % result.output) AddAuthorizedKey(auth_keys, utils.ReadFile(new_pub_key_name))
def RemoveAuthorizedKeys(file_name, keys): """Removes public SSH keys from an authorized_keys file. @type file_name: str @param file_name: path to authorized_keys file @type keys: list of str @param keys: list of strings containing keys """ key_field_list = [_SplitSshKey(key) for key in keys] fd, tmpname = tempfile.mkstemp(dir=os.path.dirname(file_name)) try: out = os.fdopen(fd, "w") try: f = open(file_name, "r") try: for line in f: # Ignore whitespace changes while comparing lines if _SplitSshKey(line) not in key_field_list: out.write(line) out.flush() os.rename(tmpname, file_name) finally: f.close() finally: out.close() except: utils.RemoveFile(tmpname) raise
def UpgradeWatcher(self): # Remove old watcher state file if it exists if os.path.exists(self.opts.WATCHER_STATEFILE): logging.info("Removing watcher state file %s", self.opts.WATCHER_STATEFILE) if not self.opts.dry_run: utils.RemoveFile(self.opts.WATCHER_STATEFILE)
def InitSSHSetup(key_type, key_bits, error_fn=errors.OpPrereqError, _homedir_fn=None, _suffix=""): """Setup the SSH configuration for the node. This generates a dsa keypair for root, adds the pub key to the permitted hosts and adds the hostkey to its own known hosts. @param key_type: the type of SSH keypair to be generated @param key_bits: the key length, in bits, to be used """ priv_key, _, auth_keys = GetUserFiles(constants.SSH_LOGIN_USER, kind=key_type, mkdir=True, _homedir_fn=_homedir_fn) new_priv_key_name = priv_key + _suffix new_pub_key_name = priv_key + _suffix + ".pub" for name in new_priv_key_name, new_pub_key_name: if os.path.exists(name): utils.CreateBackup(name) utils.RemoveFile(name) result = utils.RunCmd(["ssh-keygen", "-b", str(key_bits), "-t", key_type, "-f", new_priv_key_name, "-q", "-N", ""]) if result.failed: raise error_fn("Could not generate ssh keypair, error %s" % result.output) AddAuthorizedKey(auth_keys, utils.ReadFile(new_pub_key_name))
def _MarkDown(self, instance_name): """Mark the instance as running. This does no checks, which should be done by its callers. """ file_name = self._InstanceFile(instance_name) utils.RemoveFile(file_name)
def CloseMultiplexers(): """Closes all current multiplexers and cleans up. """ for node in _MULTIPLEXERS.keys(): (sname, child) = _MULTIPLEXERS.pop(node) utils.KillProcess(child.pid, timeout=10, waitpid=True) utils.RemoveFile(sname)
def _RemoveConfigFile(self, instance_name): """Remove the xen configuration file. """ utils.RemoveFile(self._ConfigFileName(instance_name)) try: shutil.rmtree(self._InstanceNICDir(instance_name)) except OSError, err: if err.errno != errno.ENOENT: raise
def Main(): """Main routine. """ opts = ParseOptions() utils.SetupToolLogging(opts.debug, opts.verbose, toolname=os.path.splitext( os.path.basename(__file__))[0]) try: # List of files to delete. Contains tuples consisting of the absolute path # and a boolean denoting whether a backup copy should be created before # deleting. clean_files = [ (pathutils.CONFD_HMAC_KEY, True), (pathutils.CLUSTER_CONF_FILE, True), (pathutils.CLUSTER_DOMAIN_SECRET_FILE, True), ] clean_files.extend(map(lambda s: (s, True), pathutils.ALL_CERT_FILES)) clean_files.extend( map(lambda s: (s, False), ssconf.SimpleStore().GetFileList())) if not opts.yes_do_it: cli.ToStderr( "Cleaning a node is irreversible. If you really want to" " clean this node, supply the --yes-do-it option.") return constants.EXIT_FAILURE logging.info("Stopping daemons") result = utils.RunCmd([pathutils.DAEMON_UTIL, "stop-all"], interactive=True) if result.failed: raise Exception("Could not stop daemons, command '%s' failed: %s" % (result.cmd, result.fail_reason)) for (filename, backup) in clean_files: if os.path.exists(filename): if opts.backup and backup: logging.info("Backing up %s", filename) utils.CreateBackup(filename) logging.info("Removing %s", filename) utils.RemoveFile(filename) logging.info("Node successfully cleaned") except Exception, err: # pylint: disable=W0703 logging.debug("Caught unhandled exception", exc_info=True) (retcode, message) = cli.FormatError(err) logging.error(message) return retcode
def PrepMasterd(options, _): """Prep master daemon function, executed with the PID file held. """ # This is safe to do as the pid file guarantees against # concurrent execution. utils.RemoveFile(pathutils.MASTER_SOCKET) mainloop = daemon.Mainloop() master = MasterServer(pathutils.MASTER_SOCKET, options.uid, options.gid) return (mainloop, master)
def tearDown(self): while self._temp_files: try: utils.RemoveFile(self._temp_files.pop()) except EnvironmentError: pass for patch in self.patches.values(): patch.stop() self.patches = {} self.mocks = {}
def _WriteConfigFile(self, instance_name, data): """Write the Xen config file for the instance. This version of the function just writes the config file from static data. """ # just in case it exists utils.RemoveFile(utils.PathJoin(self._cfgdir, "auto", instance_name)) cfg_file = self._ConfigFileName(instance_name) try: utils.WriteFile(cfg_file, data=data) except EnvironmentError, err: raise errors.HypervisorError("Cannot write Xen instance configuration" " file %s: %s" % (cfg_file, err))
def testMountpoint(self): lvfmp_fn = compat.partial(utils.ListVisibleFiles, _is_mountpoint=lambda _: True) self.assertEqual(lvfmp_fn(self.path), []) # Create "lost+found" as a regular file self._CreateFiles(["foo", "bar", ".baz", "lost+found"]) self.assertEqual(set(lvfmp_fn(self.path)), set(["foo", "bar", "lost+found"])) # Replace "lost+found" with a directory laf_path = utils.PathJoin(self.path, "lost+found") utils.RemoveFile(laf_path) os.mkdir(laf_path) self.assertEqual(set(lvfmp_fn(self.path)), set(["foo", "bar"]))
def StartMultiplexer(node): """Starts a multiplexer command. @param node: the node for which to open the multiplexer """ if node in _MULTIPLEXERS: return # Note: yes, we only need mktemp, since we'll remove the file anyway sname = tempfile.mktemp(prefix="ganeti-qa-multiplexer.") utils.RemoveFile(sname) opts = ["-N", "-oControlPath=%s" % sname, "-oControlMaster=yes"] print "Created socket at %s" % sname child = StartLocalCommand(GetSSHCommand(node, None, opts=opts)) _MULTIPLEXERS[node] = (sname, child)
def _CleanupInstance(self, instance_name, stash): """Actual implementation of the instance cleanup procedure. @type instance_name: string @param instance_name: instance name @type stash: dict(string:any) @param stash: dict that contains desired information for instance cleanup """ try: if self._STASH_KEY_ALLOCATED_LOOP_DEV in stash: loop_dev_path = stash[self._STASH_KEY_ALLOCATED_LOOP_DEV] utils.ReleaseBdevPartitionMapping(loop_dev_path) except errors.CommandError as err: raise HypervisorError("Failed to cleanup partition mapping : %s" % err) utils.RemoveFile(self._InstanceStashFilePath(instance_name))
def SetDrainFlag(drain_flag): """Sets the drain flag for the queue. @type drain_flag: boolean @param drain_flag: Whether to set or unset the drain flag @attention: This function should only called the current holder of the queue lock """ getents = runtime.GetEnts() if drain_flag: utils.WriteFile(pathutils.JOB_QUEUE_DRAIN_FILE, data="", uid=getents.masterd_uid, gid=getents.daemons_gid, mode=constants.JOB_QUEUE_FILES_PERMS) else: utils.RemoveFile(pathutils.JOB_QUEUE_DRAIN_FILE) assert (not drain_flag) ^ CheckDrainFlag()
def ExecMasterd(options, args, prep_data): # pylint: disable=W0613 """Main master daemon function, executed with the PID file held. """ (mainloop, master) = prep_data try: rpc.Init() try: master.setup_context() try: mainloop.Run(shutdown_wait_fn=master.WaitForShutdown) finally: master.server_cleanup() finally: rpc.Shutdown() finally: utils.RemoveFile(pathutils.MASTER_SOCKET) logging.info("Clean master daemon shutdown")
def ReplaceSshKeys(src_key_type, dest_key_type, src_key_suffix="", dest_key_suffix=""): """Replaces an SSH key pair by another SSH key pair. Note that both parts, the private and the public key, are replaced. @type src_key_type: string @param src_key_type: key type of key pair that is replacing the other key pair @type dest_key_type: string @param dest_key_type: key type of the key pair that is being replaced by the source key pair @type src_key_suffix: string @param src_key_suffix: optional suffix of the key files of the source key pair @type dest_key_suffix: string @param dest_key_suffix: optional suffix of the keey files of the destination key pair """ (src_priv_filename, src_pub_filename) = GetSshKeyFilenames(src_key_type, suffix=src_key_suffix) (dest_priv_filename, dest_pub_filename) = GetSshKeyFilenames(dest_key_type, suffix=dest_key_suffix) if not (os.path.exists(src_priv_filename) and os.path.exists(src_pub_filename)): raise errors.SshUpdateError( "At least one of the source key files is missing: %s", ", ".join([src_priv_filename, src_pub_filename])) for dest_file in [dest_priv_filename, dest_pub_filename]: if os.path.exists(dest_file): utils.CreateBackup(dest_file) utils.RemoveFile(dest_file) shutil.move(src_priv_filename, dest_priv_filename) shutil.move(src_pub_filename, dest_pub_filename)
def _InitSSHSetup(): """Setup the SSH configuration for the cluster. This generates a dsa keypair for root, adds the pub key to the permitted hosts and adds the hostkey to its own known hosts. """ priv_key, pub_key, auth_keys = ssh.GetUserFiles(constants.SSH_LOGIN_USER) for name in priv_key, pub_key: if os.path.exists(name): utils.CreateBackup(name) utils.RemoveFile(name) result = utils.RunCmd( ["ssh-keygen", "-t", "dsa", "-f", priv_key, "-q", "-N", ""]) if result.failed: raise errors.OpExecError("Could not generate ssh keypair, error %s" % result.output) utils.AddAuthorizedKey(auth_keys, utils.ReadFile(pub_key))
def GenericMain(daemon_name, optionparser, check_fn, prepare_fn, exec_fn, multithreaded=False, console_logging=False, default_ssl_cert=None, default_ssl_key=None, warn_breach=False): """Shared main function for daemons. @type daemon_name: string @param daemon_name: daemon name @type optionparser: optparse.OptionParser @param optionparser: initialized optionparser with daemon-specific options (common -f -d options will be handled by this module) @type check_fn: function which accepts (options, args) @param check_fn: function that checks start conditions and exits if they're not met @type prepare_fn: function which accepts (options, args) @param prepare_fn: function that is run before forking, or None; it's result will be passed as the third parameter to exec_fn, or if None was passed in, we will just pass None to exec_fn @type exec_fn: function which accepts (options, args, prepare_results) @param exec_fn: function that's executed with the daemon's pid file held, and runs the daemon itself. @type multithreaded: bool @param multithreaded: Whether the daemon uses threads @type console_logging: boolean @param console_logging: if True, the daemon will fall back to the system console if logging fails @type default_ssl_cert: string @param default_ssl_cert: Default SSL certificate path @type default_ssl_key: string @param default_ssl_key: Default SSL key path @type warn_breach: bool @param warn_breach: issue a warning at daemon launch time, before daemonizing, about the possibility of breaking parameter privacy invariants through the otherwise helpful debug logging. """ optionparser.add_option("-f", "--foreground", dest="fork", help="Don't detach from the current terminal", default=True, action="store_false") optionparser.add_option("-d", "--debug", dest="debug", help="Enable some debug messages", default=False, action="store_true") optionparser.add_option("--syslog", dest="syslog", help="Enable logging to syslog (except debug" " messages); one of 'no', 'yes' or 'only' [%s]" % constants.SYSLOG_USAGE, default=constants.SYSLOG_USAGE, choices=["no", "yes", "only"]) family = ssconf.SimpleStore().GetPrimaryIPFamily() # family will default to AF_INET if there is no ssconf file (e.g. when # upgrading a cluster from 2.2 -> 2.3. This is intended, as Ganeti clusters # <= 2.2 can not be AF_INET6 if daemon_name in constants.DAEMONS_PORTS: default_bind_address = constants.IP4_ADDRESS_ANY if family == netutils.IP6Address.family: default_bind_address = constants.IP6_ADDRESS_ANY default_port = netutils.GetDaemonPort(daemon_name) # For networked daemons we allow choosing the port and bind address optionparser.add_option("-p", "--port", dest="port", help="Network port (default: %s)" % default_port, default=default_port, type="int") optionparser.add_option("-b", "--bind", dest="bind_address", help=("Bind address (default: '%s')" % default_bind_address), default=default_bind_address, metavar="ADDRESS") optionparser.add_option("-i", "--interface", dest="bind_interface", help=("Bind interface"), metavar="INTERFACE") if default_ssl_key is not None and default_ssl_cert is not None: optionparser.add_option("--no-ssl", dest="ssl", help="Do not secure HTTP protocol with SSL", default=True, action="store_false") optionparser.add_option("-K", "--ssl-key", dest="ssl_key", help=("SSL key path (default: %s)" % default_ssl_key), default=default_ssl_key, type="string", metavar="SSL_KEY_PATH") optionparser.add_option("-C", "--ssl-cert", dest="ssl_cert", help=("SSL certificate path (default: %s)" % default_ssl_cert), default=default_ssl_cert, type="string", metavar="SSL_CERT_PATH") # Disable the use of fork(2) if the daemon uses threads if multithreaded: utils.DisableFork() options, args = optionparser.parse_args() if getattr(options, "bind_interface", None) is not None: if options.bind_address != default_bind_address: msg = ( "Can't specify both, bind address (%s) and bind interface (%s)" % (options.bind_address, options.bind_interface)) print(msg, file=sys.stderr) sys.exit(constants.EXIT_FAILURE) interface_ip_addresses = \ netutils.GetInterfaceIpAddresses(options.bind_interface) if family == netutils.IP6Address.family: if_addresses = interface_ip_addresses[constants.IP6_VERSION] else: if_addresses = interface_ip_addresses[constants.IP4_VERSION] if len(if_addresses) < 1: msg = "Failed to find IP for interface %s" % options.bind_interace print(msg, file=sys.stderr) sys.exit(constants.EXIT_FAILURE) options.bind_address = if_addresses[0] if getattr(options, "ssl", False): ssl_paths = { "certificate": options.ssl_cert, "key": options.ssl_key, } for name, path in ssl_paths.items(): if not os.path.isfile(path): print("SSL %s file '%s' was not found" % (name, path), file=sys.stderr) sys.exit(constants.EXIT_FAILURE) # TODO: By initiating http.HttpSslParams here we would only read the files # once and have a proper validation (isfile returns False on directories) # at the same time. result, running_uid, expected_uid = _VerifyDaemonUser(daemon_name) if not result: msg = ("%s started using wrong user ID (%d), expected %d" % (daemon_name, running_uid, expected_uid)) print(msg, file=sys.stderr) sys.exit(constants.EXIT_FAILURE) if check_fn is not None: check_fn(options, args) log_filename = constants.DAEMONS_LOGFILES[daemon_name] # node-daemon logging in lib/http/server.py, _HandleServerRequestInner if options.debug and warn_breach: sys.stderr.write(constants.DEBUG_MODE_CONFIDENTIALITY_WARNING % daemon_name) if options.fork: # Newer GnuTLS versions (>= 3.3.0) use a library constructor for # initialization and open /dev/urandom on library load time, way before we # fork(). Closing /dev/urandom causes subsequent ganeti.http.client # requests to fail and the process to receive a SIGABRT. As we cannot # reliably detect GnuTLS's socket, we work our way around this by keeping # all fds referring to /dev/urandom open. noclose_fds = [] for fd in os.listdir("/proc/self/fd"): try: if os.readlink(os.path.join("/proc/self/fd", fd)) == "/dev/urandom": noclose_fds.append(int(fd)) except EnvironmentError: # The fd might have disappeared (although it shouldn't as we're running # single-threaded). continue utils.CloseFDs(noclose_fds=noclose_fds) (wpipe, stdio_reopen_fn) = utils.Daemonize(logfile=log_filename) else: (wpipe, stdio_reopen_fn) = (None, None) log_reopen_fn = \ utils.SetupLogging(log_filename, daemon_name, debug=options.debug, stderr_logging=not options.fork, multithreaded=multithreaded, syslog=options.syslog, console_logging=console_logging) # Reopen log file(s) on SIGHUP signal.signal( signal.SIGHUP, compat.partial(_HandleSigHup, [log_reopen_fn, stdio_reopen_fn])) try: utils.WritePidFile(utils.DaemonPidFileName(daemon_name)) except errors.PidFileLockError as err: print("Error while locking PID file:\n%s" % err, file=sys.stderr) sys.exit(constants.EXIT_FAILURE) try: try: logging.info("%s daemon startup", daemon_name) if callable(prepare_fn): prep_results = prepare_fn(options, args) else: prep_results = None except Exception as err: utils.WriteErrorToFD(wpipe, _BeautifyError(err)) raise if wpipe is not None: # we're done with the preparation phase, we close the pipe to # let the parent know it's safe to exit os.close(wpipe) exec_fn(options, args, prep_results) finally: utils.RemoveFile(utils.DaemonPidFileName(daemon_name))
def tearDown(self): while self._temp_files: try: utils.RemoveFile(self._temp_files.pop()) except EnvironmentError: pass
def main(): debug = int(os.environ["GNT_DEBUG"]) logname = pathutils.GetLogFilename("jobs") utils.SetupLogging(logname, "job-startup", debug=debug) (job_id, llock, secret_params_serialized) = _SetupJob() secret_params = "" if secret_params_serialized: secret_params_json = serializer.LoadJson(secret_params_serialized) secret_params = RestorePrivateValueWrapping(secret_params_json) utils.SetupLogging(logname, "job-%s" % (job_id,), debug=debug) try: logging.debug("Preparing the context and the configuration") context = masterd.GanetiContext(llock) logging.debug("Registering signal handlers") cancel = [False] prio_change = [False] def _TermHandler(signum, _frame): logging.info("Killed by signal %d", signum) cancel[0] = True signal.signal(signal.SIGTERM, _TermHandler) def _HupHandler(signum, _frame): logging.debug("Received signal %d, old flag was %s, will set to True", signum, mcpu.sighupReceived) mcpu.sighupReceived[0] = True signal.signal(signal.SIGHUP, _HupHandler) def _User1Handler(signum, _frame): logging.info("Received signal %d, indicating priority change", signum) prio_change[0] = True signal.signal(signal.SIGUSR1, _User1Handler) job = context.jobqueue.SafeLoadJobFromDisk(job_id, False) job.SetPid(os.getpid()) if secret_params: for i in range(0, len(secret_params)): if hasattr(job.ops[i].input, "osparams_secret"): job.ops[i].input.osparams_secret = secret_params[i] execfun = mcpu.Processor(context, job_id, job_id).ExecOpCode proc = _JobProcessor(context.jobqueue, execfun, job) result = _JobProcessor.DEFER while result != _JobProcessor.FINISHED: result = proc() if result == _JobProcessor.WAITDEP and not cancel[0]: # Normally, the scheduler should avoid starting a job where the # dependencies are not yet finalised. So warn, but wait an continue. logging.warning("Got started despite a dependency not yet finished") time.sleep(5) if cancel[0]: logging.debug("Got cancel request, cancelling job %d", job_id) r = context.jobqueue.CancelJob(job_id) job = context.jobqueue.SafeLoadJobFromDisk(job_id, False) proc = _JobProcessor(context.jobqueue, execfun, job) logging.debug("CancelJob result for job %d: %s", job_id, r) cancel[0] = False if prio_change[0]: logging.debug("Received priority-change request") try: fname = os.path.join(pathutils.LUXID_MESSAGE_DIR, "%d.prio" % job_id) new_prio = int(utils.ReadFile(fname)) utils.RemoveFile(fname) logging.debug("Changing priority of job %d to %d", job_id, new_prio) r = context.jobqueue.ChangeJobPriority(job_id, new_prio) job = context.jobqueue.SafeLoadJobFromDisk(job_id, False) proc = _JobProcessor(context.jobqueue, execfun, job) logging.debug("Result of changing priority of %d to %d: %s", job_id, new_prio, r) except Exception: # pylint: disable=W0703 logging.warning("Informed of priority change, but could not" " read new priority") prio_change[0] = False except Exception: # pylint: disable=W0703 logging.exception("Exception when trying to run job %d", job_id) finally: logging.debug("Job %d finalized", job_id) logging.debug("Removing livelock file %s", llock.GetPath()) os.remove(llock.GetPath()) sys.exit(0)
def testRemoveFile(self): """Test that RemoveFile does remove a file""" utils.RemoveFile(self.tmpfile) if os.path.exists(self.tmpfile): self.fail("File '%s' not removed" % self.tmpfile)
def testIgnoreNotExisting(self): """Test that RemoveFile() ignores non-existing files""" utils.RemoveFile(self.tmpfile) utils.RemoveFile(self.tmpfile)
def testIgnoreDirs(self): """Test that RemoveFile() ignores directories""" self.assertEqual(None, utils.RemoveFile(self.tmpdir))
self.failUnless(utils.IsProcessAlive(new_pid)) # Try writing to locked file try: utils.WritePidFile(pid_file) except errors.PidFileLockError, err: errmsg = str(err) self.assertTrue(errmsg.endswith(" %s" % new_pid), msg=("Error message ('%s') didn't contain correct" " PID (%s)" % (errmsg, new_pid))) else: self.fail("Writing to locked file didn't fail") utils.KillProcess(new_pid, waitpid=True) self.failIf(utils.IsProcessAlive(new_pid)) utils.RemoveFile(self.f_dpn("child")) self.failUnlessRaises(errors.ProgrammerError, utils.KillProcess, 0) def testExceptionType(self): # Make sure the PID lock error is a subclass of LockError in case some code # depends on it self.assertTrue(issubclass(errors.PidFileLockError, errors.LockError)) def tearDown(self): shutil.rmtree(self.dir) class TestNewUUID(unittest.TestCase): """Test case for NewUUID""" def runTest(self): self.failUnless(utils.UUID_RE.match(utils.NewUUID()))
def main(): debug = int(os.environ["GNT_DEBUG"]) logname = pathutils.GetLogFilename("jobs") utils.SetupLogging(logname, "job-startup", debug=debug) (job_id, livelock_name) = _GetMasterInfo() utils.SetupLogging(logname, "job-%s" % (job_id,), debug=debug) exit_code = 1 try: logging.debug("Preparing the context and the configuration") context = masterd.GanetiContext(livelock_name) logging.debug("Registering signal handlers") cancel = [False] prio_change = [False] def _TermHandler(signum, _frame): logging.info("Killed by signal %d", signum) cancel[0] = True signal.signal(signal.SIGTERM, _TermHandler) def _HupHandler(signum, _frame): logging.debug("Received signal %d, old flag was %s, will set to True", signum, mcpu.sighupReceived) mcpu.sighupReceived[0] = True signal.signal(signal.SIGHUP, _HupHandler) def _User1Handler(signum, _frame): logging.info("Received signal %d, indicating priority change", signum) prio_change[0] = True signal.signal(signal.SIGUSR1, _User1Handler) logging.debug("Picking up job %d", job_id) context.jobqueue.PickupJob(job_id) # waiting for the job to finish time.sleep(1) while not context.jobqueue.HasJobBeenFinalized(job_id): if cancel[0]: logging.debug("Got cancel request, cancelling job %d", job_id) r = context.jobqueue.CancelJob(job_id) logging.debug("CancelJob result for job %d: %s", job_id, r) cancel[0] = False if prio_change[0]: logging.debug("Received priority-change request") try: fname = os.path.join(pathutils.LUXID_MESSAGE_DIR, "%d.prio" % job_id) new_prio = int(utils.ReadFile(fname)) utils.RemoveFile(fname) logging.debug("Changing priority of job %d to %d", job_id, new_prio) r = context.jobqueue.ChangeJobPriority(job_id, new_prio) logging.debug("Result of changing priority of %d to %d: %s", job_id, new_prio, r) except Exception: # pylint: disable=W0703 logging.warning("Informed of priority change, but could not" " read new priority") prio_change[0] = False time.sleep(1) # wait until the queue finishes logging.debug("Waiting for the queue to finish") while context.jobqueue.PrepareShutdown(): time.sleep(1) logging.debug("Shutting the queue down") context.jobqueue.Shutdown() exit_code = 0 except Exception: # pylint: disable=W0703 logging.exception("Exception when trying to run job %d", job_id) finally: logging.debug("Job %d finalized", job_id) logging.debug("Removing livelock file %s", livelock_name.GetPath()) os.remove(livelock_name.GetPath()) sys.exit(exit_code)