mirror of https://github.com/apache/cloudstack.git
change XenServerConnectionPool from hostuued based to pooluuid based
This commit is contained in:
parent
350a482fff
commit
55f2f29271
|
|
@ -17,9 +17,7 @@
|
|||
*/
|
||||
package com.cloud.hypervisor.xen.resource;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
|
@ -36,14 +34,12 @@ import com.xensource.xenapi.Pool;
|
|||
import com.xensource.xenapi.Session;
|
||||
import com.xensource.xenapi.Types;
|
||||
import com.xensource.xenapi.Types.XenAPIException;
|
||||
import com.xensource.xenapi.Types.UuidInvalid;
|
||||
|
||||
public class XenServerConnectionPool {
|
||||
private static final Logger s_logger = Logger
|
||||
.getLogger(XenServerConnectionPool.class);
|
||||
|
||||
protected HashMap<String /* hostUuid */, XenServerConnection> _conns = new HashMap<String, XenServerConnection>();
|
||||
protected HashMap<String /* poolUuid */, ConnectionInfo> _infos = new HashMap<String, ConnectionInfo>();
|
||||
|
||||
protected HashMap<String /* poolUuid */, XenServerConnection> _conns = new HashMap<String, XenServerConnection>();
|
||||
protected int _retries;
|
||||
protected int _interval;
|
||||
|
||||
|
|
@ -52,7 +48,40 @@ public class XenServerConnectionPool {
|
|||
_interval = 3;
|
||||
}
|
||||
|
||||
void forceSleep(long sec) {
|
||||
private void addConnect(String poolUuid, XenServerConnection conn){
|
||||
if( poolUuid == null ) return;
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Add master connection through " + conn.getIp() + " for pool(" + conn.getPoolUuid() + ")");
|
||||
}
|
||||
synchronized (_conns) {
|
||||
_conns.put(poolUuid, conn);
|
||||
}
|
||||
}
|
||||
|
||||
private XenServerConnection getConnect(String poolUuid) {
|
||||
if( poolUuid == null ) return null;
|
||||
synchronized (_conns) {
|
||||
return _conns.get(poolUuid);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeConnect(String poolUuid) {
|
||||
if( poolUuid == null ) {
|
||||
return;
|
||||
}
|
||||
XenServerConnection conn = null;
|
||||
synchronized (_conns) {
|
||||
conn = _conns.remove(poolUuid);
|
||||
}
|
||||
if ( conn != null ) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Remove master connection through " + conn.getIp() + " for pool(" + conn.getPoolUuid() + ")");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void forceSleep(long sec) {
|
||||
long firetime = System.currentTimeMillis() + (sec * 1000);
|
||||
long msec = sec * 1000;
|
||||
while (true) {
|
||||
|
|
@ -86,12 +115,9 @@ public class XenServerConnectionPool {
|
|||
}
|
||||
slaveConn = null;
|
||||
masterConn = null;
|
||||
URL slaveUrl = null;
|
||||
URL masterUrl = null;
|
||||
Session slaveSession = null;
|
||||
|
||||
slaveUrl = new URL("http://" + slaveIp);
|
||||
slaveConn = new Connection(slaveUrl, 100);
|
||||
|
||||
slaveConn = new Connection(getURL(slaveIp), 100);
|
||||
slaveSession = Session.slaveLocalLoginWithPassword(slaveConn,
|
||||
username, password);
|
||||
|
||||
|
|
@ -109,11 +135,10 @@ public class XenServerConnectionPool {
|
|||
Session.localLogout(slaveConn);
|
||||
slaveConn = null;
|
||||
s_logger.debug("Logging on as the master to " + masterIp);
|
||||
masterUrl = new URL("http://" + masterIp);
|
||||
masterConn = new Connection(masterUrl, 100);
|
||||
masterConn = new Connection(getURL(masterIp), 100);
|
||||
Session.loginWithPassword(masterConn, username, password,
|
||||
APIVersion.latest().toString());
|
||||
cleanup(poolUuid);
|
||||
removeConnect(poolUuid);
|
||||
ensurePoolIntegrity(masterConn, masterIp, username, password,
|
||||
wait);
|
||||
PoolSyncDB(masterConn);
|
||||
|
|
@ -150,93 +175,16 @@ public class XenServerConnectionPool {
|
|||
slaveConn.dispose();
|
||||
slaveConn = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
throw new CloudRuntimeException(
|
||||
"Unable to logon to the new master after " + retry + " retries");
|
||||
}
|
||||
}
|
||||
|
||||
protected void cleanup(String poolUuid) {
|
||||
synchronized (poolUuid.intern()) {
|
||||
if( poolUuid == null ) {
|
||||
return;
|
||||
}
|
||||
ConnectionInfo info = _infos.remove(poolUuid);
|
||||
if (info == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
s_logger.debug("Cleaning up session for pool " + poolUuid);
|
||||
for (Member member : info.refs.values()) {
|
||||
s_logger.debug("remove connection for host " + member.uuid);
|
||||
_conns.remove(member.uuid);
|
||||
}
|
||||
|
||||
if (info.conn != null) {
|
||||
try {
|
||||
s_logger.debug("Logging out of session "
|
||||
+ info.conn.getSessionReference());
|
||||
Session.logout(info.conn);
|
||||
} catch (XenAPIException e) {
|
||||
s_logger.debug("Unable to logout of the session");
|
||||
} catch (XmlRpcException e) {
|
||||
s_logger.debug("Unable to logout of the session");
|
||||
}
|
||||
info.conn.dispose();
|
||||
}
|
||||
s_logger.debug("Session is cleaned up");
|
||||
}
|
||||
}
|
||||
|
||||
protected void cleanup(String poolUuid, ConnectionInfo info) {
|
||||
synchronized (poolUuid.intern()) {
|
||||
ConnectionInfo info2 = _infos.get(poolUuid);
|
||||
if( info2 == null ) {
|
||||
return;
|
||||
}
|
||||
s_logger.debug("Cleanup for Session " + info.conn.getSessionReference());
|
||||
if (info != info2) {
|
||||
s_logger.debug("Session " + info.conn.getSessionReference()
|
||||
+ " is already logged out.");
|
||||
return;
|
||||
}
|
||||
|
||||
cleanup(poolUuid);
|
||||
}
|
||||
}
|
||||
|
||||
public void disconnect(String uuid, String poolUuid) {
|
||||
synchronized (poolUuid.intern()) {
|
||||
Connection conn = _conns.remove(uuid);
|
||||
if (conn == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Logging out of " + conn.getSessionReference()
|
||||
+ " for host " + uuid);
|
||||
}
|
||||
|
||||
ConnectionInfo info = _infos.get(poolUuid);
|
||||
if (info == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Connection for pool " + poolUuid
|
||||
+ " found. session=" + info.conn.getSessionReference());
|
||||
}
|
||||
|
||||
Member member = info.refs.remove(uuid);
|
||||
|
||||
if (info.refs.size() == 0 || ( member != null && member.ipAddr.equals(info.masterIp) )) {
|
||||
cleanup(poolUuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void logout(Connection conn) {
|
||||
|
|
@ -255,8 +203,7 @@ public class XenServerConnectionPool {
|
|||
Connection slaveConn = null;
|
||||
Connection masterConn = null;
|
||||
try{
|
||||
URL slaveUrl = new URL("http://" + ip);
|
||||
slaveConn = new Connection(slaveUrl, 100);
|
||||
slaveConn = new Connection(getURL(ip), 100);
|
||||
Session.slaveLocalLoginWithPassword(slaveConn, username, password);
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
|
|
@ -269,8 +216,7 @@ public class XenServerConnectionPool {
|
|||
masterIp = master.getAddress(slaveConn);
|
||||
|
||||
s_logger.debug("Logging on as the master to " + masterIp);
|
||||
URL masterUrl = new URL("http://" + masterIp);
|
||||
masterConn = new Connection(masterUrl, 100);
|
||||
masterConn = new Connection(getURL(masterIp), 100);
|
||||
Session.loginWithPassword(masterConn, username, password,
|
||||
APIVersion.latest().toString());
|
||||
return masterConn;
|
||||
|
|
@ -304,8 +250,7 @@ public class XenServerConnectionPool {
|
|||
public Connection slaveConnect(String ip, String username, String password) {
|
||||
Connection conn = null;
|
||||
try{
|
||||
URL url = new URL("http://" + ip);
|
||||
conn = new Connection(url, 100);
|
||||
conn = new Connection(getURL(ip), 100);
|
||||
Session.slaveLocalLoginWithPassword(conn, username, password);
|
||||
return conn;
|
||||
}catch ( Exception e){
|
||||
|
|
@ -314,18 +259,6 @@ public class XenServerConnectionPool {
|
|||
return null;
|
||||
}
|
||||
|
||||
protected ConnectionInfo getConnectionInfo(String poolUuid) {
|
||||
synchronized (_infos) {
|
||||
return _infos.get(poolUuid);
|
||||
}
|
||||
}
|
||||
|
||||
protected XenServerConnection getConnection(String hostUuid) {
|
||||
synchronized (_conns) {
|
||||
return _conns.get(hostUuid);
|
||||
}
|
||||
}
|
||||
|
||||
static void PoolSyncDB(Connection conn) {
|
||||
try {
|
||||
Set<Host> hosts = Host.getAll(conn);
|
||||
|
|
@ -352,8 +285,7 @@ public class XenServerConnectionPool {
|
|||
Connection c = null;
|
||||
try{
|
||||
s_logger.debug("Trying to transition master to " + slaveIp);
|
||||
URL slaveUrl = new URL("http://" + slaveIp);
|
||||
slaveConn = new Connection(slaveUrl, 100);
|
||||
slaveConn = new Connection(getURL(slaveIp), 100);
|
||||
Session.slaveLocalLoginWithPassword(slaveConn, username, password);
|
||||
Pool.emergencyTransitionToMaster(slaveConn);
|
||||
try {
|
||||
|
|
@ -364,7 +296,7 @@ public class XenServerConnectionPool {
|
|||
// restart xapi in 10 sec
|
||||
forceSleep(10);
|
||||
// check if the master of this host is set correctly.
|
||||
c = new Connection(slaveUrl, 100);
|
||||
c = new Connection(getURL(slaveIp), 100);
|
||||
for (int i = 0; i < 30; i++) {
|
||||
try {
|
||||
Session.loginWithPassword(c, username, password, APIVersion.latest().toString());
|
||||
|
|
@ -398,14 +330,13 @@ public class XenServerConnectionPool {
|
|||
|
||||
}
|
||||
|
||||
void PoolEmergencyResetMaster(String slaveIp, String masterIp,
|
||||
static void PoolEmergencyResetMaster(String slaveIp, String masterIp,
|
||||
String username, String password) {
|
||||
Connection slaveConn = null;
|
||||
try {
|
||||
s_logger.debug("Trying to reset master of slave " + slaveIp
|
||||
+ " to " + masterIp);
|
||||
URL slaveUrl = new URL("http://" + slaveIp);
|
||||
slaveConn = new Connection(slaveUrl, 10);
|
||||
slaveConn = new Connection(getURL(slaveIp), 10);
|
||||
Session.slaveLocalLoginWithPassword(slaveConn, username, password);
|
||||
Pool.emergencyResetMaster(slaveConn, masterIp);
|
||||
if (slaveConn != null) {
|
||||
|
|
@ -421,6 +352,8 @@ public class XenServerConnectionPool {
|
|||
Pool.Record pr = getPoolRecord(slaveConn);
|
||||
String mIp = pr.master.getAddress(slaveConn);
|
||||
if (mIp.trim().equals(masterIp.trim())) {
|
||||
s_logger.debug("Succeeded to reset master of slave " + slaveIp
|
||||
+ " to " + masterIp);
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
|
@ -445,25 +378,25 @@ public class XenServerConnectionPool {
|
|||
}
|
||||
}
|
||||
}
|
||||
throw new CloudRuntimeException("Unable to reset master of slave " + slaveIp
|
||||
+ " to " + masterIp + "after 30 retry");
|
||||
}
|
||||
|
||||
protected void ensurePoolIntegrity(Connection conn,
|
||||
String masterIp, String username, String password, int wait)
|
||||
throws XenAPIException, XmlRpcException {
|
||||
String masterIp, String username, String password, int wait) {
|
||||
try {
|
||||
// try recoverSlave first
|
||||
Set<Host> slaves = Pool.recoverSlaves(conn);
|
||||
Set<Host> rcSlaves = Pool.recoverSlaves(conn);
|
||||
// wait 10 second
|
||||
forceSleep(10);
|
||||
for(Host slave : slaves ) {
|
||||
for(Host slave : rcSlaves ) {
|
||||
for (int i = 0; i < 30; i++) {
|
||||
Connection slaveConn = null;
|
||||
try {
|
||||
|
||||
String slaveIp = slave.getAddress(conn);
|
||||
s_logger.debug("Logging on as the slave to " + slaveIp);
|
||||
URL slaveUrl = new URL("http://" + slaveIp);
|
||||
slaveConn = new Connection(slaveUrl, 10);
|
||||
slaveConn = new Connection(getURL(slaveIp), 10);
|
||||
Session.slaveLocalLoginWithPassword(slaveConn, username, password);
|
||||
Pool.Record pr = getPoolRecord(slaveConn);
|
||||
String mIp = pr.master.getAddress(slaveConn);
|
||||
|
|
@ -482,218 +415,171 @@ public class XenServerConnectionPool {
|
|||
}
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
// then try emergency reset master
|
||||
Set<Host> slaves = Host.getAll(conn);
|
||||
for (Host slave : slaves) {
|
||||
String slaveIp = slave.getAddress(conn);
|
||||
Connection slaveConn = null;
|
||||
try {
|
||||
s_logger.debug("Logging on as the slave to " + slaveIp);
|
||||
URL slaveUrl = new URL("http://" + slaveIp);
|
||||
slaveConn = new Connection(slaveUrl, 10);
|
||||
Session.slaveLocalLoginWithPassword(slaveConn, username,
|
||||
password);
|
||||
Pool.Record slavePoolr = getPoolRecord(slaveConn);
|
||||
String ip = slavePoolr.master.getAddress(slaveConn);
|
||||
if (!masterIp.trim().equals(ip.trim())) {
|
||||
PoolEmergencyResetMaster(slaveIp, masterIp, username,
|
||||
// then try emergency reset master
|
||||
Set<Host> slaves = Host.getAll(conn);
|
||||
for (Host slave : slaves) {
|
||||
String slaveIp = slave.getAddress(conn);
|
||||
Connection slaveConn = null;
|
||||
try {
|
||||
s_logger.debug("Logging on as the slave to " + slaveIp);
|
||||
|
||||
slaveConn = new Connection(getURL(slaveIp), 10);
|
||||
Session.slaveLocalLoginWithPassword(slaveConn, username,
|
||||
password);
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
throw new CloudRuntimeException("Bad URL" + slaveIp, e);
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Unable to login to slave " + slaveIp
|
||||
+ " error " + e.getMessage());
|
||||
} finally {
|
||||
if (slaveConn != null) {
|
||||
try {
|
||||
Session.localLogout(slaveConn);
|
||||
} catch (Exception e) {
|
||||
Pool.Record slavePoolr = getPoolRecord(slaveConn);
|
||||
String ip = slavePoolr.master.getAddress(slaveConn);
|
||||
if (!masterIp.trim().equals(ip.trim())) {
|
||||
PoolEmergencyResetMaster(slaveIp, masterIp, username,
|
||||
password);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Unable to login to slave " + slaveIp
|
||||
+ " error " + e.getMessage());
|
||||
} finally {
|
||||
if (slaveConn != null) {
|
||||
try {
|
||||
Session.localLogout(slaveConn);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
slaveConn.dispose();
|
||||
}
|
||||
slaveConn.dispose();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Catch " + e.getClass().getName() + " due to " + e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static private URL getURL(String ip){
|
||||
try {
|
||||
return new URL("http://" + ip);
|
||||
} catch (Exception e) {
|
||||
String msg = "Unable to convert IP " + ip + " to URL due to " + e.toString();
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug(msg);
|
||||
}
|
||||
throw new CloudRuntimeException(msg, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Connection connect(String hostUuid, String poolUuid, String ipAddress,
|
||||
String username, 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);
|
||||
}
|
||||
synchronized (poolUuid.intern()) {
|
||||
XenServerConnection masterConn = null;
|
||||
Connection slaveConn = null;
|
||||
URL slaveUrl = null;
|
||||
URL masterUrl = null;
|
||||
String masterIp = null;
|
||||
ConnectionInfo info = 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);
|
||||
}
|
||||
// Let's see if it is an existing connection.
|
||||
masterConn = _conns.get(hostUuid);
|
||||
if (masterConn != null){
|
||||
mConn = getConnect(poolUuid);
|
||||
if (mConn != null){
|
||||
try{
|
||||
Host.getByUuid(masterConn, hostUuid);
|
||||
return masterConn;
|
||||
Host.getByUuid(mConn, hostUuid);
|
||||
return mConn;
|
||||
} catch (Types.SessionInvalid e) {
|
||||
s_logger.debug("Session thgrough ip " + mConn.getIp() + " is invalid for pool(" + poolUuid + ") due to " + e.toString());
|
||||
try {
|
||||
Session.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=" + mConn.getUsername() + " master-password=" + mConn.getPassword();
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug(msg);
|
||||
}
|
||||
throw new CloudRuntimeException(msg, e);
|
||||
} catch (Exception e) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Master Session " + masterConn.getSessionReference() + " is broken due to " + e.getMessage());
|
||||
s_logger.debug("connect through IP(" + mConn.getIp() + " for pool(" + poolUuid + ") is broken due to " + e.toString());
|
||||
}
|
||||
cleanup(masterConn.get_poolUuid());
|
||||
masterConn = null;
|
||||
removeConnect(poolUuid);
|
||||
mConn = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Creating connection to " + ipAddress);
|
||||
s_logger.debug("Logging on as the slave to " + ipAddress);
|
||||
}
|
||||
|
||||
try {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Logging on as the slave to " + ipAddress);
|
||||
}
|
||||
slaveUrl = new URL("http://" + ipAddress);
|
||||
slaveConn = new Connection(slaveUrl, 100);
|
||||
Session.slaveLocalLoginWithPassword(slaveConn,
|
||||
sConn = new Connection(getURL(ipAddress), 100);
|
||||
Session.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("Slave logon successful to " + ipAddress);
|
||||
s_logger.debug(msg);
|
||||
}
|
||||
|
||||
info = _infos.get(poolUuid);
|
||||
boolean create_new_session = true;
|
||||
if (info != null) {
|
||||
try {
|
||||
masterConn = info.conn;
|
||||
Host.getByUuid(masterConn, hostUuid);
|
||||
ensurePoolIntegrity(masterConn, info.masterIp, username,
|
||||
password, wait);
|
||||
masterIp = info.masterIp;
|
||||
create_new_session = false;
|
||||
} catch (Exception e) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Unable to connect to master " + info.masterIp);
|
||||
}
|
||||
|
||||
cleanup(poolUuid);
|
||||
masterConn = null;
|
||||
masterIp = null;
|
||||
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 {
|
||||
Session.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 {
|
||||
try {
|
||||
Pool.Record pr = getPoolRecord(slaveConn);
|
||||
masterIp = pr.master.getAddress(slaveConn);
|
||||
masterUrl = new URL("http://" + masterIp);;
|
||||
masterConn = new XenServerConnection(masterUrl, username,
|
||||
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);
|
||||
Session.loginWithPassword(masterConn, username, password,
|
||||
Session.loginWithPassword(mConn, username, password,
|
||||
APIVersion.latest().toString());
|
||||
create_new_session = false;
|
||||
|
||||
} catch (Exception e) {
|
||||
cleanup(poolUuid);
|
||||
masterConn = null;
|
||||
masterIp = null;
|
||||
}
|
||||
}
|
||||
if (create_new_session) {
|
||||
try{
|
||||
cleanup(poolUuid);
|
||||
s_logger.info("Attempting switch master to " + ipAddress);
|
||||
|
||||
PoolEmergencyTransitionToMaster(ipAddress, username, password);
|
||||
|
||||
s_logger.info("Successfully converted to master: " + ipAddress);
|
||||
|
||||
s_logger.info("Loginning on as master to " + ipAddress);
|
||||
masterUrl = slaveUrl;
|
||||
masterConn = new XenServerConnection(masterUrl, username,
|
||||
password, _retries, _interval, wait);
|
||||
Session.loginWithPassword(masterConn, username, password,
|
||||
APIVersion.latest().toString());
|
||||
s_logger.info("Logined on as master to " + ipAddress);
|
||||
masterIp = ipAddress;
|
||||
|
||||
ensurePoolIntegrity(masterConn, ipAddress, username, password,
|
||||
wait);
|
||||
} catch (Exception e) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("failed to switch master to Unable to " + ipAddress + " due to " + e.getMessage());
|
||||
}
|
||||
cleanup(poolUuid);
|
||||
masterConn = null;
|
||||
masterIp = null;
|
||||
}
|
||||
}
|
||||
|
||||
if( masterConn == null ) {
|
||||
throw new CloudRuntimeException(" Can not create connection to pool " + poolUuid);
|
||||
}
|
||||
info = _infos.get(poolUuid);
|
||||
|
||||
if ( info == null ) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Create info on master :" + masterIp);
|
||||
}
|
||||
info = new ConnectionInfo();
|
||||
info.conn = masterConn;
|
||||
info.masterIp = masterIp;
|
||||
info.refs = new HashMap<String, Member>();
|
||||
masterConn.setInfo(poolUuid, info);
|
||||
_infos.put(poolUuid, info);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Pool " + poolUuid
|
||||
+ " is matched with session "
|
||||
+ info.conn.getSessionReference());
|
||||
}
|
||||
}
|
||||
masterConn = new XenServerConnection(info.conn);
|
||||
|
||||
s_logger.debug("Added a reference for host " + hostUuid
|
||||
+ " to session " + masterConn.getSessionReference()
|
||||
+ " in pool " + poolUuid);
|
||||
info.refs.put(hostUuid, new Member(ipAddress, hostUuid, username,
|
||||
password));
|
||||
_conns.put(hostUuid, masterConn);
|
||||
|
||||
s_logger.info("Connection made to " + ipAddress + " for host "
|
||||
+ hostUuid + ". Pool Uuid is " + poolUuid);
|
||||
|
||||
return masterConn;
|
||||
} catch (XenAPIException e) {
|
||||
s_logger.warn("Unable to make a connection to the server "
|
||||
+ ipAddress);
|
||||
throw new CloudRuntimeException(
|
||||
"Unable to make a connection to the server " + ipAddress);
|
||||
} catch (XmlRpcException e) {
|
||||
s_logger.warn("Unable to make a connection to the server "
|
||||
+ ipAddress, e);
|
||||
throw new CloudRuntimeException(
|
||||
"Unable to make a connection to the server " + ipAddress);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new CloudRuntimeException(
|
||||
"How can we get a malformed exception for this "
|
||||
+ ipAddress);
|
||||
} finally {
|
||||
if (slaveConn != null) {
|
||||
try {
|
||||
Session.localLogout(slaveConn);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
slaveConn.dispose();
|
||||
slaveConn = null;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Pool.Record getPoolRecord(Connection conn)
|
||||
static private Pool.Record getPoolRecord(Connection conn)
|
||||
throws XmlRpcException, XenAPIException {
|
||||
Map<Pool, Pool.Record> pools = Pool.getAllRecords(conn);
|
||||
assert pools.size() == 1 : "Pool size is not one....hmmm....wth? "
|
||||
|
|
@ -708,72 +594,46 @@ public class XenServerConnectionPool {
|
|||
return s_instance;
|
||||
}
|
||||
|
||||
protected class ConnectionInfo {
|
||||
public String masterIp;
|
||||
public XenServerConnection conn;
|
||||
public HashMap<String, Member> refs = new HashMap<String, Member>();
|
||||
}
|
||||
|
||||
protected class Member {
|
||||
public String ipAddr;
|
||||
public String uuid;
|
||||
public String username;
|
||||
public String password;
|
||||
|
||||
|
||||
public Member(String ipAddr, String uuid, String username, String password) {
|
||||
this.ipAddr = ipAddr;
|
||||
this.uuid = uuid;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
|
||||
public class XenServerConnection extends Connection {
|
||||
long _interval;
|
||||
int _retries;
|
||||
String _ip;
|
||||
String _username;
|
||||
String _password;
|
||||
URL _url;
|
||||
ConnectionInfo _info;
|
||||
String _poolUuid;
|
||||
|
||||
public XenServerConnection(URL url, String username, String password,
|
||||
public XenServerConnection(URL url, String ip, String username, String password,
|
||||
int retries, int interval, int wait) {
|
||||
super(url, wait);
|
||||
_url = url;
|
||||
_ip = ip;
|
||||
_retries = retries;
|
||||
_username = username;
|
||||
_password = password;
|
||||
_interval = (long) interval * 1000;
|
||||
}
|
||||
|
||||
public XenServerConnection(XenServerConnection that) {
|
||||
super(that._url, that.getSessionReference(), that._wait);
|
||||
this._url = that._url;
|
||||
this._retries = that._retries;
|
||||
this._username = that._username;
|
||||
this._password = that._password;
|
||||
this._interval = that._interval;
|
||||
this._info = that._info;
|
||||
this._poolUuid = that._poolUuid;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void setInfo(String poolUuid, ConnectionInfo info) {
|
||||
this._poolUuid = poolUuid;
|
||||
this._info = info;
|
||||
}
|
||||
|
||||
public int getWaitTimeout() {
|
||||
return _wait;
|
||||
}
|
||||
|
||||
public String get_poolUuid() {
|
||||
public String getPoolUuid() {
|
||||
return _poolUuid;
|
||||
}
|
||||
|
||||
|
||||
public String getUsername() {
|
||||
return _username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return _password;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return _ip;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map dispatch(String method_call, Object[] method_params) throws XmlRpcException, XenAPIException {
|
||||
if (method_call.equals("session.local_logout")
|
||||
|
|
@ -814,9 +674,7 @@ public class XenServerConnectionPool {
|
|||
s_logger.debug("Session is invalid for method: " + method_call + " due to " + e.getMessage() + ". Reconnecting...retry="
|
||||
+ retries);
|
||||
if (retries >= _retries) {
|
||||
if (_poolUuid != null) {
|
||||
cleanup(_poolUuid, _info);
|
||||
}
|
||||
removeConnect(_poolUuid);
|
||||
throw e;
|
||||
}
|
||||
Session.loginWithPassword(this, _username,
|
||||
|
|
@ -826,24 +684,18 @@ public class XenServerConnectionPool {
|
|||
s_logger.debug("XmlRpcException for method: " + method_call + " due to " + e.getMessage() + ". Reconnecting...retry="
|
||||
+ retries);
|
||||
if (retries >= _retries) {
|
||||
if (_poolUuid != null) {
|
||||
cleanup(_poolUuid, _info);
|
||||
}
|
||||
removeConnect(_poolUuid);
|
||||
throw e;
|
||||
}
|
||||
Throwable cause = e.getCause();
|
||||
if (cause == null || !(cause instanceof SocketException)) {
|
||||
if (_poolUuid != null) {
|
||||
cleanup(_poolUuid, _info);
|
||||
}
|
||||
removeConnect(_poolUuid);
|
||||
throw e;
|
||||
}
|
||||
} catch (Types.HostIsSlave e) {
|
||||
s_logger.debug("HostIsSlave Exception for method: " + method_call + " due to " + e.getMessage() + ". Reconnecting...retry="
|
||||
+ retries);
|
||||
if (_poolUuid != null) {
|
||||
cleanup(_poolUuid, _info);
|
||||
}
|
||||
removeConnect(_poolUuid);
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
|
@ -852,13 +704,9 @@ public class XenServerConnectionPool {
|
|||
} catch (InterruptedException e) {
|
||||
s_logger.info("Who woke me from my slumber?");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
assert false : "We should never get here";
|
||||
if (_poolUuid != null) {
|
||||
cleanup(_poolUuid, _info);
|
||||
}
|
||||
removeConnect(_poolUuid);
|
||||
}
|
||||
throw new CloudRuntimeException("After " + _retries
|
||||
+ " retries, we cannot contact the host ");
|
||||
|
|
@ -866,4 +714,4 @@ public class XenServerConnectionPool {
|
|||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue