Пример #1
0
    def _GetMagicCommand(self):
        """Returns the command to read/write the magic value.

    """
        if not self._opts.magic:
            return None

        # Prefix to ensure magic isn't interpreted as option to "echo"
        magic = "M=%s" % self._opts.magic

        cmd = StringIO()

        if self._mode == constants.IEM_IMPORT:
            cmd.write("{ ")
            cmd.write(
                utils.ShellQuoteArgs(["read", "-n",
                                      str(len(magic)), "magic"]))
            cmd.write(" && ")
            cmd.write("if test \"$magic\" != %s; then" %
                      utils.ShellQuote(magic))
            cmd.write(" echo %s >&2;" %
                      utils.ShellQuote("Magic value mismatch"))
            cmd.write(" exit 1;")
            cmd.write("fi;")
            cmd.write(" }")

        elif self._mode == constants.IEM_EXPORT:
            cmd.write(utils.ShellQuoteArgs(["echo", "-E", "-n", magic]))

        else:
            raise errors.GenericError("Invalid mode '%s'" % self._mode)

        return cmd.getvalue()
Пример #2
0
    def BuildCmd(self,
                 hostname,
                 user,
                 command,
                 batch=True,
                 ask_key=False,
                 tty=False,
                 use_cluster_key=True,
                 strict_host_check=True,
                 private_key=None,
                 quiet=True,
                 port=None):
        """Build an ssh command to execute a command on a remote node.

    @param hostname: the target host, string
    @param user: user to auth as
    @param command: the command
    @param batch: if true, ssh will run in batch mode with no prompting
    @param ask_key: if true, ssh will run with
        StrictHostKeyChecking=ask, so that we can connect to an
        unknown host (not valid in batch mode)
    @param use_cluster_key: whether to expect and use the
        cluster-global SSH key
    @param strict_host_check: whether to check the host's SSH key at all
    @param private_key: use this private key instead of the default
    @param quiet: whether to enable -q to ssh
    @param port: the SSH port on which the node's daemon is running

    @return: the ssh call to run 'command' on the remote host.

    """
        argv = [constants.SSH]
        argv.extend(
            self._BuildSshOptions(batch,
                                  ask_key,
                                  use_cluster_key,
                                  strict_host_check,
                                  private_key,
                                  quiet=quiet,
                                  port=port))
        if tty:
            argv.extend(["-t", "-t"])

        argv.append("%s@%s" % (user, hostname))

        # Insert variables for virtual nodes
        argv.extend(
            "export %s=%s;" % (utils.ShellQuote(name), utils.ShellQuote(value))
            for (name, value) in vcluster.EnvironmentForHost(hostname).items())

        argv.append(command)

        return argv
Пример #3
0
def UploadData(node, data, mode=0o600, filename=None):
  """Uploads data to a node and returns the filename.

  Caller needs to remove the returned file on the node when it's not needed
  anymore.

  """
  if filename:
    tmp = "tmp=%s" % utils.ShellQuote(filename)
  else:
    tmp = ('tmp=$(mktemp --tmpdir gnt.XXXXXX) && '
           'chmod %o "${tmp}"') % mode
  cmd = ("%s && "
         "[[ -f \"${tmp}\" ]] && "
         "cat > \"${tmp}\" && "
         "echo \"${tmp}\"") % tmp

  p = subprocess.Popen(GetSSHCommand(node, cmd), shell=False,
                       stdin=subprocess.PIPE, stdout=subprocess.PIPE)
  p.stdin.write(data)
  p.stdin.close()
  AssertEqual(p.wait(), 0)

  # Return temporary filename
  return _GetCommandStdout(p).strip()
Пример #4
0
    def test(self):
        buf = StringIO()
        sw = utils.ShellWriter(buf)
        sw.Write("#!/bin/bash")
        sw.Write("if true; then")
        sw.IncIndent()
        try:
            sw.Write("echo true")

            sw.Write("for i in 1 2 3")
            sw.Write("do")
            sw.IncIndent()
            try:
                self.assertEqual(sw._indent, 2)
                sw.Write("date")
            finally:
                sw.DecIndent()
            sw.Write("done")
        finally:
            sw.DecIndent()
        sw.Write("echo %s", utils.ShellQuote("Hello World"))
        sw.Write("exit 0")

        self.assertEqual(sw._indent, 0)

        output = buf.getvalue()

        self.assertTrue(output.endswith("\n"))

        lines = output.splitlines()
        self.assertEqual(len(lines), 9)
        self.assertEqual(lines[0], "#!/bin/bash")
        self.assertTrue(re.match(r"^\s+date$", lines[5]))
        self.assertEqual(lines[7], "echo 'Hello World'")
Пример #5
0
def _CreateOobScriptStructure():
  """Create a simple OOB handling script and its structure."""
  master = qa_config.GetMasterNode()

  data_path = qa_utils.UploadData(master.primary, "")
  verify_path = qa_utils.UploadData(master.primary, "")
  exit_code_path = qa_utils.UploadData(master.primary, "")

  oob_script = (("#!/bin/bash\n"
                 "echo \"$@\" > %s\n"
                 "cat %s\n"
                 "exit $(< %s)\n") %
                (utils.ShellQuote(verify_path), utils.ShellQuote(data_path),
                 utils.ShellQuote(exit_code_path)))
  oob_path = qa_utils.UploadData(master.primary, oob_script, mode=0700)

  return [oob_path, verify_path, data_path, exit_code_path]
Пример #6
0
def RemoveFromEtcHosts(hostnames):
    """Remove hostnames from /etc/hosts.

  @param hostnames: List of hostnames first used A records, all other CNAMEs

  """
    master = qa_config.GetMasterNode()
    tmp_hosts = UploadData(master.primary, "", mode=0644)
    quoted_tmp_hosts = utils.ShellQuote(tmp_hosts)

    sed_data = " ".join(hostnames)
    try:
        AssertCommand(
            (r"sed -e '/^\(::1\|127\.0\.0\.1\)\s\+%s/d' %s > %s"
             r" && mv %s %s") %
            (sed_data, utils.ShellQuote(pathutils.ETC_HOSTS), quoted_tmp_hosts,
             quoted_tmp_hosts, utils.ShellQuote(pathutils.ETC_HOSTS)))
    except Exception:
        AssertCommand(["rm", "-f", tmp_hosts])
        raise
Пример #7
0
def BackupFile(node, path):
    """Creates a backup of a file on the node and returns the filename.

  Caller needs to remove the returned file on the node when it's not needed
  anymore.

  """
    vpath = MakeNodePath(node, path)

    cmd = ("tmp=$(mktemp .gnt.XXXXXX --tmpdir=$(dirname %s)) && "
           "[[ -f \"$tmp\" ]] && "
           "cp %s $tmp && "
           "echo $tmp") % (utils.ShellQuote(vpath), utils.ShellQuote(vpath))

    # Return temporary filename
    result = GetCommandOutput(node, cmd).strip()

    print "Backup filename: %s" % result

    return result
Пример #8
0
def AddToEtcHosts(hostnames):
    """Adds hostnames to /etc/hosts.

  @param hostnames: List of hostnames first used A records, all other CNAMEs

  """
    master = qa_config.GetMasterNode()
    tmp_hosts = UploadData(master.primary, "", mode=0644)

    data = []
    for localhost in ("::1", "127.0.0.1"):
        data.append("%s %s" % (localhost, " ".join(hostnames)))

    try:
        AssertCommand(
            "{ cat %s && echo -e '%s'; } > %s && mv %s %s" %
            (utils.ShellQuote(pathutils.ETC_HOSTS), "\\n".join(data),
             utils.ShellQuote(tmp_hosts), utils.ShellQuote(tmp_hosts),
             utils.ShellQuote(pathutils.ETC_HOSTS)))
    except Exception:
        AssertCommand(["rm", "-f", tmp_hosts])
        raise
Пример #9
0
def AssertRedirectedCommand(cmd, fail=False, node=None, log_cmd=True):
  """Executes a command with redirected output.

  The log will go to the qa-output log file in the ganeti log
  directory on the node where the command is executed. The fail and
  node parameters are passed unchanged to AssertCommand.

  @param cmd: the command to be executed, as a list; a string is not
      supported

  """
  if not isinstance(cmd, list):
    raise qa_error.Error("Non-list passed to AssertRedirectedCommand")
  ofile = utils.ShellQuote(_QA_OUTPUT)
  cmdstr = utils.ShellQuoteArgs(cmd)
  AssertCommand("echo ---- $(date) %s ---- >> %s" % (cmdstr, ofile),
                fail=False, node=node, log_cmd=False)
  return AssertCommand(cmdstr + " >> %s" % ofile,
                       fail=fail, node=node, log_cmd=log_cmd)
Пример #10
0
def GetSSHCommand(node,
                  cmd,
                  strict=True,
                  opts=None,
                  tty=False,
                  use_multiplexer=True):
    """Builds SSH command to be executed.

  @type node: string
  @param node: node the command should run on
  @type cmd: string
  @param cmd: command to be executed in the node; if None or empty
      string, no command will be executed
  @type strict: boolean
  @param strict: whether to enable strict host key checking
  @type opts: list
  @param opts: list of additional options
  @type tty: boolean or None
  @param tty: if we should use tty; if None, will be auto-detected
  @type use_multiplexer: boolean
  @param use_multiplexer: if the multiplexer for the node should be used

  """
    args = ["ssh", "-oEscapeChar=none", "-oBatchMode=yes", "-lroot"]

    if tty is None:
        tty = sys.stdout.isatty()

    if tty:
        args.append("-t")

    if strict:
        tmp = "yes"
    else:
        tmp = "no"
    args.append("-oStrictHostKeyChecking=%s" % tmp)
    args.append("-oClearAllForwardings=yes")
    args.append("-oForwardAgent=yes")
    if opts:
        args.extend(opts)
    if node in _MULTIPLEXERS and use_multiplexer:
        spath = _MULTIPLEXERS[node][0]
        args.append("-oControlPath=%s" % spath)
        args.append("-oControlMaster=no")

    (vcluster_master, vcluster_basedir) = \
      qa_config.GetVclusterSettings()

    if vcluster_master:
        args.append(vcluster_master)
        args.append("%s/%s/cmd" % (vcluster_basedir, node))

        if cmd:
            # For virtual clusters the whole command must be wrapped using the "cmd"
            # script, as that script sets a number of environment variables. If the
            # command contains shell meta characters the whole command needs to be
            # quoted.
            args.append(utils.ShellQuote(cmd))
    else:
        args.append(node)

        if cmd:
            args.append(cmd)

    return args
Пример #11
0
        # Return temporary filename
        return _GetCommandStdout(p).strip()
    finally:
        f.close()


def UploadData(node, data, mode=0600, filename=None):
    """Uploads data to a node and returns the filename.

  Caller needs to remove the returned file on the node when it's not needed
  anymore.

  """
    if filename:
        tmp = "tmp=%s" % utils.ShellQuote(filename)
    else:
        tmp = ('tmp=$(mktemp --tmpdir gnt.XXXXXX) && '
               'chmod %o "${tmp}"') % mode
    cmd = ("%s && "
           "[[ -f \"${tmp}\" ]] && "
           "cat > \"${tmp}\" && "
           "echo \"${tmp}\"") % tmp

    p = subprocess.Popen(GetSSHCommand(node, cmd),
                         shell=False,
                         stdin=subprocess.PIPE,
                         stdout=subprocess.PIPE)
    p.stdin.write(data)
    p.stdin.close()
    AssertEqual(p.wait(), 0)
Пример #12
0
        # Return temporary filename
        return _GetCommandStdout(p).strip()
    finally:
        f.close()


def UploadData(node, data, mode=0600, filename=None):
    """Uploads data to a node and returns the filename.

  Caller needs to remove the returned file on the node when it's not needed
  anymore.

  """
    if filename:
        quoted_filename = utils.ShellQuote(filename)
        directory = utils.ShellQuote(os.path.dirname(filename))

        cmd = " && ".join([
            "mkdir -p %s" % directory,
            "cat > %s" % quoted_filename,
            "chmod %o %s" % (mode, quoted_filename)
        ])
    else:
        cmd = " && ".join([
            'tmp=$(mktemp --tmpdir gnt.XXXXXX)',
            'chmod %o "${tmp}"' % mode, 'cat > "${tmp}"', 'echo "${tmp}"'
        ])

    p = subprocess.Popen(GetSSHCommand(node, cmd),
                         shell=False,
Пример #13
0
 def testShellQuote(self):
     self.assertEqual(utils.ShellQuote("abc"), "abc")
     self.assertEqual(utils.ShellQuote('ab"c'), "'ab\"c'")
     self.assertEqual(utils.ShellQuote("a'bc"), "'a'\\''bc'")
     self.assertEqual(utils.ShellQuote("a b c"), "'a b c'")
     self.assertEqual(utils.ShellQuote("a b\\ c"), "'a b\\ c'")