예제 #1
0
  /**
   * Starts the embedded agent, but only if the embedded agent is installed and it is enabled.
   *
   * @throws RuntimeException if the agent is installed and enabled but failed to start
   * @deprecated we don't have an embedded agent anymore, leaving this in case we resurrect it
   */
  private void startEmbeddedAgent() throws RuntimeException {
    // we can't use EmbeddedAgentBootstrapServiceMBean because if the embedded agent
    // isn't installed, that class will not be available; we must use JMX API
    final ObjectName agentBootstrapMBean =
        ObjectNameFactory.create("rhq:service=EmbeddedAgentBootstrap");
    final String agentEnabledAttribute = "AgentEnabled";
    final String startAgentMethod = "startAgent";
    final String configurationOverridesAttribute = "ConfigurationOverrides";
    final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

    try {
      // this will fail if the embedded agent isn't installed
      String enabled = (String) mbs.getAttribute(agentBootstrapMBean, agentEnabledAttribute);

      // if we got this far, the embedded agent is at least installed
      // now check to see if its enabled - if so start it; any startup exceptions now are thrown
      try {
        if (Boolean.valueOf(enabled)) {
          log.info("The embedded Agent is installed and enabled - it will now be started...");

          // NOTE: we cannot directly import AgentConfigurationConstants, so we hardcode the
          // actual constant values here - need to keep an eye on these in the unlikely event
          // the constant values change.
          String AgentConfigurationConstants_SERVER_TRANSPORT = "rhq.agent.server.transport";
          String AgentConfigurationConstants_SERVER_BIND_ADDRESS = "rhq.agent.server.bind-address";
          String AgentConfigurationConstants_SERVER_BIND_PORT = "rhq.agent.server.bind-port";

          // Get the configuration overrides as set in the configuration file.
          // If the agent's bind address isn't overridden with a non-empty value,
          // then we need to get the Server bind address and use it for the agent's bind address.
          // If the agent's server endpoint address/port are empty, we again use the values
          // appropriate for the Server this agent is embedded in.
          // Note that we don't look for the values in persisted preferences - we assume they
          // are always present in the configuration overrides (which they should always be);
          Properties overrides;
          String serverTransport;
          String serverAddress;
          String serverPort;
          String agentAddress;

          overrides =
              (Properties) mbs.getAttribute(agentBootstrapMBean, configurationOverridesAttribute);

          serverTransport = overrides.getProperty(AgentConfigurationConstants_SERVER_TRANSPORT);
          serverAddress = overrides.getProperty(AgentConfigurationConstants_SERVER_BIND_ADDRESS);
          serverPort = overrides.getProperty(AgentConfigurationConstants_SERVER_BIND_PORT);
          agentAddress =
              overrides.getProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_ADDRESS);

          Server server = serverManager.getServer();

          if (agentAddress == null || agentAddress.trim().equals("")) {
            overrides.setProperty(
                ServiceContainerConfigurationConstants.CONNECTOR_BIND_ADDRESS, server.getAddress());
          }
          if (serverAddress == null || serverAddress.trim().equals("")) {
            overrides.setProperty(
                AgentConfigurationConstants_SERVER_BIND_ADDRESS, server.getAddress());
          }
          if (serverPort == null || serverPort.trim().equals("")) {
            if (SecurityUtil.isTransportSecure(serverTransport)) {
              overrides.setProperty(
                  AgentConfigurationConstants_SERVER_BIND_PORT,
                  Integer.toString(server.getSecurePort()));
            } else {
              overrides.setProperty(
                  AgentConfigurationConstants_SERVER_BIND_PORT, Integer.toString(server.getPort()));
            }
          }

          mbs.setAttribute(
              agentBootstrapMBean, new Attribute(configurationOverridesAttribute, overrides));

          // We need to do the agent startup in a separate thread so we do not hang
          // this startup servlet.  JBossAS 4.2 will not begin accepting HTTP requests
          // until this startup servlet has finished (this is different from JBossAS 4.0).
          // The agent needs to submit an HTTP request in order to complete its startup
          // (it needs to register with the server).
          // The side effect of this is the RHQ Server will still start even if the embedded
          // agent fails to start - this may not be a bad thing.  We probably do not want
          // the entire RHQ Server to go down if its agent fails to start.
          Runnable agentStartRunnable =
              new Runnable() {
                public void run() {
                  // this returns only when the agent has started and is registered (sends HTTP
                  // request)
                  try {
                    mbs.invoke(agentBootstrapMBean, startAgentMethod, new Object[0], new String[0]);
                  } catch (Throwable t) {
                    log.error("Failed to start the embedded Agent - it will not be available!", t);
                  }
                }
              };

          Thread agentStartThread = new Thread(agentStartRunnable, "Embedded Agent Startup");
          agentStartThread.setDaemon(true);
          agentStartThread.start();
        } else {
          log.debug("The embedded Agent is not enabled, so it will not be started.");
        }
      } catch (Throwable t) {
        throw new RuntimeException("Failed to start the embedded Agent.", t);
      }
    } catch (RuntimeException se) {
      throw se;
    } catch (Throwable t) {
      log.info("The embedded Agent is not installed, so it will not be started (" + t + ").");
    }

    return;
  }
  @Override
  public void run() {
    LOG.info(AgentI18NResourceKeys.PRIMARY_SERVER_SWITCHOVER_THREAD_STARTED);

    while (!isInterrupted() && !toldToStop) {
      try {
        // Note that if the agent is not sending or the failover list doesn't have any servers,
        // then we skip this time and wait some more.
        // However, it the agent is sending and we have a failover list, then we need to check
        // to see if the server we are currently talking to is the same as primary server, listed
        // at the top of the failover list. If not the same, we ask the agent to switch to that
        // server.
        ClientCommandSender sender = this.agent.getClientCommandSender();
        if (sender.isSending()) {
          FailoverListComposite failoverList =
              this.agent.downloadServerFailoverList(); // ask the server for a new one

          // if the failover list doesn't have any servers, skip our poll and wait some more
          if (failoverList.size() > 0) {
            AgentConfiguration config = this.agent.getConfiguration();
            String transport = config.getServerTransport();
            String transportParams = config.getServerTransportParams();
            String currentServerAddress = config.getServerBindAddress();
            int currentServerPort = config.getServerBindPort();

            ServerEntry primary =
                failoverList.get(0); // get the top of the list, aka primary server
            String primaryAddress = primary.address;
            int primaryPort =
                (SecurityUtil.isTransportSecure(transport)) ? primary.securePort : primary.port;

            if (!primaryAddress.equals(currentServerAddress) || primaryPort != currentServerPort) {
              LOG.info(
                  AgentI18NResourceKeys.NOT_TALKING_TO_PRIMARY_SERVER,
                  primaryAddress,
                  primaryPort,
                  currentServerAddress,
                  currentServerPort);
              // create our own comm so we ping in an isolated client - don't reuse the sender's
              // comm for this
              RemoteCommunicator comm =
                  this.agent.createServerRemoteCommunicator(
                      transport, primaryAddress, primaryPort, transportParams);
              if (ping(comm)) {
                LOG.info(AgentI18NResourceKeys.PRIMARY_SERVER_UP, primaryAddress, primaryPort);
                failoverList.resetIndex(); // so the failover method call starts at the top
                this.agent.failoverToNewServer(
                    sender
                        .getRemoteCommunicator()); // note that we make sure we pass in the sender's
                                                   // comm
              } else {
                LOG.info(
                    AgentI18NResourceKeys.PRIMARY_SERVER_STILL_DOWN, primaryAddress, primaryPort);
              }
            }
          }
        }

        // to do sleep until its time to check again
        synchronized (this) {
          wait(interval);
        }
      } catch (InterruptedException ie) {
        break; // exiting
      } catch (Exception e) {
        LOG.warn(e, AgentI18NResourceKeys.PRIMARY_SERVER_SWITCHOVER_EXCEPTION, e);
      }
    }

    LOG.info(AgentI18NResourceKeys.PRIMARY_SERVER_SWITCHOVER_THREAD_STOPPED);
    return;
  }