diff --git a/api/src/com/cloud/agent/api/UpdateHostPasswordCommand.java b/api/src/com/cloud/agent/api/UpdateHostPasswordCommand.java new file mode 100644 index 00000000000..5c848e5a34c --- /dev/null +++ b/api/src/com/cloud/agent/api/UpdateHostPasswordCommand.java @@ -0,0 +1,46 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.cloud.agent.api; + + + +public class UpdateHostPasswordCommand extends Command { + protected String _username; + protected String _new_password; + + protected UpdateHostPasswordCommand() { + } + + public UpdateHostPasswordCommand(String username, String new_password) { + this._username = username; + this._new_password = new_password; + } + + public String getNewPassword() { + return _new_password; + } + + public String getUsername() { + return _username; + } + + @Override + public boolean executeInSequence() { + return false; + } +} diff --git a/api/src/com/cloud/api/commands/UpdateHostPasswordCmd.java b/api/src/com/cloud/api/commands/UpdateHostPasswordCmd.java index ec6849d6b46..b386d700d27 100644 --- a/api/src/com/cloud/api/commands/UpdateHostPasswordCmd.java +++ b/api/src/com/cloud/api/commands/UpdateHostPasswordCmd.java @@ -90,6 +90,7 @@ public class UpdateHostPasswordCmd extends BaseCmd { @Override public void execute() { _mgr.updateHostPassword(this); + _resourceService.updateHostPassword(this); this.setResponseObject(new SuccessResponse(getCommandName())); } } \ No newline at end of file diff --git a/api/src/com/cloud/resource/ResourceService.java b/api/src/com/cloud/resource/ResourceService.java index 429d976b0d7..54f09effb64 100644 --- a/api/src/com/cloud/resource/ResourceService.java +++ b/api/src/com/cloud/resource/ResourceService.java @@ -81,6 +81,8 @@ public interface ResourceService { */ boolean deleteHost(long hostId, boolean isForced); + boolean updateHostPassword(UpdateHostPasswordCmd upasscmd); + Host getHost(long hostId); Cluster getCluster(Long clusterId); diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 4d9fce79870..d9c9f344824 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -33,9 +33,11 @@ import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Queue; import java.util.Set; import java.util.UUID; @@ -119,6 +121,7 @@ import com.cloud.agent.api.StopAnswer; import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.StoragePoolInfo; import com.cloud.agent.api.UpgradeSnapshotCommand; +import com.cloud.agent.api.UpdateHostPasswordCommand; import com.cloud.agent.api.VmStatsEntry; import com.cloud.agent.api.check.CheckSshAnswer; import com.cloud.agent.api.check.CheckSshCommand; @@ -229,7 +232,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected static final int MB = 1024 * 1024; protected String _name; protected String _username; - protected String _password; + protected Queue _password=new LinkedList(); protected final int _retry = 24; protected final int _sleep = 10000; protected long _dcId; @@ -355,7 +358,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe URL slaveUrl = null; slaveUrl = _connPool.getURL(_host.ip); slaveConn = new Connection(slaveUrl, 10); - slaveSession = Session.slaveLocalLoginWithPassword(slaveConn, _username, _password); + slaveSession = _connPool.slaveLocalLoginWithPassword(slaveConn, _username, _password); return true; } catch (Exception e) { } finally { @@ -369,7 +372,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } return false; } - + protected String logX(XenAPIObject obj, String msg) { return new StringBuilder("Host ").append(_host.ip).append(" ").append(obj.toWireString()).append(": ").append(msg).toString(); } @@ -489,6 +492,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return execute((OvsCreateTunnelCommand)cmd); } else if (cmd instanceof OvsDestroyTunnelCommand) { return execute((OvsDestroyTunnelCommand)cmd); + } else if (cmd instanceof UpdateHostPasswordCommand) { + return execute((UpdateHostPasswordCommand)cmd); } else { return Answer.createUnsupportedCommandAnswer(cmd); } @@ -3920,7 +3925,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(hr.address, 22); try { sshConnection.connect(null, 60000, 60000); - if (!sshConnection.authenticateWithPassword(_username, _password)) { + if (!sshConnection.authenticateWithPassword(_username, _password.peek())) { throw new CloudRuntimeException("Unable to authenticate"); } @@ -4263,6 +4268,12 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } + + private Answer execute(UpdateHostPasswordCommand cmd) { + _password.add(cmd.getNewPassword()); + return new Answer(cmd, true, null); + } + private OvsCreateTunnelAnswer execute(OvsCreateTunnelCommand cmd) { Connection conn = getConnection(); String bridge = "unknown"; @@ -4567,7 +4578,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe _host.ip = (String) params.get("ipaddress"); _username = (String) params.get("username"); - _password = (String) params.get("password"); + _password.add((String) params.get("password")); _pod = (String) params.get("pod"); _cluster = (String)params.get("cluster"); _privateNetworkName = (String) params.get("private.network.device"); @@ -4613,7 +4624,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe private void CheckXenHostInfo() throws ConfigurationException { Connection conn = _connPool.slaveConnect(_host.ip, _username, _password); - if( conn == null ) { + if( conn == null ) { throw new ConfigurationException("Can not create slave connection to " + _host.ip); } try { diff --git a/core/src/com/cloud/hypervisor/xen/resource/XenServerConnectionPool.java b/core/src/com/cloud/hypervisor/xen/resource/XenServerConnectionPool.java index 6e8097824e7..4c640a79dd5 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/XenServerConnectionPool.java +++ b/core/src/com/cloud/hypervisor/xen/resource/XenServerConnectionPool.java @@ -21,6 +21,7 @@ import java.net.SocketException; import java.net.URL; import java.util.HashMap; import java.util.Map; +import java.util.Queue; import java.util.Set; import javax.net.ssl.HostnameVerifier; @@ -38,6 +39,7 @@ 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.XenAPIException; import com.xensource.xenapi.Types.UuidInvalid; @@ -120,9 +122,9 @@ public class XenServerConnectionPool { } } - public boolean joinPool(Connection conn, String hostIp, String masterIp, String username, String password) { + public boolean joinPool(Connection conn, String hostIp, String masterIp, String username, Queue password) { try { - Pool.join(conn, masterIp, username, password); + join(conn, masterIp, username, password); if (s_logger.isDebugEnabled()) { s_logger.debug("Host(" + hostIp + ") Join the pool at " + masterIp); } @@ -139,7 +141,7 @@ public class XenServerConnectionPool { s_logger.debug("Logging on as the slave to " + hostIp); } slaveConn = new Connection(getURL(hostIp), 10); - slaveSession = Session.slaveLocalLoginWithPassword(slaveConn, username, password); + slaveSession = slaveLocalLoginWithPassword(slaveConn, username, password); if (s_logger.isDebugEnabled()) { s_logger.debug("Slave logon successful. session= " + slaveSession); } @@ -179,7 +181,7 @@ public class XenServerConnectionPool { } public void switchMaster(String slaveIp, String poolUuid, - Connection conn, Host host, String username, String password, + Connection conn, Host host, String username, Queue password, int wait) throws XmlRpcException, XenAPIException { synchronized (poolUuid.intern()) { String masterIp = host.getAddress(conn); @@ -200,8 +202,7 @@ public class XenServerConnectionPool { Session slaveSession = null; slaveConn = new Connection(getURL(slaveIp), 10); - slaveSession = Session.slaveLocalLoginWithPassword(slaveConn, - username, password); + slaveSession = slaveLocalLoginWithPassword(slaveConn, username, password); if (s_logger.isDebugEnabled()) { s_logger.debug("Slave logon successful. session= " @@ -216,24 +217,17 @@ public class XenServerConnectionPool { } s_logger.debug("Logging on as the master to " + masterIp); masterConn = new Connection(getURL(masterIp), 10); - Session.loginWithPassword(masterConn, username, password, - APIVersion.latest().toString()); + loginWithPassword(masterConn, username, password, APIVersion.latest().toString()); removeConnect(poolUuid); - ensurePoolIntegrity(masterConn, masterIp, username, password, - wait); + ensurePoolIntegrity(masterConn, masterIp, username, password, wait); PoolSyncDB(masterConn); return; } catch (Types.HostIsSlave e) { - s_logger - .debug("HostIsSlaveException: Still waiting for the conversion to the master"); + 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()); + 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()); + s_logger.debug("Exception: Still waiting for the conversion to the master" + e.getMessage()); } finally { if (masterConn != null) { try { @@ -271,11 +265,11 @@ public class XenServerConnectionPool { } } - public Connection slaveConnect(String ip, String username, String password) { + public Connection slaveConnect(String ip, String username, Queue password) { Connection conn = null; try{ conn = new Connection(getURL(ip), 10); - Session.slaveLocalLoginWithPassword(conn, username, password); + slaveLocalLoginWithPassword(conn, username, password); return conn; }catch ( Exception e){ s_logger.debug("Failed to slave local login to " + ip); @@ -283,13 +277,12 @@ public class XenServerConnectionPool { return null; } - public Connection masterConnect(String ip, String username, String password) { + public Connection masterConnect(String ip, String username, Queue password) { Connection conn = null; try{ conn = new Connection(getURL(ip), 10); s_logger.debug("Logging on as the master to " + ip); - Session.loginWithPassword(conn, username, password, - APIVersion.latest().toString()); + loginWithPassword(conn, username, password, APIVersion.latest().toString()); return conn; }catch ( Exception e){ s_logger.debug("Failed to slave local login to " + ip); @@ -298,11 +291,11 @@ public class XenServerConnectionPool { } - public String getMasterIp(String ip, String username, String password) throws XenAPIException { + public String getMasterIp(String ip, String username, Queue password) throws XenAPIException { Connection slaveConn = null; try{ slaveConn = new Connection(getURL(ip), 10); - Session.slaveLocalLoginWithPassword(slaveConn, username, password); + slaveLocalLoginWithPassword(slaveConn, username, password); if (s_logger.isDebugEnabled()) { s_logger.debug("Slave logon to " + ip); @@ -346,13 +339,13 @@ public class XenServerConnectionPool { } } - void PoolEmergencyTransitionToMaster(String slaveIp, String username, String password) { + void PoolEmergencyTransitionToMaster(String slaveIp, String username, Queue password) { Connection slaveConn = null; Connection c = null; try{ s_logger.debug("Trying to transition master to " + slaveIp); slaveConn = new Connection(getURL(slaveIp), 10); - Session.slaveLocalLoginWithPassword(slaveConn, username, password); + slaveLocalLoginWithPassword(slaveConn, username, password); Pool.emergencyTransitionToMaster(slaveConn); // restart xapi in 10 sec forceSleep(10); @@ -360,7 +353,7 @@ public class XenServerConnectionPool { c = new Connection(getURL(slaveIp), 10); for (int i = 0; i < 30; i++) { try { - Session.loginWithPassword(c, username, password, APIVersion.latest().toString()); + loginWithPassword(c, username, password, APIVersion.latest().toString()); s_logger.debug("Succeeded to transition master to " + slaveIp); return; } catch (Types.HostIsSlave e) { @@ -388,26 +381,25 @@ public class XenServerConnectionPool { } private void PoolEmergencyResetMaster(String slaveIp, String masterIp, - String username, String password) { + String username, Queue password) { Connection slaveConn = null; try { s_logger.debug("Trying to reset master of slave " + slaveIp + " to " + masterIp); slaveConn = new Connection(getURL(slaveIp), 10); - Session.slaveLocalLoginWithPassword(slaveConn, username, password); + slaveLocalLoginWithPassword(slaveConn, username, password); Pool.emergencyResetMaster(slaveConn, masterIp); forceSleep(10); for (int i = 0; i < 30; i++) { try { - Session.slaveLocalLoginWithPassword(slaveConn, username, password); + 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); + s_logger.debug("Succeeded to reset master of slave " + slaveIp + " to " + masterIp); return; } - } catch (Exception e) { + } catch (Exception e) { } finally { localLogout(slaveConn); slaveConn = null; @@ -427,7 +419,7 @@ public class XenServerConnectionPool { } protected void ensurePoolIntegrity(Connection conn, - String masterIp, String username, String password, int wait) { + String masterIp, String username, Queue password, int wait) { try { // try recoverSlave first Set rcSlaves = Pool.recoverSlaves(conn); @@ -441,13 +433,13 @@ public class XenServerConnectionPool { String slaveIp = slave.getAddress(conn); s_logger.debug("Logging on as the slave to " + slaveIp); slaveConn = new Connection(getURL(slaveIp), 10); - Session.slaveLocalLoginWithPassword(slaveConn, username, password); + 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) { + } catch (Exception e) { } finally { localLogout(slaveConn); slaveConn = null; @@ -465,17 +457,14 @@ public class XenServerConnectionPool { s_logger.debug("Logging on as the slave to " + slaveIp); slaveConn = new Connection(getURL(slaveIp), 10); - Session.slaveLocalLoginWithPassword(slaveConn, username, - password); + 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); + PoolEmergencyResetMaster(slaveIp, masterIp, username, password); } } catch (Exception e) { - s_logger.debug("Unable to login to slave " + slaveIp - + " error " + e.getMessage()); + s_logger.debug("Unable to login to slave " + slaveIp + " error " + e.getMessage()); } finally { localLogout(slaveConn); slaveConn = null; @@ -501,7 +490,7 @@ public class XenServerConnectionPool { } public Connection connect(String hostUuid, String poolUuid, String ipAddress, - String username, String password, int wait) { + String username, Queue password, int wait) { XenServerConnection mConn = null; Connection sConn = null; String masterIp = null; @@ -522,12 +511,11 @@ public class XenServerConnectionPool { } 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()); + 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; } @@ -535,21 +523,21 @@ public class XenServerConnectionPool { String msg = "Catch Exception: " + e.getClass().getName() + " Can't connect host " + ipAddress + " due to " + e.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug(msg); - } + } PoolEmergencyResetMaster(ipAddress, mConn.getIp(), mConn.getUsername(), mConn.getPassword()); return mConn; } catch (Types.HostOffline e ) { String msg = "Catch Exception: " + e.getClass().getName() + " Host is offline " + ipAddress + " due to " + e.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug(msg); - } + } PoolEmergencyResetMaster(ipAddress, mConn.getIp(), mConn.getUsername(), mConn.getPassword()); return mConn; } 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()); return mConn; } catch (UuidInvalid e) { @@ -573,13 +561,12 @@ public class XenServerConnectionPool { try { try { sConn = new Connection(getURL(ipAddress), 5); - Session.slaveLocalLoginWithPassword(sConn, - username, password); + 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; @@ -587,11 +574,9 @@ public class XenServerConnectionPool { pr = getPoolRecord(sConn); } catch (Exception e) { PoolEmergencyTransitionToMaster(ipAddress, username, password); - mConn = new XenServerConnection(getURL(ipAddress), ipAddress, username, - password, _retries, _interval, wait); + mConn = new XenServerConnection(getURL(ipAddress), ipAddress, username, password, _retries, _interval, wait); try { - Session.loginWithPassword(mConn, username, password, - APIVersion.latest().toString()); + 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(); @@ -607,8 +592,7 @@ public class XenServerConnectionPool { } throw new CloudRuntimeException(msg); } else { - ensurePoolIntegrity(mConn, ipAddress, username, password, - wait); + ensurePoolIntegrity(mConn, ipAddress, username, password, wait); addConnect(poolUuid, mConn); return mConn; } @@ -622,10 +606,8 @@ public class XenServerConnectionPool { } try { masterIp = pr.master.getAddress(sConn); - mConn = new XenServerConnection(getURL(masterIp), masterIp, username, - password, _retries, _interval, wait); - Session.loginWithPassword(mConn, username, password, - APIVersion.latest().toString()); + 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) { @@ -641,6 +623,150 @@ public class XenServerConnectionPool { } } } + + + protected Session slaveLocalLoginWithPassword(Connection conn, String username, Queue 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 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 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 { @@ -664,10 +790,10 @@ public class XenServerConnectionPool { int _retries; String _ip; String _username; - String _password; + Queue _password; String _poolUuid; - public XenServerConnection(URL url, String ip, String username, String password, + public XenServerConnection(URL url, String ip, String username, Queue password, int retries, int interval, int wait) { super(url, wait); _ip = ip; @@ -686,7 +812,7 @@ public class XenServerConnectionPool { return _username; } - public String getPassword() { + public Queue getPassword() { return _password; } @@ -737,11 +863,10 @@ public class XenServerConnectionPool { removeConnect(_poolUuid); throw e; } - Session.loginWithPassword(this, _username, - _password, APIVersion.latest().toString()); + 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()); + s_logger.debug("XmlRpcClientException for method: " + method_call + " due to " + e.getMessage()); removeConnect(_poolUuid); throw e; } catch (XmlRpcException e) { @@ -774,8 +899,7 @@ public class XenServerConnectionPool { throw new CloudRuntimeException("After " + _retries + " retries, we cannot contact the host "); } - - + } public static class TrustAllManager implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager { diff --git a/server/src/com/cloud/agent/manager/AgentAttache.java b/server/src/com/cloud/agent/manager/AgentAttache.java index 56a5356050a..f1899c4c215 100644 --- a/server/src/com/cloud/agent/manager/AgentAttache.java +++ b/server/src/com/cloud/agent/manager/AgentAttache.java @@ -467,6 +467,12 @@ public abstract class AgentAttache { */ public abstract void send(Request req) throws AgentUnavailableException; + /** + * Update password. + * @param new/changed password. + */ + public abstract void updatePassword(Command new_password); + /** * Process disconnect. * @param state state of the agent. diff --git a/server/src/com/cloud/agent/manager/AgentManagerImpl.java b/server/src/com/cloud/agent/manager/AgentManagerImpl.java index e22a770f84f..46bf16166d6 100755 --- a/server/src/com/cloud/agent/manager/AgentManagerImpl.java +++ b/server/src/com/cloud/agent/manager/AgentManagerImpl.java @@ -71,6 +71,7 @@ import com.cloud.agent.api.StartupRoutingCommand; import com.cloud.agent.api.StartupStorageCommand; import com.cloud.agent.api.StartupTrafficMonitorCommand; import com.cloud.agent.api.UnsupportedAnswer; +import com.cloud.agent.api.UpdateHostPasswordCommand; import com.cloud.agent.manager.allocator.HostAllocator; import com.cloud.agent.manager.allocator.PodAllocator; import com.cloud.agent.transport.Request; @@ -84,6 +85,7 @@ import com.cloud.api.commands.DeleteClusterCmd; import com.cloud.api.commands.PrepareForMaintenanceCmd; import com.cloud.api.commands.ReconnectHostCmd; import com.cloud.api.commands.UpdateHostCmd; +import com.cloud.api.commands.UpdateHostPasswordCmd; import com.cloud.capacity.Capacity; import com.cloud.capacity.CapacityVO; import com.cloud.capacity.dao.CapacityDao; @@ -1206,6 +1208,27 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, ResourceS _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), host.getDataCenterId()); return deleteHost(hostId, isForced, caller); } + + + @Override + public boolean updateHostPassword(UpdateHostPasswordCmd upasscmd) { + if (upasscmd.getClusterId() == null) { + //update agent attache password + AgentAttache agent = this.findAttache(upasscmd.getHostId()); + UpdateHostPasswordCommand cmd = new UpdateHostPasswordCommand(upasscmd.getUsername(), upasscmd.getPassword()); + agent.updatePassword(cmd); + } + else { + // get agents for the cluster + List hosts = _hostDao.listByCluster(upasscmd.getClusterId()); + for (HostVO h : hosts) { + AgentAttache agent = this.findAttache(h.getId()); + UpdateHostPasswordCommand cmd = new UpdateHostPasswordCommand(upasscmd.getUsername(), upasscmd.getPassword()); + agent.updatePassword(cmd); + } + } + return false; + } @DB protected boolean deleteSecondaryStorageHost(HostVO secStorageHost) { @@ -1719,6 +1742,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, ResourceS try { resource.configure(host.getName(), params); } catch (ConfigurationException e) { + e.printStackTrace(); s_logger.warn("Unable to configure resource due to ", e); return; } @@ -2433,12 +2457,6 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, ResourceS return attache; } - public AgentAttache findAgent(long hostId) { - synchronized (_agents) { - return _agents.get(hostId); - } - } - protected AgentAttache createAttache(long id, HostVO server, Link link) { s_logger.debug("create ConnectedAgentAttache for " + id); final AgentAttache attache = new ConnectedAgentAttache(this, id, link, server.getStatus() == Status.Maintenance || server.getStatus() == Status.ErrorInMaintenance @@ -3005,4 +3023,5 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, ResourceS protected AgentManagerImpl() { } + } diff --git a/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java b/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java index 29bb990ad25..1ac5df77977 100644 --- a/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java +++ b/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java @@ -515,7 +515,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust if (Request.fromServer(data)) { - AgentAttache agent = findAgent(hostId); + AgentAttache agent = findAttache(hostId); if (Request.isControl(data)) { if (agent == null) { diff --git a/server/src/com/cloud/agent/manager/ConnectedAgentAttache.java b/server/src/com/cloud/agent/manager/ConnectedAgentAttache.java index 953ff2eec62..fa64d59f8e8 100644 --- a/server/src/com/cloud/agent/manager/ConnectedAgentAttache.java +++ b/server/src/com/cloud/agent/manager/ConnectedAgentAttache.java @@ -23,6 +23,7 @@ import java.nio.channels.ClosedChannelException; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Command; import com.cloud.agent.transport.Request; import com.cloud.exception.AgentUnavailableException; import com.cloud.host.Status; @@ -94,4 +95,9 @@ public class ConnectedAgentAttache extends AgentAttache { super.finalize(); } } + + @Override + public void updatePassword(Command newPassword) { + throw new IllegalStateException("Should not have come here "); + } } diff --git a/server/src/com/cloud/agent/manager/DirectAgentAttache.java b/server/src/com/cloud/agent/manager/DirectAgentAttache.java index 30ddedae0c7..a2b182b732d 100644 --- a/server/src/com/cloud/agent/manager/DirectAgentAttache.java +++ b/server/src/com/cloud/agent/manager/DirectAgentAttache.java @@ -24,6 +24,8 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import javax.naming.ConfigurationException; + import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -38,6 +40,7 @@ import com.cloud.exception.AgentUnavailableException; import com.cloud.host.Status; import com.cloud.host.Status.Event; import com.cloud.resource.ServerResource; +import com.cloud.resource.hypervisor.HypervisorResource; import com.cloud.utils.concurrency.NamedThreadFactory; public class DirectAgentAttache extends AgentAttache { @@ -220,4 +223,10 @@ public class DirectAgentAttache extends AgentAttache { } } } + + + @Override + public void updatePassword(Command new_password) { + _resource.executeRequest(new_password); + } } diff --git a/server/src/com/cloud/agent/manager/DummyAttache.java b/server/src/com/cloud/agent/manager/DummyAttache.java index ca4635dc003..8283fa54634 100644 --- a/server/src/com/cloud/agent/manager/DummyAttache.java +++ b/server/src/com/cloud/agent/manager/DummyAttache.java @@ -18,6 +18,7 @@ package com.cloud.agent.manager; import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Command; import com.cloud.agent.transport.Request; import com.cloud.exception.AgentUnavailableException; import com.cloud.host.Status; @@ -47,4 +48,10 @@ public class DummyAttache extends AgentAttache { } + + @Override + public void updatePassword(Command newPassword) { + throw new IllegalStateException("Should not have come here "); + } + } diff --git a/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java b/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java index 435297c2c6a..31659fc190b 100755 --- a/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java +++ b/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java @@ -22,8 +22,10 @@ import java.net.URI; import java.net.UnknownHostException; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Queue; import java.util.Set; import javax.ejb.Local; @@ -148,9 +150,11 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L } String hostname = url.getHost(); InetAddress ia = InetAddress.getByName(hostname); - String hostIp = ia.getHostAddress(); - String masterIp = _connPool.getMasterIp(hostIp, username, password); - conn = _connPool.masterConnect(masterIp, username, password); + String hostIp = ia.getHostAddress(); + Queue pass=new LinkedList(); + pass.add(password); + String masterIp = _connPool.getMasterIp(hostIp, username, pass); + conn = _connPool.masterConnect(masterIp, username, pass); if (conn == null) { String msg = "Unable to get a connection to " + url; s_logger.debug(msg); @@ -335,12 +339,14 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L String masterIp = null; String username = null; String password = null; + Queue pass=new LinkedList(); for (HostVO host : hosts) { _hostDao.loadDetails(host); username = host.getDetail("username"); password = host.getDetail("password"); + pass.add(password); String address = host.getPrivateIpAddress(); - Connection hostConn = _connPool.slaveConnect(address, username, password); + Connection hostConn = _connPool.slaveConnect(address, username, pass); if (hostConn == null) { continue; } @@ -367,7 +373,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L throw new CloudRuntimeException("Unable to reach the pool master of the existing cluster"); } - if( !_connPool.joinPool(conn, hostIp, masterIp, username, password) ){ + if( !_connPool.joinPool(conn, hostIp, masterIp, username, pass) ){ s_logger.warn("Unable to join the pool"); throw new DiscoveryException("Unable to join the pool"); } diff --git a/server/src/com/cloud/migration/Db21to22MigrationUtil.java b/server/src/com/cloud/migration/Db21to22MigrationUtil.java index 8833ea25457..8a964ca2536 100644 --- a/server/src/com/cloud/migration/Db21to22MigrationUtil.java +++ b/server/src/com/cloud/migration/Db21to22MigrationUtil.java @@ -21,7 +21,9 @@ package com.cloud.migration; import java.io.File; import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.util.LinkedList; import java.util.List; +import java.util.Queue; import org.apache.log4j.xml.DOMConfigurator; @@ -94,7 +96,9 @@ public class Db21to22MigrationUtil { || password.isEmpty()) { continue; } - Connection conn = _connPool.slaveConnect(ip, username, password); + Queue pass=new LinkedList(); + pass.add(password); + Connection conn = _connPool.slaveConnect(ip, username, pass); if (conn == null) continue; Pool.Record pr = null; diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 73aef3b89fb..fd1874bbf42 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -4697,13 +4697,8 @@ public class ManagementServerImpl implements ManagementServer { } DetailVO nv = _detailsDao.findDetail(h.getId(), ApiConstants.USERNAME); if (nv.getValue().equals(cmd.getUsername())) { - DetailVO nvp = _detailsDao.findDetail(h.getId(), ApiConstants.NEW_PASSWORD); - if (nvp==null){ - nvp = new DetailVO(h.getId(), ApiConstants.NEW_PASSWORD, cmd.getPassword()); - } - else { - nvp.setValue(cmd.getPassword()); - } + DetailVO nvp = new DetailVO(h.getId(), ApiConstants.PASSWORD, cmd.getPassword()); + nvp.setValue(cmd.getPassword()); _detailsDao.persist(nvp); } else { throw new InvalidParameterValueException("The username is not under use by management server."); @@ -4720,13 +4715,8 @@ public class ManagementServerImpl implements ManagementServer { // update password for this host DetailVO nv = _detailsDao.findDetail(h.getId(), ApiConstants.USERNAME); if (nv.getValue().equals(cmd.getUsername())) { - DetailVO nvp = _detailsDao.findDetail(h.getId(), ApiConstants.NEW_PASSWORD); - if (nvp==null){ - nvp = new DetailVO(h.getId(), ApiConstants.NEW_PASSWORD, cmd.getPassword()); - } - else { - nvp.setValue(cmd.getPassword()); - } + DetailVO nvp = _detailsDao.findDetail(h.getId(), ApiConstants.PASSWORD); + nvp.setValue(cmd.getPassword()); _detailsDao.persist(nvp); } else { // if one host in the cluster has diff username then rollback to maintain consistency