@Override
    protected Map dispatch(String method_call, Object[] method_params)
        throws XmlRpcException, XenAPIException {
      if (method_call.equals("session.local_logout")
          || method_call.equals("session.slave_local_login_with_password")
          || method_call.equals("session.logout")) {
        return super.dispatch(method_call, method_params);
      }

      if (method_call.equals("session.login_with_password")) {
        int retries = 0;
        while (retries++ < _retries) {
          try {
            return super.dispatch(method_call, method_params);
          } catch (XmlRpcException e) {
            Throwable cause = e.getCause();
            if (cause == null || !(cause instanceof SocketException)) {
              throw e;
            }
            if (retries >= _retries) {
              throw e;
            }
            s_logger.debug("Unable to login...retrying " + retries);
          }
          try {
            Thread.sleep(_interval);
          } catch (InterruptedException e) {
            s_logger.debug("Man....I was just getting comfortable there....who woke me up?");
          }
        }
      } else {
        int retries = 0;
        while (retries++ < _retries) {
          try {
            return super.dispatch(method_call, method_params);
          } catch (Types.SessionInvalid e) {
            s_logger.debug(
                "Session is invalid for method: "
                    + method_call
                    + " due to "
                    + e.getMessage()
                    + ".  Reconnecting...retry="
                    + retries);
            if (retries >= _retries) {
              removeConnect(_poolUuid);
              throw e;
            }
            loginWithPassword(this, _username, _password, APIVersion.latest().toString());
            method_params[0] = getSessionReference();
          } catch (XmlRpcClientException e) {
            s_logger.debug(
                "XmlRpcClientException for method: " + method_call + " due to " + e.getMessage());
            removeConnect(_poolUuid);
            throw e;
          } catch (XmlRpcException e) {
            s_logger.debug(
                "XmlRpcException for method: "
                    + method_call
                    + " due to "
                    + e.getMessage()
                    + ".  Reconnecting...retry="
                    + retries);
            if (retries >= _retries) {
              removeConnect(_poolUuid);
              throw e;
            }
            Throwable cause = e.getCause();
            if (cause == null || !(cause instanceof SocketException)) {
              removeConnect(_poolUuid);
              throw e;
            }
          } catch (Types.HostIsSlave e) {
            s_logger.debug(
                "HostIsSlave Exception for method: "
                    + method_call
                    + " due to "
                    + e.getMessage()
                    + ".  Reconnecting...retry="
                    + retries);
            removeConnect(_poolUuid);
            throw e;
          }
          try {
            Thread.sleep(_interval);
          } catch (InterruptedException e) {
            s_logger.info("Who woke me from my slumber?");
          }
        }
        assert false : "We should never get here";
        removeConnect(_poolUuid);
      }
      throw new CloudRuntimeException(
          "After " + _retries + " retries, we cannot contact the host ");
    }
  public Connection connect(
      String hostUuid,
      String poolUuid,
      String ipAddress,
      String username,
      Queue<String> password,
      int wait) {
    XenServerConnection mConn = null;
    Connection sConn = null;
    String masterIp = null;
    if (hostUuid == null
        || poolUuid == null
        || ipAddress == null
        || username == null
        || password == null) {
      String msg =
          "Connect some parameter are null hostUuid:"
              + hostUuid
              + " ,poolUuid:"
              + poolUuid
              + " ,ipAddress:"
              + ipAddress;
      s_logger.debug(msg);
      throw new CloudRuntimeException(msg);
    }
    Host host = null;
    synchronized (poolUuid.intern()) {
      // Let's see if it is an existing connection.
      mConn = getConnect(poolUuid);
      if (mConn != null) {
        try {
          host = Host.getByUuid(mConn, hostUuid);
        } catch (Types.SessionInvalid e) {
          s_logger.debug(
              "Session thgrough ip "
                  + mConn.getIp()
                  + " is invalid for pool("
                  + poolUuid
                  + ") due to "
                  + e.toString());
          try {
            loginWithPassword(
                mConn, mConn.getUsername(), mConn.getPassword(), APIVersion.latest().toString());
          } catch (Exception e1) {
            if (s_logger.isDebugEnabled()) {
              s_logger.debug(
                  "connect through IP("
                      + mConn.getIp()
                      + " for pool("
                      + poolUuid
                      + ") is broken due to "
                      + e.toString());
            }
            removeConnect(poolUuid);
            mConn = null;
          }
        } catch (UuidInvalid e) {
          String msg =
              "Host("
                  + hostUuid
                  + ") doesn't belong to pool("
                  + poolUuid
                  + "), please execute 'xe pool-join master-address="
                  + mConn.getIp()
                  + " master-username="******"connect through IP("
                    + mConn.getIp()
                    + " for pool("
                    + poolUuid
                    + ") is broken due to "
                    + e.toString());
          }
          removeConnect(poolUuid);
          mConn = null;
        }
      }

      if (mConn == null) {
        try {
          try {
            if (s_logger.isDebugEnabled()) {
              s_logger.debug("Logging on as the slave to " + ipAddress);
            }
            sConn = new Connection(getURL(ipAddress), 5);
            slaveLocalLoginWithPassword(sConn, username, password);
          } catch (Exception e) {
            String msg =
                "Unable to create slave connection to host("
                    + hostUuid
                    + ") due to "
                    + e.toString();
            if (s_logger.isDebugEnabled()) {
              s_logger.debug(msg);
            }
            throw new CloudRuntimeException(msg, e);
          }
          Pool.Record pr = null;
          try {
            pr = getPoolRecord(sConn);
          } catch (Exception e) {
            PoolEmergencyTransitionToMaster(ipAddress, username, password);
            mConn =
                new XenServerConnection(
                    getURL(ipAddress), ipAddress, username, password, _retries, _interval, wait);
            try {
              loginWithPassword(mConn, username, password, APIVersion.latest().toString());
              pr = getPoolRecord(mConn);
            } catch (Exception e1) {
              String msg =
                  "Unable to create master connection to host("
                      + hostUuid
                      + ") after transition it to master, due to "
                      + e1.toString();
              if (s_logger.isDebugEnabled()) {
                s_logger.debug(msg);
              }
              throw new CloudRuntimeException(msg, e1);
            }
            if (!pr.uuid.equals(poolUuid)) {
              String msg =
                  "host("
                      + hostUuid
                      + ") should be in pool("
                      + poolUuid
                      + "), but it is actually in pool("
                      + pr.uuid
                      + ")";
              if (s_logger.isDebugEnabled()) {
                s_logger.debug(msg);
              }
              throw new CloudRuntimeException(msg);
            } else {
              if (s_managePool) {
                ensurePoolIntegrity(mConn, ipAddress, username, password, wait);
              }
              addConnect(poolUuid, mConn);
              return mConn;
            }
          }
          if (!pr.uuid.equals(poolUuid)) {
            String msg =
                "host("
                    + hostUuid
                    + ") should be in pool("
                    + poolUuid
                    + "), but it is actually in pool("
                    + pr.uuid
                    + ")";
            if (s_logger.isDebugEnabled()) {
              s_logger.debug(msg);
            }
            throw new CloudRuntimeException(msg);
          }
          try {
            masterIp = pr.master.getAddress(sConn);
            mConn =
                new XenServerConnection(
                    getURL(masterIp), masterIp, username, password, _retries, _interval, wait);
            loginWithPassword(mConn, username, password, APIVersion.latest().toString());
            addConnect(poolUuid, mConn);
            return mConn;
          } catch (Exception e) {
            String msg = "Unable to logon in " + masterIp + " as master in pool(" + poolUuid + ")";
            if (s_logger.isDebugEnabled()) {
              s_logger.debug(msg);
            }
            throw new CloudRuntimeException(msg);
          }
        } finally {
          localLogout(sConn);
          sConn = null;
        }
      }
    }

    if (mConn != null) {
      if (s_managePool) {
        try {
          Map<String, String> args = new HashMap<String, String>();
          host.callPlugin(mConn, "echo", "main", args);
        } catch (Types.SessionInvalid e) {
          if (s_logger.isDebugEnabled()) {
            String msg =
                "Catch Exception: "
                    + e.getClass().getName()
                    + " Can't connect host "
                    + ipAddress
                    + " due to "
                    + e.toString();
            s_logger.debug(msg);
          }
          PoolEmergencyResetMaster(
              ipAddress, mConn.getIp(), mConn.getUsername(), mConn.getPassword());
        } catch (Types.CannotContactHost e) {
          if (s_logger.isDebugEnabled()) {
            String msg =
                "Catch Exception: "
                    + e.getClass().getName()
                    + " Can't connect host "
                    + ipAddress
                    + " due to "
                    + e.toString();
            s_logger.debug(msg);
          }
          PoolEmergencyResetMaster(
              ipAddress, mConn.getIp(), mConn.getUsername(), mConn.getPassword());
        } catch (Types.HostOffline e) {
          if (s_logger.isDebugEnabled()) {
            String msg =
                "Catch Exception: "
                    + e.getClass().getName()
                    + " Host is offline "
                    + ipAddress
                    + " due to "
                    + e.toString();
            s_logger.debug(msg);
          }
          PoolEmergencyResetMaster(
              ipAddress, mConn.getIp(), mConn.getUsername(), mConn.getPassword());
        } catch (Types.HostNotLive e) {
          String msg =
              "Catch Exception: "
                  + e.getClass().getName()
                  + " Host Not Live "
                  + ipAddress
                  + " due to "
                  + e.toString();
          if (s_logger.isDebugEnabled()) {
            s_logger.debug(msg);
          }
          PoolEmergencyResetMaster(
              ipAddress, mConn.getIp(), mConn.getUsername(), mConn.getPassword());
        } catch (Exception e) {
          String msg = "Echo test failed on host " + hostUuid + " IP " + ipAddress;
          s_logger.warn(msg, e);
          throw new CloudRuntimeException(msg, e);
        }
      }
    }
    return mConn;
  }