// Copyright 2012 Citrix Systems, Inc. Licensed under the // Apache License, Version 2.0 (the "License"); you may not use this // file except in compliance with the License. Citrix Systems, Inc. // reserves all rights not expressly granted by the License. // You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.hypervisor.xen.resource; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.net.SocketException; import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.Queue; import java.util.Set; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSession; import org.apache.log4j.Logger; import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.client.XmlRpcClientException; import com.cloud.utils.NumbersUtil; import com.cloud.utils.PropertiesUtil; import com.cloud.utils.exception.CloudRuntimeException; import com.xensource.xenapi.APIVersion; import com.xensource.xenapi.Connection; import com.xensource.xenapi.Host; import com.xensource.xenapi.Pool; import com.xensource.xenapi.Session; import com.xensource.xenapi.Types; import com.xensource.xenapi.Types.BadServerResponse; import com.xensource.xenapi.Types.UuidInvalid; import com.xensource.xenapi.Types.XenAPIException; public class XenServerConnectionPool { private static final Logger s_logger = Logger.getLogger(XenServerConnectionPool.class); protected HashMap<String /* poolUuid */, XenServerConnection> _conns = new HashMap<String, XenServerConnection>(); protected int _retries; protected int _interval; protected static boolean s_managePool = true; protected static long s_sleepOnError = 10 * 1000; // in ms static { File file = PropertiesUtil.findConfigFile("environment.properties"); if (file == null) { s_logger.debug("Unable to find environment.properties"); } else { FileInputStream finputstream; try { finputstream = new FileInputStream(file); final Properties props = new Properties(); props.load(finputstream); finputstream.close(); String search = props.getProperty("manage.xenserver.pool.master"); if (search != null) { s_managePool = Boolean.parseBoolean(search); } search = props.getProperty("sleep.interval.on.error"); if (search != null) { s_sleepOnError = NumbersUtil.parseInterval(search, 10) * 1000; } s_logger.info("XenServer Connection Pool Configs: manage.xenserver.pool.master=" + s_managePool + "; sleep.interval.on.error=" + s_sleepOnError); } catch (FileNotFoundException e) { s_logger.debug("File is not found", e); } catch (IOException e) { s_logger.debug("IO Exception while reading file", e); } } try { javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1]; javax.net.ssl.TrustManager tm = new TrustAllManager(); trustAllCerts[0] = tm; javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("TLS"); sc.init(null, trustAllCerts, null); javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HostnameVerifier hv = new HostnameVerifier() { @Override public boolean verify(String hostName, SSLSession session) { return true; } }; HttpsURLConnection.setDefaultHostnameVerifier(hv); } catch (Exception e) { } } protected XenServerConnectionPool() { _retries = 3; _interval = 3; } 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) { if (msec < 100) break; try { Thread.sleep(msec); return; } catch (InterruptedException e) { msec = firetime - System.currentTimeMillis(); } } } public boolean joinPool(Connection conn, String hostIp, String masterIp, String username, Queue<String> password) { try { join(conn, masterIp, username, password); if (s_logger.isDebugEnabled()) { s_logger.debug("Host(" + hostIp + ") Join the pool at " + masterIp); } try { // slave will restart xapi in 10 sec Thread.sleep(10000); } catch (InterruptedException e) { } for (int i = 0 ; i < 15; i++) { Connection slaveConn = null; Session slaveSession = null; try { if (s_logger.isDebugEnabled()) { s_logger.debug("Logging on as the slave to " + hostIp); } slaveConn = new Connection(getURL(hostIp), 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())) { if (s_logger.isDebugEnabled()) { s_logger.debug("Host(" + hostIp + ") Joined the pool at " + masterIp); } return true; } } catch (Exception e) { } finally { if (slaveSession != null) { try { Session.logout(slaveConn); } catch (Exception e) { } slaveConn.dispose(); } } try { Thread.sleep(2000); } catch (InterruptedException e) { } } } catch (Exception e) { String msg = "Catch " + e.getClass().getName() + " Unable to allow host " + hostIp + " to join pool " + masterIp + " due to " + e.toString(); s_logger.warn(msg, e); } if (s_logger.isDebugEnabled()) { s_logger.debug("Host(" + hostIp + ") unable to Join the pool at " + masterIp); } return false; } 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"); } } private void localLogout(Connection conn) { if ( conn == null ) return; try { if( s_logger.isTraceEnabled()) { s_logger.trace("Logging out of the session " + conn.getSessionReference()); } Session.localLogout(conn); } catch (Exception e) { s_logger.debug("localLogout has problem " + e.getMessage()); } finally { conn.dispose(); conn = null; } } public Connection slaveConnect(String ip, String username, Queue<String> password) { Connection conn = null; try{ conn = new Connection(getURL(ip), 10); slaveLocalLoginWithPassword(conn, username, password); return conn; }catch ( Exception e){ s_logger.debug("Failed to slave local login to " + ip); } return null; } 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); } public String getMasterIp(String ip, String username, Queue<String> password) throws XenAPIException { Connection slaveConn = null; try{ slaveConn = new Connection(getURL(ip), 10); slaveLocalLoginWithPassword(slaveConn, username, password); if (s_logger.isDebugEnabled()) { s_logger.debug("Slave logon to " + ip); } String masterIp = null; Pool.Record pr = getPoolRecord(slaveConn); Host master = pr.master; masterIp = master.getAddress(slaveConn); return masterIp; }catch(Types.SessionAuthenticationFailed e){ s_logger.debug("Failed to slave local login to " + ip + " due to " + e.toString()); throw e; }catch ( Exception e){ s_logger.debug("Failed to slave local login to " + ip + " due to " + e.toString()); } finally { localLogout(slaveConn); slaveConn = null; } throw new RuntimeException("can not get 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) { } } } } private void PoolEmergencyResetMaster(String slaveIp, String masterIp, 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; try { s_logger.debug("Trying to reset master of slave " + slaveIp + " to " + masterIp); slaveConn = new Connection(getURL(slaveIp), 10); slaveLocalLoginWithPassword(slaveConn, username, password); Pool.emergencyResetMaster(slaveConn, masterIp); forceSleep(10); for (int i = 0; i < 30; i++) { try { slaveLocalLoginWithPassword(slaveConn, username, password); 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) { } finally { localLogout(slaveConn); slaveConn = null; } // wait 2 second forceSleep(2); } throw new CloudRuntimeException("Unable to reset master of slave " + slaveIp + " to " + masterIp + "after 30 retry"); } catch (Exception e) { throw new CloudRuntimeException("Unable to reset master of slave " + slaveIp + " to " + masterIp + " due to " + e.toString()); } finally { localLogout(slaveConn); slaveConn = null; } } protected void ensurePoolIntegrity(Connection conn, String masterIp, String username, Queue<String> password, int wait) { try { // try recoverSlave first Set<Host> rcSlaves = Pool.recoverSlaves(conn); // wait 10 second forceSleep(10); 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); slaveConn = new Connection(getURL(slaveIp), 10); slaveLocalLoginWithPassword(slaveConn, username, password); Pool.Record pr = getPoolRecord(slaveConn); String mIp = pr.master.getAddress(slaveConn); if (mIp.trim().equals(masterIp.trim())) { break; } } catch (Exception e) { } finally { localLogout(slaveConn); slaveConn = null; } // wait 2 second forceSleep(2); } } // 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); 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, password); } } catch (Exception e) { s_logger.debug("Unable to login to slave " + slaveIp + " error " + e.getMessage()); } finally { localLogout(slaveConn); slaveConn = null; } } } catch (Exception e) { if (s_logger.isDebugEnabled()) { s_logger.debug("Catch " + e.getClass().getName() + " due to " + e.toString()); } } } public URL getURL(String ip){ try { return new URL("https://" + 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, 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=" + 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("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; } protected Session slaveLocalLoginWithPassword(Connection conn, String username, Queue<String> password) throws BadServerResponse, XenAPIException, XmlRpcException { Session s = null; boolean logged_in=false; Exception ex = null; while (!logged_in){ try { s = Session.slaveLocalLoginWithPassword(conn, username, password.peek()); 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; } break; } } } return s; } 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; } protected void join(Connection conn, String masterIp, String username, Queue<String> password) throws BadServerResponse, XenAPIException, XmlRpcException, Types.JoiningHostCannotContainSharedSrs { boolean logged_in=false; Exception ex = null; while (!logged_in){ try { Pool.join(conn, masterIp, username, password.peek()); 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; } break; } } } } static public 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? " + pools.size(); return pools.values().iterator().next(); } private static final XenServerConnectionPool s_instance = new XenServerConnectionPool(); public static XenServerConnectionPool getInstance() { return s_instance; } public class XenServerConnection extends Connection { long _interval; int _retries; String _ip; String _username; Queue<String> _password; String _poolUuid; public XenServerConnection(URL url, String ip, String username, Queue<String> password, int retries, int interval, int wait) { super(url, wait); _ip = ip; _retries = retries; _username = username; _password = password; _interval = (long) interval * 1000; } public String getPoolUuid() { return _poolUuid; } public String getUsername() { return _username; } public Queue<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") || 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 static class TrustAllManager implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager { @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public boolean isServerTrusted(java.security.cert.X509Certificate[] certs) { return true; } public boolean isClientTrusted(java.security.cert.X509Certificate[] certs) { return true; } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { return; } @Override public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { return; } } }