public Connection masterConnect(String ip, String username, Queue<String> password) {
   Connection conn = null;
   try {
     conn = new Connection(getURL(ip), 10);
     s_logger.debug("Logging on as the master to " + ip);
     loginWithPassword(conn, username, password, APIVersion.latest().toString());
     return conn;
   } catch (Exception e) {
     s_logger.debug("Failed to slave local login to " + ip);
   }
   throw new RuntimeException("can not log in to master " + ip);
 }
  void PoolEmergencyTransitionToMaster(String slaveIp, String username, Queue<String> password) {
    if (!s_managePool) {
      if (s_logger.isDebugEnabled()) {
        s_logger.debug("Don't manage pool on error so sleeping for " + s_sleepOnError);
        try {
          Thread.sleep(s_sleepOnError);
        } catch (InterruptedException ie) {
        }
      }
      return;
    }

    Connection slaveConn = null;
    Connection c = null;
    try {
      s_logger.debug("Trying to transition master to " + slaveIp);
      slaveConn = new Connection(getURL(slaveIp), 10);
      slaveLocalLoginWithPassword(slaveConn, username, password);
      Pool.emergencyTransitionToMaster(slaveConn);
      // restart xapi in 10 sec
      forceSleep(10);
      // check if the master of this host is set correctly.
      c = new Connection(getURL(slaveIp), 10);
      for (int i = 0; i < 30; i++) {
        try {
          loginWithPassword(c, username, password, APIVersion.latest().toString());
          s_logger.debug("Succeeded to transition master to " + slaveIp);
          return;
        } catch (Types.HostIsSlave e) {
          s_logger.debug("HostIsSlave: Still waiting for the conversion to the master " + slaveIp);
        } catch (Exception e) {
          s_logger.debug("Exception: Still waiting for the conversion to the master");
        }
        forceSleep(2);
      }
      throw new RuntimeException("EmergencyTransitionToMaster failed after retry 30 times");
    } catch (Exception e) {
      throw new RuntimeException("EmergencyTransitionToMaster failed due to " + e.getMessage());
    } finally {
      localLogout(slaveConn);
      slaveConn = null;
      if (c != null) {
        try {
          Session.logout(c);
          c.dispose();
        } catch (Exception e) {
        }
      }
    }
  }
  protected Session loginWithPassword(
      Connection conn, String username, Queue<String> password, String version)
      throws BadServerResponse, XenAPIException, XmlRpcException {
    Session s = null;
    boolean logged_in = false;
    Exception ex = null;
    while (!logged_in) {
      try {
        s =
            Session.loginWithPassword(
                conn, username, password.peek(), APIVersion.latest().toString());
        logged_in = true;
      } catch (BadServerResponse e) {
        logged_in = false;
        ex = e;
      } catch (XenAPIException e) {
        logged_in = false;
        ex = e;
      } catch (XmlRpcException e) {
        logged_in = false;
        ex = e;
      }

      if (logged_in && conn != null) {
        break;
      } else {
        if (password.size() > 1) {
          password.remove();
          continue;
        } else {
          // the last password did not work leave it and flag error
          if (ex instanceof BadServerResponse) {
            throw (BadServerResponse) ex;
          } else if (ex instanceof XmlRpcException) {
            throw (XmlRpcException) ex;
          } else if (ex instanceof Types.SessionAuthenticationFailed) {
            throw (Types.SessionAuthenticationFailed) ex;
          } else if (ex instanceof XenAPIException) {
            throw (XenAPIException) ex;
          }
        }
      }
    }
    return s;
  }
    @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;
  }
  public void switchMaster(
      String slaveIp,
      String poolUuid,
      Connection conn,
      Host host,
      String username,
      Queue<String> password,
      int wait)
      throws XmlRpcException, XenAPIException {
    synchronized (poolUuid.intern()) {
      String masterIp = host.getAddress(conn);
      s_logger.debug("Designating the new master to " + masterIp);
      Pool.designateNewMaster(conn, host);
      Connection slaveConn = null;
      Connection masterConn = null;
      int retry = 30;
      for (int i = 0; i < retry; i++) {
        forceSleep(5);
        try {
          if (s_logger.isDebugEnabled()) {
            s_logger.debug("Logging on as the slave to " + slaveIp);
          }
          slaveConn = null;
          masterConn = null;
          Session slaveSession = null;

          slaveConn = new Connection(getURL(slaveIp), 10);
          slaveSession = slaveLocalLoginWithPassword(slaveConn, username, password);

          if (s_logger.isDebugEnabled()) {
            s_logger.debug("Slave logon successful. session= " + slaveSession);
          }

          Pool.Record pr = getPoolRecord(slaveConn);
          Host master = pr.master;
          String ma = master.getAddress(slaveConn);
          if (!ma.trim().equals(masterIp.trim())) {
            continue;
          }
          s_logger.debug("Logging on as the master to " + masterIp);
          masterConn = new Connection(getURL(masterIp), 10);
          loginWithPassword(masterConn, username, password, APIVersion.latest().toString());
          removeConnect(poolUuid);
          ensurePoolIntegrity(masterConn, masterIp, username, password, wait);
          return;
        } catch (Types.HostIsSlave e) {
          s_logger.debug("HostIsSlaveException: Still waiting for the conversion to the master");
        } catch (XmlRpcException e) {
          s_logger.debug(
              "XmlRpcException: Still waiting for the conversion to the master " + e.getMessage());
        } catch (Exception e) {
          s_logger.debug(
              "Exception: Still waiting for the conversion to the master" + e.getMessage());
        } finally {
          if (masterConn != null) {
            try {
              Session.logout(masterConn);
            } catch (Exception e) {
              s_logger.debug("Unable to log out of session: " + e.getMessage());
            }
            masterConn.dispose();
            masterConn = null;
          }
          localLogout(slaveConn);
          slaveConn = null;
        }
      }
      throw new CloudRuntimeException(
          "Unable to logon to the new master after " + retry + " retries");
    }
  }