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)
Example #4
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)
Example #5
0
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))
Example #6
0
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
Example #7
0
 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)
Example #8
0
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))
Example #9
0
    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)
Example #10
0
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)
Example #11
0
  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
Example #12
0
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
Example #13
0
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)
Example #14
0
    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 = {}
Example #15
0
  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"]))
Example #17
0
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)
Example #18
0
    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))
Example #19
0
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()
Example #20
0
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")
Example #21
0
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)
Example #22
0
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))
Example #23
0
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))
Example #24
0
 def tearDown(self):
     while self._temp_files:
         try:
             utils.RemoveFile(self._temp_files.pop())
         except EnvironmentError:
             pass
Example #25
0
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()))
Example #30
0
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)