You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ch...@apache.org on 2013/04/10 00:16:34 UTC
[12/19] git commit: updated refs/heads/master to bf56403
QuickCloud: copy authorization code from ConsoleProxyManagerImpl
QuickCloud: refactor to avoid copy paste of authentication and startup code
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/3d78019e
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/3d78019e
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/3d78019e
Branch: refs/heads/master
Commit: 3d78019e571677f1b2ac87acebe6192f2a4fa96c
Parents: 790d2ce
Author: Chiradeep Vittal <ch...@apache.org>
Authored: Tue Mar 26 10:05:06 2013 -0700
Committer: Chiradeep Vittal <ch...@apache.org>
Committed: Tue Apr 9 14:45:26 2013 -0700
----------------------------------------------------------------------
.../AgentBasedConsoleProxyManager.java | 184 +-------
.../src/com/cloud/consoleproxy/AgentHookBase.java | 266 +++++++++++
.../consoleproxy/ConsoleProxyManagerImpl.java | 362 ++++++---------
.../consoleproxy/StaticConsoleProxyManager.java | 84 +++-
4 files changed, 489 insertions(+), 407 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3d78019e/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java b/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java
index 6f8575d..ff6e64e 100755
--- a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java
+++ b/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java
@@ -23,48 +23,28 @@ import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
import com.cloud.agent.AgentManager;
-import com.cloud.agent.api.AgentControlAnswer;
-import com.cloud.agent.api.ConsoleAccessAuthenticationAnswer;
-import com.cloud.agent.api.ConsoleAccessAuthenticationCommand;
-import com.cloud.agent.api.ConsoleProxyLoadReportCommand;
import com.cloud.agent.api.GetVncPortAnswer;
import com.cloud.agent.api.GetVncPortCommand;
-import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupProxyCommand;
-import com.cloud.agent.api.StopAnswer;
-import com.cloud.agent.api.to.NicTO;
-import com.cloud.agent.api.to.VirtualMachineTO;
-import com.cloud.agent.manager.Commands;
import com.cloud.configuration.dao.ConfigurationDao;
-import com.cloud.deploy.DeployDestination;
-import com.cloud.exception.ConcurrentOperationException;
-import com.cloud.exception.InsufficientCapacityException;
-import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.HostVO;
-import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
import com.cloud.info.ConsoleProxyInfo;
-import com.cloud.network.Network;
+import com.cloud.keystore.KeystoreManager;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.component.ManagerBase;
import com.cloud.vm.ConsoleProxyVO;
-import com.cloud.vm.ReservationContext;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
-import com.cloud.vm.VirtualMachine;
-import com.cloud.vm.VirtualMachineGuru;
import com.cloud.vm.VirtualMachineManager;
-import com.cloud.vm.VirtualMachineName;
-import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.ConsoleProxyDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
@Local(value = { ConsoleProxyManager.class })
-public class AgentBasedConsoleProxyManager extends ManagerBase implements ConsoleProxyManager, VirtualMachineGuru<ConsoleProxyVO>, AgentHook {
+public class AgentBasedConsoleProxyManager extends ManagerBase implements ConsoleProxyManager {
private static final Logger s_logger = Logger.getLogger(AgentBasedConsoleProxyManager.class);
@Inject
@@ -85,9 +65,25 @@ public class AgentBasedConsoleProxyManager extends ManagerBase implements Consol
VirtualMachineManager _itMgr;
@Inject
protected ConsoleProxyDao _cpDao;
+ @Inject
+ protected KeystoreManager _ksMgr;
@Inject ConfigurationDao _configDao;
+ public class AgentBasedAgentHook extends AgentHookBase {
+
+ public AgentBasedAgentHook(VMInstanceDao instanceDao, HostDao hostDao, ConfigurationDao cfgDao,
+ KeystoreManager ksMgr, AgentManager agentMgr) {
+ super(instanceDao, hostDao, cfgDao, ksMgr, agentMgr);
+ }
+
+ @Override
+ protected HostVO findConsoleProxyHost(StartupProxyCommand cmd) {
+ return _hostDao.findByGuid(cmd.getGuid());
+ }
+
+ }
+
public int getVncPort(VMInstanceVO vm) {
if (vm.getHostId() == null) {
return -1;
@@ -123,11 +119,10 @@ public class AgentBasedConsoleProxyManager extends ManagerBase implements Consol
_consoleProxyUrlDomain = configs.get("consoleproxy.url.domain");
- _listener = new ConsoleProxyListener(this);
+ _listener =
+ new ConsoleProxyListener(new AgentBasedAgentHook(_instanceDao, _hostDao, _configDao, _ksMgr, _agentMgr));
_agentMgr.registerForHostEvents(_listener, true, true, false);
- _itMgr.registerGuru(VirtualMachine.Type.ConsoleProxy, this);
-
if (s_logger.isInfoEnabled()) {
s_logger.info("AgentBasedConsoleProxyManager has been configured. SSL enabled: " + _sslEnabled);
}
@@ -177,64 +172,8 @@ public class AgentBasedConsoleProxyManager extends ManagerBase implements Consol
return null;
}
- @Override
- public void onLoadReport(ConsoleProxyLoadReportCommand cmd) {
- }
-
- @Override
- public AgentControlAnswer onConsoleAccessAuthentication(ConsoleAccessAuthenticationCommand cmd) {
- long vmId = 0;
-
- if (cmd.getVmId() != null && cmd.getVmId().isEmpty()) {
- if (s_logger.isTraceEnabled()) {
- s_logger.trace("Invalid vm id sent from proxy(happens when proxy session has terminated)");
- }
- return new ConsoleAccessAuthenticationAnswer(cmd, false);
- }
-
- try {
- vmId = Long.parseLong(cmd.getVmId());
- } catch (NumberFormatException e) {
- s_logger.error("Invalid vm id " + cmd.getVmId() + " sent from console access authentication", e);
- return new ConsoleAccessAuthenticationAnswer(cmd, false);
- }
-
- // TODO authentication channel between console proxy VM and management
- // server needs to be secured,
- // the data is now being sent through private network, but this is
- // apparently not enough
- VMInstanceVO vm = _instanceDao.findById(vmId);
- if (vm == null) {
- return new ConsoleAccessAuthenticationAnswer(cmd, false);
- }
-
- if (vm.getHostId() == null) {
- s_logger.warn("VM " + vmId + " lost host info, failed authentication request");
- return new ConsoleAccessAuthenticationAnswer(cmd, false);
- }
-
- HostVO host = _hostDao.findById(vm.getHostId());
- if (host == null) {
- s_logger.warn("VM " + vmId + "'s host does not exist, fail authentication request");
- return new ConsoleAccessAuthenticationAnswer(cmd, false);
- }
- String sid = cmd.getSid();
- if (sid == null || !sid.equals(vm.getVncPassword())) {
- s_logger.warn("sid " + sid + " in url does not match stored sid " + vm.getVncPassword());
- return new ConsoleAccessAuthenticationAnswer(cmd, false);
- }
- return new ConsoleAccessAuthenticationAnswer(cmd, true);
- }
-
- @Override
- public void onAgentConnect(HostVO host, StartupCommand cmd) {
- }
-
- @Override
- public void onAgentDisconnect(long agentId, Status state) {
- }
@Override
public ConsoleProxyVO startProxy(long proxyVmId) {
@@ -270,90 +209,7 @@ public class AgentBasedConsoleProxyManager extends ManagerBase implements Consol
}
@Override
- public void startAgentHttpHandlerInVM(StartupProxyCommand startupCmd) {
- }
-
- @Override
public String getName() {
return _name;
}
-
- @Override
- public Long convertToId(String vmName) {
- if (!VirtualMachineName.isValidConsoleProxyName(vmName, _instance)) {
- return null;
- }
- return VirtualMachineName.getConsoleProxyId(vmName);
- }
-
- @Override
- public ConsoleProxyVO findByName(String name) {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public ConsoleProxyVO findById(long id) {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public ConsoleProxyVO persist(ConsoleProxyVO vm) {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public boolean finalizeVirtualMachineProfile(VirtualMachineProfile<ConsoleProxyVO> profile, DeployDestination dest, ReservationContext context) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile<ConsoleProxyVO> profile, DeployDestination dest, ReservationContext context) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile<ConsoleProxyVO> profile) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean finalizeStart(VirtualMachineProfile<ConsoleProxyVO> profile, long hostId, Commands cmds, ReservationContext context) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public void finalizeStop(VirtualMachineProfile<ConsoleProxyVO> profile, StopAnswer answer) {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void finalizeExpunge(ConsoleProxyVO proxy) {
- }
-
- @Override
- public boolean plugNic(Network network, NicTO nic, VirtualMachineTO vm,
- ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException,
- InsufficientCapacityException {
- //not supported
- throw new UnsupportedOperationException("Plug nic is not supported for vm of type " + vm.getType());
- }
-
-
- @Override
- public boolean unplugNic(Network network, NicTO nic, VirtualMachineTO vm,
- ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException {
- //not supported
- throw new UnsupportedOperationException("Unplug nic is not supported for vm of type " + vm.getType());
- }
-
- @Override
- public void prepareStop(VirtualMachineProfile<ConsoleProxyVO> profile) {
- }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3d78019e/server/src/com/cloud/consoleproxy/AgentHookBase.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/consoleproxy/AgentHookBase.java b/server/src/com/cloud/consoleproxy/AgentHookBase.java
new file mode 100644
index 0000000..b969f6d
--- /dev/null
+++ b/server/src/com/cloud/consoleproxy/AgentHookBase.java
@@ -0,0 +1,266 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with 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.
+
+package com.cloud.consoleproxy;
+
+import java.util.Date;
+import java.util.Random;
+import java.util.UUID;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.AgentControlAnswer;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.ConsoleAccessAuthenticationAnswer;
+import com.cloud.agent.api.ConsoleAccessAuthenticationCommand;
+import com.cloud.agent.api.ConsoleProxyLoadReportCommand;
+import com.cloud.agent.api.GetVncPortAnswer;
+import com.cloud.agent.api.GetVncPortCommand;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.StartupProxyCommand;
+import com.cloud.agent.api.proxy.StartConsoleProxyAgentHttpHandlerCommand;
+import com.cloud.configuration.Config;
+import com.cloud.configuration.dao.ConfigurationDao;
+import com.cloud.exception.AgentUnavailableException;
+import com.cloud.exception.OperationTimedoutException;
+import com.cloud.host.HostVO;
+import com.cloud.host.Status;
+import com.cloud.host.dao.HostDao;
+import com.cloud.keystore.KeystoreManager;
+import com.cloud.servlet.ConsoleProxyServlet;
+import com.cloud.utils.Ternary;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.dao.VMInstanceDao;
+
+/**
+ * Utility class to manage interactions with agent-based console access
+ * Extracted from ConsoleProxyManagerImpl so that other console proxy managers
+ * can reuse
+ */
+public abstract class AgentHookBase implements AgentHook {
+ private static final Logger s_logger = Logger.getLogger(AgentHookBase.class);
+
+ VMInstanceDao _instanceDao;
+ HostDao _hostDao;
+ ConfigurationDao _configDao;
+ AgentManager _agentMgr;
+ KeystoreManager _ksMgr;
+ final Random _random = new Random(System.currentTimeMillis());
+ private String _hashKey;
+
+
+ public AgentHookBase(VMInstanceDao instanceDao, HostDao hostDao, ConfigurationDao cfgDao, KeystoreManager ksMgr,
+ AgentManager agentMgr) {
+ this._instanceDao = instanceDao;
+ this._hostDao = hostDao;
+ this._agentMgr = agentMgr;
+ this._configDao = cfgDao;
+ this._ksMgr = ksMgr;
+ }
+
+ public String getHashKey() {
+ // although we may have race condition here, database transaction
+ // serialization should give us the same key
+ if (_hashKey == null) {
+ _hashKey =
+ _configDao.getValueAndInitIfNotExist(Config.HashKey.key(), Config.HashKey.getCategory(), UUID
+ .randomUUID().toString());
+ }
+ return _hashKey;
+ }
+
+ public AgentControlAnswer onConsoleAccessAuthentication(ConsoleAccessAuthenticationCommand cmd) {
+ Long vmId = null;
+
+ String ticketInUrl = cmd.getTicket();
+ if (ticketInUrl == null) {
+ s_logger.error("Access ticket could not be found, you could be running an old version of console proxy. vmId: "
+ + cmd.getVmId());
+ return new ConsoleAccessAuthenticationAnswer(cmd, false);
+ }
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Console authentication. Ticket in url for " + cmd.getHost() + ":" + cmd.getPort() + "-"
+ + cmd.getVmId() + " is " + ticketInUrl);
+ }
+
+ if (!cmd.isReauthenticating()) {
+ String ticket =
+ ConsoleProxyServlet.genAccessTicket(cmd.getHost(), cmd.getPort(), cmd.getSid(), cmd.getVmId());
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Console authentication. Ticket in 1 minute boundary for " + cmd.getHost() + ":"
+ + cmd.getPort() + "-" + cmd.getVmId() + " is " + ticket);
+ }
+
+ if (!ticket.equals(ticketInUrl)) {
+ Date now = new Date();
+ // considering of minute round-up
+ String minuteEarlyTicket =
+ ConsoleProxyServlet.genAccessTicket(cmd.getHost(), cmd.getPort(), cmd.getSid(), cmd.getVmId(),
+ new Date(now.getTime() - 60 * 1000));
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Console authentication. Ticket in 2-minute boundary for " + cmd.getHost() + ":"
+ + cmd.getPort() + "-" + cmd.getVmId() + " is " + minuteEarlyTicket);
+ }
+
+ if (!minuteEarlyTicket.equals(ticketInUrl)) {
+ s_logger.error("Access ticket expired or has been modified. vmId: " + cmd.getVmId()
+ + "ticket in URL: " + ticketInUrl + ", tickets to check against: " + ticket + ","
+ + minuteEarlyTicket);
+ return new ConsoleAccessAuthenticationAnswer(cmd, false);
+ }
+ }
+ }
+
+ if (cmd.getVmId() != null && cmd.getVmId().isEmpty()) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Invalid vm id sent from proxy(happens when proxy session has terminated)");
+ }
+ return new ConsoleAccessAuthenticationAnswer(cmd, false);
+ }
+
+ VirtualMachine vm = _instanceDao.findByUuid(cmd.getVmId());
+ if (vm == null) {
+ vm = _instanceDao.findById(Long.parseLong(cmd.getVmId()));
+ }
+ if (vm == null) {
+ s_logger.error("Invalid vm id " + cmd.getVmId() + " sent from console access authentication");
+ return new ConsoleAccessAuthenticationAnswer(cmd, false);
+ }
+
+ if (vm.getHostId() == null) {
+ s_logger.warn("VM " + vmId + " lost host info, failed authentication request");
+ return new ConsoleAccessAuthenticationAnswer(cmd, false);
+ }
+
+ HostVO host = _hostDao.findById(vm.getHostId());
+ if (host == null) {
+ s_logger.warn("VM " + vmId + "'s host does not exist, fail authentication request");
+ return new ConsoleAccessAuthenticationAnswer(cmd, false);
+ }
+
+ String sid = cmd.getSid();
+ if (sid == null || !sid.equals(vm.getVncPassword())) {
+ s_logger.warn("sid " + sid + " in url does not match stored sid " + vm.getVncPassword());
+ return new ConsoleAccessAuthenticationAnswer(cmd, false);
+ }
+
+ if (cmd.isReauthenticating()) {
+ ConsoleAccessAuthenticationAnswer authenticationAnswer = new ConsoleAccessAuthenticationAnswer(cmd, true);
+ authenticationAnswer.setReauthenticating(true);
+
+ s_logger.info("Re-authentication request, ask host " + vm.getHostId() + " for new console info");
+ GetVncPortAnswer answer =
+ (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(),
+ new GetVncPortCommand(vm.getId(), vm.getInstanceName()));
+
+ if (answer != null && answer.getResult()) {
+ Ternary<String, String, String> parsedHostInfo = ConsoleProxyServlet.parseHostInfo(answer.getAddress());
+
+ if (parsedHostInfo.second() != null && parsedHostInfo.third() != null) {
+
+ s_logger.info("Re-authentication result. vm: " + vm.getId() + ", tunnel url: "
+ + parsedHostInfo.second() + ", tunnel session: " + parsedHostInfo.third());
+
+ authenticationAnswer.setTunnelUrl(parsedHostInfo.second());
+ authenticationAnswer.setTunnelSession(parsedHostInfo.third());
+ } else {
+ s_logger.info("Re-authentication result. vm: " + vm.getId() + ", host address: "
+ + parsedHostInfo.first() + ", port: " + answer.getPort());
+
+ authenticationAnswer.setHost(parsedHostInfo.first());
+ authenticationAnswer.setPort(answer.getPort());
+ }
+ } else {
+ s_logger.warn("Re-authentication request failed");
+
+ authenticationAnswer.setSuccess(false);
+ }
+
+ return authenticationAnswer;
+ }
+
+ return new ConsoleAccessAuthenticationAnswer(cmd, true);
+ }
+
+ public void startAgentHttpHandlerInVM(StartupProxyCommand startupCmd) {
+ StartConsoleProxyAgentHttpHandlerCommand cmd = null;
+ if (_configDao.isPremium()) {
+ String storePassword = String.valueOf(_random.nextLong());
+ byte[] ksBits =
+ _ksMgr.getKeystoreBits(ConsoleProxyManager.CERTIFICATE_NAME, ConsoleProxyManager.CERTIFICATE_NAME,
+ storePassword);
+
+ assert (ksBits != null);
+ if (ksBits == null) {
+ s_logger.error("Could not find and construct a valid SSL certificate");
+ }
+ cmd = new StartConsoleProxyAgentHttpHandlerCommand(ksBits, storePassword);
+ cmd.setEncryptorPassword(getHashKey());
+ } else {
+ cmd = new StartConsoleProxyAgentHttpHandlerCommand();
+ cmd.setEncryptorPassword(getHashKey());
+ }
+
+ try {
+
+ HostVO consoleProxyHost = findConsoleProxyHost(startupCmd);
+
+ assert (consoleProxyHost != null);
+
+ Answer answer = _agentMgr.send(consoleProxyHost.getId(), cmd);
+ if (answer == null || !answer.getResult()) {
+ s_logger.error("Console proxy agent reported that it failed to execute http handling startup command");
+ } else {
+ s_logger.info("Successfully sent out command to start HTTP handling in console proxy agent");
+ }
+ } catch (AgentUnavailableException e) {
+ s_logger.error("Unable to send http handling startup command to the console proxy resource for proxy:"
+ + startupCmd.getProxyVmId(), e);
+ } catch (OperationTimedoutException e) {
+ s_logger.error(
+ "Unable to send http handling startup command(time out) to the console proxy resource for proxy:"
+ + startupCmd.getProxyVmId(), e);
+ } catch (OutOfMemoryError e) {
+ s_logger.error("Unrecoverable OutOfMemory Error, exit and let it be re-launched");
+ System.exit(1);
+ } catch (Exception e) {
+ s_logger.error(
+ "Unexpected exception when sending http handling startup command(time out) to the console proxy resource for proxy:"
+ + startupCmd.getProxyVmId(), e);
+ }
+ }
+
+ protected abstract HostVO findConsoleProxyHost(StartupProxyCommand cmd);
+
+ @Override
+ public void onLoadReport(ConsoleProxyLoadReportCommand cmd) {
+ // no-op since we do not auto-scale
+ }
+
+ @Override
+ public void onAgentConnect(HostVO host, StartupCommand cmd) {
+ // no-op
+ }
+
+ @Override
+ public void onAgentDisconnect(long agentId, Status state) {
+ // no-op since we do not autoscale
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3d78019e/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
index fc4fc6e..9740d28 100755
--- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
+++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java
@@ -23,7 +23,6 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Random;
import java.util.UUID;
import javax.ejb.Local;
@@ -35,13 +34,8 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
-import com.cloud.agent.api.AgentControlAnswer;
import com.cloud.agent.api.Answer;
-import com.cloud.agent.api.ConsoleAccessAuthenticationAnswer;
-import com.cloud.agent.api.ConsoleAccessAuthenticationCommand;
import com.cloud.agent.api.ConsoleProxyLoadReportCommand;
-import com.cloud.agent.api.GetVncPortAnswer;
-import com.cloud.agent.api.GetVncPortCommand;
import com.cloud.agent.api.RebootCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupProxyCommand;
@@ -49,7 +43,6 @@ import com.cloud.agent.api.StopAnswer;
import com.cloud.agent.api.check.CheckSshAnswer;
import com.cloud.agent.api.check.CheckSshCommand;
import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer;
-import com.cloud.agent.api.proxy.StartConsoleProxyAgentHttpHandlerCommand;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.agent.manager.Commands;
@@ -66,10 +59,8 @@ import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeployDestination;
-import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
-import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.host.Host;
@@ -106,7 +97,6 @@ import com.cloud.resource.ServerResource;
import com.cloud.resource.UnableDeleteHostException;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
-import com.cloud.servlet.ConsoleProxyServlet;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePoolStatus;
import com.cloud.storage.VMTemplateHostVO;
@@ -123,7 +113,6 @@ import com.cloud.user.UserContext;
import com.cloud.utils.DateUtil;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
-import com.cloud.utils.Ternary;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GlobalLock;
@@ -167,7 +156,7 @@ import com.google.gson.GsonBuilder;
//
@Local(value = { ConsoleProxyManager.class, ConsoleProxyService.class })
public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxyManager,
- AgentHook, VirtualMachineGuru<ConsoleProxyVO>, SystemVmLoadScanHandler<Long>, ResourceStateAdapter {
+ VirtualMachineGuru<ConsoleProxyVO>, SystemVmLoadScanHandler<Long>, ResourceStateAdapter {
private static final Logger s_logger = Logger.getLogger(ConsoleProxyManagerImpl.class);
private static final int DEFAULT_CAPACITY_SCAN_INTERVAL = 30000; // 30 seconds
@@ -455,7 +444,131 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
private KeystoreDao _ksDao;
@Inject
private KeystoreManager _ksMgr;
- private final Random _random = new Random(System.currentTimeMillis());
+
+ public class VmBasedAgentHook extends AgentHookBase {
+
+ public VmBasedAgentHook(VMInstanceDao instanceDao, HostDao hostDao, ConfigurationDao cfgDao,
+ KeystoreManager ksMgr, AgentManager agentMgr) {
+ super(instanceDao, hostDao, cfgDao, ksMgr, agentMgr);
+ }
+
+ @Override
+ public void onLoadReport(ConsoleProxyLoadReportCommand cmd) {
+ if (cmd.getLoadInfo() == null) {
+ return;
+ }
+
+ ConsoleProxyStatus status = null;
+ try {
+ GsonBuilder gb = new GsonBuilder();
+ gb.setVersion(1.3);
+ Gson gson = gb.create();
+ status = gson.fromJson(cmd.getLoadInfo(), ConsoleProxyStatus.class);
+ } catch (Throwable e) {
+ s_logger.warn("Unable to parse load info from proxy, proxy vm id : " + cmd.getProxyVmId() + ", info : " + cmd.getLoadInfo());
+ }
+
+ if (status != null) {
+ int count = 0;
+ if (status.getConnections() != null) {
+ count = status.getConnections().length;
+ }
+
+ byte[] details = null;
+ if (cmd.getLoadInfo() != null) {
+ details = cmd.getLoadInfo().getBytes(Charset.forName("US-ASCII"));
+ }
+ _consoleProxyDao.update(cmd.getProxyVmId(), count, DateUtil.currentGMTTime(), details);
+ } else {
+ if (s_logger.isTraceEnabled()) {
+ s_logger.trace("Unable to get console proxy load info, id : " + cmd.getProxyVmId());
+ }
+
+ _consoleProxyDao.update(cmd.getProxyVmId(), 0, DateUtil.currentGMTTime(), null);
+ }
+ }
+
+ @Override
+ public void onAgentConnect(HostVO host, StartupCommand cmd) {
+ // no-op
+ }
+
+ @Override
+ public void onAgentDisconnect(long agentId, com.cloud.host.Status state) {
+
+ if (state == com.cloud.host.Status.Alert || state == com.cloud.host.Status.Disconnected) {
+ // be it either in alert or in disconnected state, the agent
+ // process
+ // may be gone in the VM,
+ // we will be reacting to stop the corresponding VM and let the
+ // scan
+ // process to
+ HostVO host = _hostDao.findById(agentId);
+ if (host.getType() == Type.ConsoleProxy) {
+ String name = host.getName();
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Console proxy agent disconnected, proxy: " + name);
+ }
+ if (name != null && name.startsWith("v-")) {
+ String[] tokens = name.split("-");
+ long proxyVmId = 0;
+ try {
+ proxyVmId = Long.parseLong(tokens[1]);
+ } catch (NumberFormatException e) {
+ s_logger.error("Unexpected exception " + e.getMessage(), e);
+ return;
+ }
+
+ final ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId);
+ if (proxy != null) {
+
+ // Disable this feature for now, as it conflicts
+ // with
+ // the case of allowing user to reboot console proxy
+ // when rebooting happens, we will receive
+ // disconnect
+ // here and we can't enter into stopping process,
+ // as when the rebooted one comes up, it will kick
+ // off a
+ // newly started one and trigger the process
+ // continue on forever
+
+ /*
+ * _capacityScanScheduler.execute(new Runnable() {
+ * public void run() { if(s_logger.isInfoEnabled())
+ * s_logger.info("Stop console proxy " +
+ * proxy.getName() +
+ * " VM because of that the agent running inside it has disconnected"
+ * ); stopProxy(proxy.getId()); } });
+ */
+ } else {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Console proxy agent disconnected but corresponding console proxy VM no longer exists in DB, proxy: "
+ + name);
+ }
+ }
+ } else {
+ assert (false) : "Invalid console proxy name: " + name;
+ }
+ }
+ }
+
+ }
+
+ @Override
+ protected HostVO findConsoleProxyHost(StartupProxyCommand startupCmd) {
+ long proxyVmId = startupCmd.getProxyVmId();
+ ConsoleProxyVO consoleProxy = _consoleProxyDao.findById(proxyVmId);
+ if (consoleProxy == null) {
+ s_logger.info("Proxy " + proxyVmId + " is no longer in DB, skip sending startup command");
+ return null;
+ }
+
+ assert (consoleProxy != null);
+ return findConsoleProxyHostByName(consoleProxy.getHostName());
+ }
+
+ }
@Override
public ConsoleProxyInfo assignProxy(final long dataCenterId, final long vmId) {
@@ -847,181 +960,9 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
}
}
- @Override
- public void onLoadReport(ConsoleProxyLoadReportCommand cmd) {
- if (cmd.getLoadInfo() == null) {
- return;
- }
-
- ConsoleProxyStatus status = null;
- try {
- GsonBuilder gb = new GsonBuilder();
- gb.setVersion(1.3);
- Gson gson = gb.create();
- status = gson.fromJson(cmd.getLoadInfo(), ConsoleProxyStatus.class);
- } catch (Throwable e) {
- s_logger.warn("Unable to parse load info from proxy, proxy vm id : " + cmd.getProxyVmId() + ", info : " + cmd.getLoadInfo());
- }
-
- if (status != null) {
- int count = 0;
- if (status.getConnections() != null) {
- count = status.getConnections().length;
- }
-
- byte[] details = null;
- if (cmd.getLoadInfo() != null) {
- details = cmd.getLoadInfo().getBytes(Charset.forName("US-ASCII"));
- }
- _consoleProxyDao.update(cmd.getProxyVmId(), count, DateUtil.currentGMTTime(), details);
- } else {
- if (s_logger.isTraceEnabled()) {
- s_logger.trace("Unable to get console proxy load info, id : " + cmd.getProxyVmId());
- }
- _consoleProxyDao.update(cmd.getProxyVmId(), 0, DateUtil.currentGMTTime(), null);
- }
- }
- @Override
- public AgentControlAnswer onConsoleAccessAuthentication(ConsoleAccessAuthenticationCommand cmd) {
- Long vmId = null;
-
- String ticketInUrl = cmd.getTicket();
- if (ticketInUrl == null) {
- s_logger.error("Access ticket could not be found, you could be running an old version of console proxy. vmId: " + cmd.getVmId());
- return new ConsoleAccessAuthenticationAnswer(cmd, false);
- }
-
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Console authentication. Ticket in url for " + cmd.getHost() + ":" + cmd.getPort() + "-" + cmd.getVmId() + " is " + ticketInUrl);
- }
-
- if(!cmd.isReauthenticating()) {
- String ticket = ConsoleProxyServlet.genAccessTicket(cmd.getHost(), cmd.getPort(), cmd.getSid(), cmd.getVmId());
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Console authentication. Ticket in 1 minute boundary for " + cmd.getHost() + ":" + cmd.getPort() + "-" + cmd.getVmId() + " is " + ticket);
- }
-
- if (!ticket.equals(ticketInUrl)) {
- Date now = new Date();
- // considering of minute round-up
- String minuteEarlyTicket = ConsoleProxyServlet.genAccessTicket(cmd.getHost(), cmd.getPort(), cmd.getSid(), cmd.getVmId(), new Date(now.getTime() - 60 * 1000));
-
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Console authentication. Ticket in 2-minute boundary for " + cmd.getHost() + ":" + cmd.getPort() + "-" + cmd.getVmId() + " is " + minuteEarlyTicket);
- }
-
- if (!minuteEarlyTicket.equals(ticketInUrl)) {
- s_logger.error("Access ticket expired or has been modified. vmId: " + cmd.getVmId() + "ticket in URL: " + ticketInUrl + ", tickets to check against: " + ticket + ","
- + minuteEarlyTicket);
- return new ConsoleAccessAuthenticationAnswer(cmd, false);
- }
- }
- }
-
- if (cmd.getVmId() != null && cmd.getVmId().isEmpty()) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Invalid vm id sent from proxy(happens when proxy session has terminated)");
- }
- return new ConsoleAccessAuthenticationAnswer(cmd, false);
- }
-
- VirtualMachine vm = _instanceDao.findByUuid(cmd.getVmId());
- if (vm == null) {
- vm = _instanceDao.findById(Long.parseLong(cmd.getVmId()));
- }
- if (vm == null) {
- s_logger.error("Invalid vm id " + cmd.getVmId() + " sent from console access authentication");
- return new ConsoleAccessAuthenticationAnswer(cmd, false);
- }
-
- if (vm.getHostId() == null) {
- s_logger.warn("VM " + vmId + " lost host info, failed authentication request");
- return new ConsoleAccessAuthenticationAnswer(cmd, false);
- }
-
- HostVO host = _hostDao.findById(vm.getHostId());
- if (host == null) {
- s_logger.warn("VM " + vmId + "'s host does not exist, fail authentication request");
- return new ConsoleAccessAuthenticationAnswer(cmd, false);
- }
-
- String sid = cmd.getSid();
- if (sid == null || !sid.equals(vm.getVncPassword())) {
- s_logger.warn("sid " + sid + " in url does not match stored sid " + vm.getVncPassword());
- return new ConsoleAccessAuthenticationAnswer(cmd, false);
- }
-
- if(cmd.isReauthenticating()) {
- ConsoleAccessAuthenticationAnswer authenticationAnswer = new ConsoleAccessAuthenticationAnswer(cmd, true);
- authenticationAnswer.setReauthenticating(true);
-
- s_logger.info("Re-authentication request, ask host " + vm.getHostId() + " for new console info");
- GetVncPortAnswer answer = (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), new
- GetVncPortCommand(vm.getId(), vm.getInstanceName()));
-
- if (answer != null && answer.getResult()) {
- Ternary<String, String, String> parsedHostInfo = ConsoleProxyServlet.parseHostInfo(answer.getAddress());
-
- if(parsedHostInfo.second() != null && parsedHostInfo.third() != null) {
-
- s_logger.info("Re-authentication result. vm: " + vm.getId() + ", tunnel url: " + parsedHostInfo.second()
- + ", tunnel session: " + parsedHostInfo.third());
-
- authenticationAnswer.setTunnelUrl(parsedHostInfo.second());
- authenticationAnswer.setTunnelSession(parsedHostInfo.third());
- } else {
- s_logger.info("Re-authentication result. vm: " + vm.getId() + ", host address: " + parsedHostInfo.first()
- + ", port: " + answer.getPort());
-
- authenticationAnswer.setHost(parsedHostInfo.first());
- authenticationAnswer.setPort(answer.getPort());
- }
- } else {
- s_logger.warn("Re-authentication request failed");
-
- authenticationAnswer.setSuccess(false);
- }
-
- return authenticationAnswer;
- }
-
- return new ConsoleAccessAuthenticationAnswer(cmd, true);
- }
-
- @Override
- public void onAgentConnect(HostVO host, StartupCommand cmd) {
- // if (host.getType() == Type.ConsoleProxy) {
- // // TODO we can use this event to mark the proxy is up and
- // // functioning instead of
- // // pinging the console proxy VM command port
- // //
- // // for now, just log a message
- // if (s_logger.isInfoEnabled()) {
- // s_logger.info("Console proxy agent is connected. proxy: " + host.getName());
- // }
- //
- // /* update public/private ip address */
- // if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) {
- // try {
- // ConsoleProxyVO console = findConsoleProxyByHost(host);
- // if (console == null) {
- // s_logger.debug("Can't find console proxy ");
- // return;
- // }
- // console.setPrivateIpAddress(cmd.getPrivateIpAddress());
- // console.setPublicIpAddress(cmd.getPublicIpAddress());
- // console.setPublicNetmask(cmd.getPublicNetmask());
- // _consoleProxyDao.persist(console);
- // } catch (NumberFormatException e) {
- // }
- // }
- // }
- }
-
- @Override
- public void onAgentDisconnect(long agentId, com.cloud.host.Status state) {
+ public void handleAgentDisconnect(long agentId, com.cloud.host.Status state) {
if (state == com.cloud.host.Status.Alert || state == com.cloud.host.Status.Disconnected) {
// be it either in alert or in disconnected state, the agent process
// may be gone in the VM,
@@ -1496,7 +1437,9 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
value = agentMgrConfigs.get("port");
_mgmt_port = NumbersUtil.parseInt(value, 8250);
- _listener = new ConsoleProxyListener(this);
+ _listener =
+ new ConsoleProxyListener(new VmBasedAgentHook(_instanceDao, _hostDao, _configDao, _ksMgr,
+ _agentMgr));
_agentMgr.registerForHostEvents(_listener, true, true, false);
_itMgr.registerGuru(VirtualMachine.Type.ConsoleProxy, this);
@@ -1719,52 +1662,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
_consoleProxyDao.update(proxy.getId(), proxy);
}
- @Override
- public void startAgentHttpHandlerInVM(StartupProxyCommand startupCmd) {
- StartConsoleProxyAgentHttpHandlerCommand cmd = null;
- if (_configDao.isPremium()) {
- String storePassword = String.valueOf(_random.nextLong());
- byte[] ksBits = _ksMgr.getKeystoreBits(ConsoleProxyManager.CERTIFICATE_NAME, ConsoleProxyManager.CERTIFICATE_NAME, storePassword);
-
- assert (ksBits != null);
- if (ksBits == null) {
- s_logger.error("Could not find and construct a valid SSL certificate");
- }
- cmd = new StartConsoleProxyAgentHttpHandlerCommand(ksBits, storePassword);
- cmd.setEncryptorPassword(getHashKey());
- } else {
- cmd = new StartConsoleProxyAgentHttpHandlerCommand();
- cmd.setEncryptorPassword(getHashKey());
- }
-
- try {
- long proxyVmId = startupCmd.getProxyVmId();
- ConsoleProxyVO consoleProxy = _consoleProxyDao.findById(proxyVmId);
- if (consoleProxy == null) {
- s_logger.info("Proxy " + proxyVmId + " is no longer in DB, skip sending startup command");
- return;
- }
-
- assert (consoleProxy != null);
- HostVO consoleProxyHost = findConsoleProxyHostByName(consoleProxy.getHostName());
- Answer answer = _agentMgr.send(consoleProxyHost.getId(), cmd);
- if (answer == null || !answer.getResult()) {
- s_logger.error("Console proxy agent reported that it failed to execute http handling startup command");
- } else {
- s_logger.info("Successfully sent out command to start HTTP handling in console proxy agent");
- }
- } catch (AgentUnavailableException e) {
- s_logger.error("Unable to send http handling startup command to the console proxy resource for proxy:" + startupCmd.getProxyVmId(), e);
- } catch (OperationTimedoutException e) {
- s_logger.error("Unable to send http handling startup command(time out) to the console proxy resource for proxy:" + startupCmd.getProxyVmId(), e);
- } catch (OutOfMemoryError e) {
- s_logger.error("Unrecoverable OutOfMemory Error, exit and let it be re-launched");
- System.exit(1);
- } catch (Exception e) {
- s_logger.error("Unexpected exception when sending http handling startup command(time out) to the console proxy resource for proxy:" + startupCmd.getProxyVmId(), e);
- }
- }
@Override
public ConsoleProxyVO persist(ConsoleProxyVO proxy) {
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3d78019e/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java b/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java
index 3ba98a9..7b59a6b 100755
--- a/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java
+++ b/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java
@@ -16,29 +16,59 @@
// under the License.
package com.cloud.consoleproxy;
+
import java.util.List;
import java.util.Map;
+import java.util.Random;
import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
-import org.springframework.stereotype.Component;
+import org.apache.log4j.Logger;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.StartupProxyCommand;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.host.Host.Type;
import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
import com.cloud.info.ConsoleProxyInfo;
+import com.cloud.keystore.KeystoreDao;
+import com.cloud.keystore.KeystoreManager;
import com.cloud.resource.ResourceManager;
+import com.cloud.resource.ResourceStateAdapter;
+import com.cloud.resource.ServerResource;
+import com.cloud.resource.UnableDeleteHostException;
+import com.cloud.utils.NumbersUtil;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.dao.ConsoleProxyDao;
+import com.cloud.vm.dao.VMInstanceDao;
@Local(value={ConsoleProxyManager.class})
-public class StaticConsoleProxyManager extends AgentBasedConsoleProxyManager implements ConsoleProxyManager {
- String _ip = null;
- @Inject ConsoleProxyDao _proxyDao;
- @Inject ResourceManager _resourceMgr;
- @Inject ConfigurationDao _configDao;
+public class StaticConsoleProxyManager extends AgentBasedConsoleProxyManager implements ConsoleProxyManager,
+ ResourceStateAdapter {
+ private static final Logger s_logger = Logger.getLogger(StaticConsoleProxyManager.class);
+
+ @Inject
+ ConsoleProxyDao _proxyDao;
+ @Inject
+ ResourceManager _resourceMgr;
+ @Inject
+ ConfigurationDao _configDao;
+ @Inject
+ private VMInstanceDao _instanceDao;
+ @Inject
+ KeystoreDao _ksDao;
+ @Inject
+ private KeystoreManager _ksMgr;
+ @Inject
+ private HostDao _hostDao;
+ private final Random _random = new Random(System.currentTimeMillis());
+ private String _hashKey;
+ private String _ip = null;
+
+
@Override
protected HostVO findHost(VMInstanceVO vm) {
@@ -50,20 +80,52 @@ public class StaticConsoleProxyManager extends AgentBasedConsoleProxyManager imp
@Override
public ConsoleProxyInfo assignProxy(long dataCenterId, long userVmId) {
- return new ConsoleProxyInfo(false, _ip, _consoleProxyPort, _consoleProxyUrlPort, _consoleProxyUrlDomain);
+ return new ConsoleProxyInfo(_sslEnabled, _ip, _consoleProxyPort, _consoleProxyUrlPort, _consoleProxyUrlDomain);
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
super.configure(name, params);
-
- Map<String, String> dbParams = _configDao.getConfiguration("ManagementServer", params);
-
- _ip = dbParams.get("public.ip");
+ _ip = _configDao.getValue("consoleproxy.static.publicIp");
if (_ip == null) {
_ip = "127.0.0.1";
}
+
+ String value = (String) params.get("consoleproxy.sslEnabled");
+ if (value != null && value.equalsIgnoreCase("true")) {
+ _sslEnabled = true;
+ }
+ int defaultPort = 8088;
+ if (_sslEnabled)
+ defaultPort = 8443;
+ _consoleProxyUrlPort = NumbersUtil.parseInt(_configDao.getValue("consoleproxy.static.port"), defaultPort);
+
+ _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
+
return true;
}
+
+ @Override
+ public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) {
+ if (!(cmd[0] instanceof StartupProxyCommand)) {
+ return null;
+ }
+
+ host.setType(com.cloud.host.Host.Type.ConsoleProxy);
+ return host;
+ }
+
+ @Override
+ public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource,
+ Map<String, String> details, List<String> hostTags) {
+ return null;
+ }
+
+ @Override
+ public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage)
+ throws UnableDeleteHostException {
+ return null;
+ }
+
}