Esempio n. 1
0
  /**
   * This method tries to compute the name of the host that's reachable by all the other nodes.
   *
   * <p>Since it's possible that the slave is not reachable from the master (it may be behind a
   * firewall, connecting to master via JNLP), this method may return null.
   *
   * <p>It's surprisingly tricky for a machine to know a name that other systems can get to,
   * especially between things like DNS search suffix, the hosts file, and YP.
   *
   * <p>So the technique here is to compute possible interfaces and names on the slave, then try to
   * ping them from the master, and pick the one that worked.
   *
   * <p>The computation may take some time, so it employs caching to make the successive lookups
   * faster.
   *
   * @since 1.300
   * @return null if the host name cannot be computed (for example because this computer is offline,
   *     because the slave is behind the firewall, etc.)
   */
  public String getHostName() throws IOException, InterruptedException {
    if (hostNameCached)
      // in the worst case we end up having multiple threads computing the host name simultaneously,
      // but that's not harmful, just wasteful.
      return cachedHostName;

    VirtualChannel channel = getChannel();
    if (channel == null) return null; // can't compute right now

    for (String address : channel.call(new ListPossibleNames())) {
      try {
        InetAddress ia = InetAddress.getByName(address);
        if (!(ia instanceof Inet4Address)) {
          LOGGER.fine(address + " is not an IPv4 address");
          continue;
        }
        if (!ComputerPinger.checkIsReachable(ia, 3)) {
          LOGGER.fine(address + " didn't respond to ping");
          continue;
        }
        cachedHostName = ia.getCanonicalHostName();
        hostNameCached = true;
        return cachedHostName;
      } catch (IOException e) {
        // if a given name fails to parse on this host, we get this error
        LOGGER.log(Level.FINE, "Failed to parse " + address, e);
      }
    }

    // allow the administrator to manually specify the host name as a fallback. HUDSON-5373
    cachedHostName = channel.call(new GetFallbackName());
    hostNameCached = true;
    return cachedHostName;
  }
  public static CommandOutputContent runOnNode(Node node, String name, String... command) {
    String content = "Exception occurred while retrieving command content";

    VirtualChannel chan = node.getChannel();
    if (chan == null) {
      content = "No connection to node";
    } else {
      try {
        content = chan.call(new CommandLauncher(command));
      } catch (IOException e) {
        final LogRecord lr =
            new LogRecord(Level.FINE, "Could not retrieve command content from {0}");
        lr.setParameters(new Object[] {getNodeName(node)});
        lr.setThrown(e);
        LOGGER.log(lr);
      } catch (InterruptedException e) {
        final LogRecord lr =
            new LogRecord(Level.FINE, "Could not retrieve command content from {0}");
        lr.setParameters(new Object[] {getNodeName(node)});
        lr.setThrown(e);
        LOGGER.log(lr);
      }
    }

    return new CommandOutputContent(name, content);
  }
 @Override
 protected T monitor(Computer c) throws IOException, InterruptedException {
   VirtualChannel ch = c.getChannel();
   if (ch != null) {
     Callable<T, IOException> cc = createCallable(c);
     if (cc != null) return ch.call(cc);
   }
   return null;
 }
Esempio n. 4
0
 /** Starts a new privilege-escalated environment, execute a closure, and shut it down. */
 public static <V, T extends Throwable> V execute(
     TaskListener listener, String rootUsername, String rootPassword, final Callable<V, T> closure)
     throws T, IOException, InterruptedException {
   VirtualChannel ch = start(listener, rootUsername, rootPassword);
   try {
     return ch.call(closure);
   } finally {
     ch.close();
     ch.join(3000); // give some time for orderly shutdown, but don't block forever.
   }
 }
    private void install(Computer c, TaskListener listener) {
        try {
            final List<SlaveRestarter> restarters = new ArrayList<SlaveRestarter>(SlaveRestarter.all());

            VirtualChannel ch = c.getChannel();
            if (ch==null) return;  // defensive check

            List<SlaveRestarter> effective = ch.call(new Callable<List<SlaveRestarter>, IOException>() {
                public List<SlaveRestarter> call() throws IOException {
                    Engine e = Engine.current();
                    if (e == null) return null;    // not running under Engine

                    try {
                        Engine.class.getMethod("addListener", EngineListener.class);
                    } catch (NoSuchMethodException _) {
                        return null;    // running with older version of remoting that doesn't support adding listener
                    }

                    // filter out ones that doesn't apply
                    for (Iterator<SlaveRestarter> itr = restarters.iterator(); itr.hasNext(); ) {
                        SlaveRestarter r =  itr.next();
                        if (!r.canWork())
                            itr.remove();
                    }

                    e.addListener(new EngineListenerAdapter() {
                        @Override
                        public void onDisconnect() {
                            try {
                                for (SlaveRestarter r : restarters) {
                                    try {
                                        LOGGER.info("Restarting slave via "+r);
                                        r.restart();
                                    } catch (Exception x) {
                                        LOGGER.log(SEVERE, "Failed to restart slave with "+r, x);
                                    }
                                }
                            } finally {
                                // if we move on to the reconnection without restart,
                                // don't let the current implementations kick in when the slave loses connection again
                                restarters.clear();
                            }
                        }
                    });

                    return restarters;
                }
            });

            listener.getLogger().println("Effective SlaveRestarter on " + c.getDisplayName() + ": " + effective);
        } catch (Throwable e) {
            e.printStackTrace(listener.error("Failed to install restarter"));
        }
    }
  /** Performs all monitoring concurrently. */
  @Override
  protected Map<Computer, T> monitor() throws InterruptedException {
    Map<Computer, Future<T>> futures = new HashMap<Computer, Future<T>>();

    for (Computer c : Jenkins.getInstance().getComputers()) {
      try {
        VirtualChannel ch = c.getChannel();
        futures.put(c, null); // sentinel value
        if (ch != null) {
          Callable<T, ?> cc = createCallable(c);
          if (cc != null) futures.put(c, ch.callAsync(cc));
        }
      } catch (RuntimeException e) {
        LOGGER.log(
            WARNING, "Failed to monitor " + c.getDisplayName() + " for " + getDisplayName(), e);
      } catch (IOException e) {
        LOGGER.log(
            WARNING, "Failed to monitor " + c.getDisplayName() + " for " + getDisplayName(), e);
      }
    }

    final long now = System.currentTimeMillis();
    final long end = now + getMonitoringTimeOut();

    final Map<Computer, T> data = new HashMap<Computer, T>();

    for (Entry<Computer, Future<T>> e : futures.entrySet()) {
      Computer c = e.getKey();
      Future<T> f = futures.get(c);
      data.put(c, null); // sentinel value

      if (f != null) {
        try {
          data.put(c, f.get(Math.max(0, end - System.currentTimeMillis()), MILLISECONDS));
        } catch (RuntimeException x) {
          LOGGER.log(
              WARNING, "Failed to monitor " + c.getDisplayName() + " for " + getDisplayName(), x);
        } catch (ExecutionException x) {
          LOGGER.log(
              WARNING, "Failed to monitor " + c.getDisplayName() + " for " + getDisplayName(), x);
        } catch (TimeoutException x) {
          LOGGER.log(
              WARNING, "Failed to monitor " + c.getDisplayName() + " for " + getDisplayName(), x);
        }
      }
    }

    return data;
  }
Esempio n. 7
0
  /** Dumps the contents of the export table. */
  public void doDumpExportTable(StaplerRequest req, StaplerResponse rsp)
      throws IOException, ServletException, InterruptedException {
    // this is a debug probe and may expose sensitive information
    checkPermission(Jenkins.ADMINISTER);

    rsp.setContentType("text/plain");
    PrintWriter w = new PrintWriter(rsp.getCompressedWriter(req));
    VirtualChannel vc = getChannel();
    if (vc instanceof Channel) {
      w.println("Master to slave");
      ((Channel) vc).dumpExportTable(w);
      w.flush(); // flush here once so that even if the dump from the slave fails, the client
      // gets some useful info

      w.println("\n\n\nSlave to master");
      w.print(vc.call(new DumpExportTableTask()));
    } else {
      w.println(Messages.Computer_BadChannel());
    }
    w.close();
  }
Esempio n. 8
0
    public String getShellOrDefault(VirtualChannel channel) {
      if (shell != null) return shell;

      String interpreter = null;
      try {
        interpreter = channel.call(new Shellinterpreter());
      } catch (IOException e) {
        LOGGER.warning(e.getMessage());
      } catch (InterruptedException e) {
        LOGGER.warning(e.getMessage());
      }
      if (interpreter == null) {
        interpreter = getShellOrDefault();
      }

      return interpreter;
    }
Esempio n. 9
0
  /** Obtains the heap dump in an HPROF file. */
  public static FilePath getHeapDump(VirtualChannel channel)
      throws IOException, InterruptedException {
    return channel.call(
        new MasterToSlaveCallable<FilePath, IOException>() {
          public FilePath call() throws IOException {
            final File hprof = File.createTempFile("hudson-heapdump", "hprof");
            hprof.delete();
            try {
              MBeanServer server = ManagementFactory.getPlatformMBeanServer();
              server.invoke(
                  new ObjectName("com.sun.management:type=HotSpotDiagnostic"),
                  "dumpHeap",
                  new Object[] {hprof.getAbsolutePath(), true},
                  new String[] {String.class.getName(), boolean.class.getName()});

              return new FilePath(hprof);
            } catch (JMException e) {
              throw new IOException(e);
            }
          }

          private static final long serialVersionUID = 1L;
        });
  }
Esempio n. 10
0
 public static Future<Map<String, String>> getThreadDumpAsync(VirtualChannel channel)
     throws IOException, InterruptedException {
   if (channel == null)
     return new AsyncFutureImpl<Map<String, String>>(Collections.singletonMap("N/A", "offline"));
   return channel.callAsync(new GetThreadDump());
 }
Esempio n. 11
0
 public static Map<String, String> getThreadDump(VirtualChannel channel)
     throws IOException, InterruptedException {
   if (channel == null) return Collections.singletonMap("N/A", "N/A");
   return channel.call(new GetThreadDump());
 }
Esempio n. 12
0
 public static Map<Object, Object> getSystemProperties(VirtualChannel channel)
     throws IOException, InterruptedException {
   if (channel == null) return Collections.<Object, Object>singletonMap("N/A", "N/A");
   return channel.call(new GetSystemProperties());
 }
Esempio n. 13
0
 /** Executes Groovy script remotely. */
 public static String executeGroovy(String script, @Nonnull VirtualChannel channel)
     throws IOException, InterruptedException {
   return channel.call(new Script(script));
 }