From dc1d43815f52cdce26c0a9aac7a6ad3422b85042 Mon Sep 17 00:00:00 2001 From: "Manuel Amador (Rudd-O)" Date: Thu, 19 Aug 2010 10:30:07 -0700 Subject: [PATCH 01/17] Requires of cloud-qemu-system-x86 correct --- cloud.spec | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cloud.spec b/cloud.spec index b164ab03b7e..fd215a8ddfa 100644 --- a/cloud.spec +++ b/cloud.spec @@ -232,6 +232,9 @@ Requires: %{name}-daemonize Requires: /sbin/service Requires: /sbin/chkconfig Requires: kvm +%if 0%{?fedora} >= 13 +Requires: cloud-qemu-system-x86 +%endif Requires: libcgroup Requires: /usr/bin/uuidgen Requires: augeas >= 0.7.1 From b96544e475b7dc6cd0e7c9faa526e7d8c79755fa Mon Sep 17 00:00:00 2001 From: "Manuel Amador (Rudd-O)" Date: Thu, 19 Aug 2010 10:35:17 -0700 Subject: [PATCH 02/17] read_properties imported from cloud_utils --- client/bindir/cloud-update-xenserver-licenses.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/bindir/cloud-update-xenserver-licenses.in b/client/bindir/cloud-update-xenserver-licenses.in index 6249f7805fe..94b8e3e8ceb 100755 --- a/client/bindir/cloud-update-xenserver-licenses.in +++ b/client/bindir/cloud-update-xenserver-licenses.in @@ -125,7 +125,7 @@ except IndexError: e("The first argument must be the license file to use") if options.all: if len(args) != 0: e("IP addresses cannot be specified if -a is specified") - config = cloud_utils.read_properties(cfg) + config = read_properties(cfg) creds = getknownhosts(config["db.cloud.host"],config["db.cloud.username"],config["db.cloud.password"]) hosts = creds.keys() else: From e94d21be0f1c3243549a13a84acbed47711dc4e7 Mon Sep 17 00:00:00 2001 From: "Manuel Amador (Rudd-O)" Date: Thu, 19 Aug 2010 10:36:02 -0700 Subject: [PATCH 03/17] Remove cloud_utils.pyc --- python/lib/cloud_utils.pyc | Bin 46932 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 python/lib/cloud_utils.pyc diff --git a/python/lib/cloud_utils.pyc b/python/lib/cloud_utils.pyc deleted file mode 100644 index 061c199488c2bc667d77e99f235db2afd52474bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46932 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 X=jnlwf#bu(m=AaLb?yD?-b4Q{ONc!m From 04d0feb47577a66d1cc118bff3f3f30aab02fcbc Mon Sep 17 00:00:00 2001 From: "Manuel Amador (Rudd-O)" Date: Thu, 19 Aug 2010 10:55:43 -0700 Subject: [PATCH 04/17] Gitignore ignores pyc ocmpiled files and build.number --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 81eba9119a3..d7723b24bc6 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ dist/ *.bak cloud-*.tar.bz2 *.log +*.pyc +build.number From 417a3c8c187a88594e3d298cd2d8774363510cf3 Mon Sep 17 00:00:00 2001 From: Alex Huang Date: Thu, 19 Aug 2010 11:27:30 -0700 Subject: [PATCH 05/17] bug 5764: More changes --- build/build.number | 4 +- .../consoleproxy/ConsoleProxyManager.java | 54 - .../AgentBasedConsoleProxyManager.java | 554 +-- ...entBasedStandaloneConsoleProxyManager.java | 18 +- .../src/com/cloud/consoleproxy/AgentHook.java | 19 + .../ConsoleProxyAlertEventArgs.java | 0 .../consoleproxy/ConsoleProxyListener.java | 45 +- .../consoleproxy/ConsoleProxyManager.java | 46 + .../consoleproxy/ConsoleProxyManagerImpl.java | 4296 ++++++++--------- .../StaticConsoleProxyManager.java | 30 +- .../cloud/server/ManagementServerImpl.java | 59 +- server/src/com/cloud/vm/VmManager.java | 12 +- 12 files changed, 2489 insertions(+), 2648 deletions(-) delete mode 100644 core/src/com/cloud/consoleproxy/ConsoleProxyManager.java create mode 100644 server/src/com/cloud/consoleproxy/AgentHook.java rename {core => server}/src/com/cloud/consoleproxy/ConsoleProxyAlertEventArgs.java (100%) rename {core => server}/src/com/cloud/consoleproxy/ConsoleProxyListener.java (76%) create mode 100644 server/src/com/cloud/consoleproxy/ConsoleProxyManager.java diff --git a/build/build.number b/build/build.number index 0216cfc6927..fd157380ba6 100644 --- a/build/build.number +++ b/build/build.number @@ -1,3 +1,3 @@ #Build Number for ANT. Do not edit! -#Thu Aug 19 09:21:10 PDT 2010 -build.number=65 +#Thu Aug 19 11:24:57 PDT 2010 +build.number=71 diff --git a/core/src/com/cloud/consoleproxy/ConsoleProxyManager.java b/core/src/com/cloud/consoleproxy/ConsoleProxyManager.java deleted file mode 100644 index ca36c338f82..00000000000 --- a/core/src/com/cloud/consoleproxy/ConsoleProxyManager.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * 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.consoleproxy; - -import com.cloud.agent.api.AgentControlAnswer; -import com.cloud.agent.api.ConsoleAccessAuthenticationCommand; -import com.cloud.agent.api.ConsoleProxyLoadReportCommand; -import com.cloud.agent.api.StartupCommand; -import com.cloud.host.HostVO; -import com.cloud.host.Status; -import com.cloud.utils.component.Manager; -import com.cloud.vm.ConsoleProxyVO; - -public interface ConsoleProxyManager extends Manager { - public static final int DEFAULT_PROXY_CAPACITY = 50; - public static final int DEFAULT_STANDBY_CAPACITY = 10; - public static final int DEFAULT_PROXY_VM_RAMSIZE = 1024; // 1G - - public static final int DEFAULT_PROXY_CMD_PORT = 8001; - public static final int DEFAULT_PROXY_VNC_PORT = 0; - public static final int DEFAULT_PROXY_URL_PORT = 80; - public static final int DEFAULT_PROXY_SESSION_TIMEOUT = 300000; // 5 minutes - - public static final String ALERT_SUBJECT = "proxy-alert"; - - public ConsoleProxyVO assignProxy(long dataCenterId, long userVmId); - - public ConsoleProxyVO startProxy(long proxyVmId, long startEventId); - public boolean stopProxy(long proxyVmId, long startEventId); - public boolean rebootProxy(long proxyVmId, long startEventId); - public boolean destroyProxy(long proxyVmId, long startEventId); - - public void onLoadReport(ConsoleProxyLoadReportCommand cmd); - public AgentControlAnswer onConsoleAccessAuthentication(ConsoleAccessAuthenticationCommand cmd); - - public void onAgentConnect(HostVO host, StartupCommand cmd); - public void onAgentDisconnect(long agentId, Status state); -} diff --git a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java b/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java index db02ce8b4da..9c333af2623 100644 --- a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java +++ b/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java @@ -16,8 +16,8 @@ * */ -package com.cloud.consoleproxy; - +package com.cloud.consoleproxy; + import java.util.Map; import javax.ejb.Local; @@ -45,316 +45,274 @@ import com.cloud.ha.HighAvailabilityManager; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; +import com.cloud.info.ConsoleProxyInfo; import com.cloud.utils.NumbersUtil; import com.cloud.utils.component.ComponentLocator; +import com.cloud.utils.component.Inject; import com.cloud.vm.ConsoleProxyVO; import com.cloud.vm.UserVmVO; import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine.Type; import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.VirtualMachineName; -import com.cloud.vm.VirtualMachine.Type; import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; - -@Local(value={ConsoleProxyManager.class}) -public class AgentBasedConsoleProxyManager implements ConsoleProxyManager, VirtualMachineManager { - private static final Logger s_logger = Logger.getLogger(AgentBasedConsoleProxyManager.class); - - private String _name; - protected HostDao _hostDao; - protected UserVmDao _userVmDao; - private String _instance; - private VMInstanceDao _instanceDao; - private ConsoleProxyListener _listener; - - protected int _consoleProxyUrlPort = ConsoleProxyManager.DEFAULT_PROXY_URL_PORT; - protected boolean _sslEnabled = false; - AgentManager _agentMgr; - - public int getVncPort(VMInstanceVO vm) { - if (vm.getHostId() == null) { - return -1; - } - GetVncPortAnswer answer = (GetVncPortAnswer)_agentMgr.easySend(vm.getHostId(), new GetVncPortCommand(vm.getId(), vm.getName())); - return answer == null ? -1 : answer.getPort(); - } - - @Override - public boolean configure(String name, Map params) throws ConfigurationException { - - if(s_logger.isInfoEnabled()) - s_logger.info("Start configuring AgentBasedConsoleProxyManager"); - - _name = name; - - ComponentLocator locator = ComponentLocator.getCurrentLocator(); - ConfigurationDao configDao = locator.getDao(ConfigurationDao.class); - if (configDao == null) { - throw new ConfigurationException( - "Unable to get the configuration dao."); - } - - Map configs = configDao.getConfiguration( - "management-server", params); - String value = configs.get("consoleproxy.url.port"); - if (value != null) - _consoleProxyUrlPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_URL_PORT); - - _hostDao = locator.getDao(HostDao.class); - if (_hostDao == null) { - throw new ConfigurationException("Unable to get " - + HostDao.class.getName()); - } - - _instanceDao = locator.getDao(VMInstanceDao.class); - if (_instanceDao == null) - throw new ConfigurationException("Unable to get " + VMInstanceDao.class.getName()); - - _userVmDao = locator.getDao(UserVmDao.class); - if (_userVmDao == null) - throw new ConfigurationException("Unable to get " + UserVmDao.class.getName()); - - _agentMgr = locator.getManager(AgentManager.class); - if (_agentMgr == null) - throw new ConfigurationException("Unable to get " + AgentManager.class.getName()); - - value = configs.get("consoleproxy.sslEnabled"); - if(value != null && value.equalsIgnoreCase("true")) - _sslEnabled = true; - - _instance = configs.get("instance.name"); - - _listener = new ConsoleProxyListener(this); - _agentMgr.registerForHostEvents(_listener, true, true, false); - - HighAvailabilityManager haMgr = locator.getManager(HighAvailabilityManager.class); - haMgr.registerHandler(Type.ConsoleProxy, this); - - if(s_logger.isInfoEnabled()) - s_logger.info("AgentBasedConsoleProxyManager has been configured. SSL enabled: " + _sslEnabled); - return true; - } - - @Override - public boolean start() { - return true; - } - - @Override - public boolean stop() { - return true; - } - - HostVO findHost(VMInstanceVO vm) { - return _hostDao.findById(vm.getHostId()); - } - - protected ConsoleProxyVO allocateProxy(HostVO host, long dataCenterId) { - // only private IP, public IP, host id have meaningful values, rest of all are place-holder values - String publicIp = host.getPublicIpAddress(); - if(publicIp == null) { - if(s_logger.isDebugEnabled()) - s_logger.debug("Host " + host.getName() + "/" + host.getPrivateIpAddress() + - " does not have public interface, we will return its private IP for cosole proxy."); - publicIp = host.getPrivateIpAddress(); - } + +@Local(value = { ConsoleProxyManager.class }) +public class AgentBasedConsoleProxyManager implements ConsoleProxyManager, VirtualMachineManager, AgentHook { + private static final Logger s_logger = Logger.getLogger(AgentBasedConsoleProxyManager.class); + + private String _name; + @Inject + protected HostDao _hostDao; + @Inject + protected UserVmDao _userVmDao; + private String _instance; + @Inject + private VMInstanceDao _instanceDao; + private ConsoleProxyListener _listener; + + protected int _consoleProxyUrlPort = ConsoleProxyManager.DEFAULT_PROXY_URL_PORT; + protected int _consoleProxyPort = ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT; + protected boolean _sslEnabled = false; + @Inject + AgentManager _agentMgr; + + public int getVncPort(VMInstanceVO vm) { + if (vm.getHostId() == null) { + return -1; + } + GetVncPortAnswer answer = (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), new GetVncPortCommand(vm.getId(), vm.getName())); + return answer == null ? -1 : answer.getPort(); + } + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + + if (s_logger.isInfoEnabled()) + s_logger.info("Start configuring AgentBasedConsoleProxyManager"); + + _name = name; + + ComponentLocator locator = ComponentLocator.getCurrentLocator(); + ConfigurationDao configDao = locator.getDao(ConfigurationDao.class); + if (configDao == null) { + throw new ConfigurationException("Unable to get the configuration dao."); + } + + Map configs = configDao.getConfiguration("management-server", params); + String value = configs.get("consoleproxy.url.port"); + if (value != null) + _consoleProxyUrlPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_URL_PORT); - // FIXME: Removed State.Running does this affect the console proxy? - return new ConsoleProxyVO(1l, "EmbeddedProxy", null, null, null, - "02:02:02:02:02:02", - host.getPrivateIpAddress(), - "255.255.255.0", - 1l, - 1l, - "03:03:03:03:03:03", - publicIp, - "255.255.255.0", - null, - "untagged", - 1l, - dataCenterId, - "0.0.0.0", - host.getId(), - "dns1", - "dn2", - "domain", - 0, - 0); - } - - @Override - public ConsoleProxyVO assignProxy(long dataCenterId, long userVmId) { - UserVmVO userVm = _userVmDao.findById(userVmId); - if (userVm == null) { - s_logger.warn("User VM " + userVmId - + " no longer exists, return a null proxy for user vm:" - + userVmId); - return null; - } - - HostVO host = findHost(userVm); - if(host != null) { - if(s_logger.isDebugEnabled()) - s_logger.debug("Assign embedded console proxy running at " + host.getName() + " to user vm " + userVmId + " with public IP " + host.getPublicIpAddress()); - - // only private IP, public IP, host id have meaningful values, rest of all are place-holder values - String publicIp = host.getPublicIpAddress(); - if(publicIp == null) { - if(s_logger.isDebugEnabled()) - s_logger.debug("Host " + host.getName() + "/" + host.getPrivateIpAddress() + - " does not have public interface, we will return its private IP for cosole proxy."); - publicIp = host.getPrivateIpAddress(); - } - - ConsoleProxyVO proxy = allocateProxy(host, dataCenterId); - - if(host.getProxyPort() != null && host.getProxyPort().intValue() > 0) - proxy.setPort(host.getProxyPort().intValue()); - else - proxy.setPort(_consoleProxyUrlPort); - - proxy.setSslEnabled(_sslEnabled); - return proxy; - } else { - s_logger.warn("Host that VM is running is no longer available, console access to VM " + userVmId + " will be temporarily unavailable."); - } - 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); + value = configs.get("consoleproxy.port"); + if (value != null) + _consoleProxyPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT); + + value = configs.get("consoleproxy.sslEnabled"); + if (value != null && value.equalsIgnoreCase("true")) + _sslEnabled = true; + + _instance = configs.get("instance.name"); + + _listener = new ConsoleProxyListener(this); + _agentMgr.registerForHostEvents(_listener, true, true, false); + + HighAvailabilityManager haMgr = locator.getManager(HighAvailabilityManager.class); + haMgr.registerHandler(Type.ConsoleProxy, this); + + if (s_logger.isInfoEnabled()) + s_logger.info("AgentBasedConsoleProxyManager has been configured. SSL enabled: " + _sslEnabled); + return true; + } + + @Override + public boolean start() { + return true; + } + + @Override + public boolean stop() { + return true; + } + + HostVO findHost(VMInstanceVO vm) { + return _hostDao.findById(vm.getHostId()); + } + + @Override + public ConsoleProxyInfo assignProxy(long dataCenterId, long userVmId) { + UserVmVO userVm = _userVmDao.findById(userVmId); + if (userVm == null) { + s_logger.warn("User VM " + userVmId + " no longer exists, return a null proxy for user vm:" + userVmId); + return null; + } + + HostVO host = findHost(userVm); + if (host != null) { + if (s_logger.isDebugEnabled()) + s_logger.debug("Assign embedded console proxy running at " + host.getName() + " to user vm " + userVmId + " with public IP " + + host.getPublicIpAddress()); + + // only private IP, public IP, host id have meaningful values, rest + // of all are place-holder values + String publicIp = host.getPublicIpAddress(); + if (publicIp == null) { + if (s_logger.isDebugEnabled()) + s_logger.debug("Host " + host.getName() + "/" + host.getPrivateIpAddress() + + " does not have public interface, we will return its private IP for cosole proxy."); + publicIp = host.getPrivateIpAddress(); + } + + int urlPort = _consoleProxyUrlPort; + + if (host.getProxyPort() != null && host.getProxyPort().intValue() > 0) + urlPort = host.getProxyPort().intValue(); + + return new ConsoleProxyInfo(_sslEnabled, publicIp, _consoleProxyPort, urlPort); + } else { + s_logger.warn("Host that VM is running is no longer available, console access to VM " + userVmId + " will be temporarily unavailable."); + } + 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) { + public void onAgentDisconnect(long agentId, Status state) { } - - @Override - public ConsoleProxyVO startProxy(long proxyVmId, long startEventId) { - return null; - } - - @Override - public boolean destroyProxy(long proxyVmId, long startEventId) { - return false; - } - - @Override - public boolean rebootProxy(long proxyVmId, long startEventId) { - return false; - } - - @Override - public boolean stopProxy(long proxyVmId, long startEventId) { - return false; - } - - @Override - public String getName() { - return _name; - } - - @Override - public Command cleanup(ConsoleProxyVO vm, String vmName) { - return new StopCommand(vm, vmName, null); - } - - @Override - public boolean completeMigration(ConsoleProxyVO vm, HostVO host) throws AgentUnavailableException, OperationTimedoutException { - return false; - } - - @Override - public void completeStartCommand(ConsoleProxyVO vm) { - } - - @Override - public void completeStopCommand(ConsoleProxyVO vm) { - } - - @Override - public Long convertToId(String vmName) { - if (!VirtualMachineName.isValidConsoleProxyName(vmName, _instance)) { - return null; - } - return VirtualMachineName.getConsoleProxyId(vmName); - } - - @Override - public boolean destroy(ConsoleProxyVO vm) throws AgentUnavailableException { - return false; - } - - @Override - public ConsoleProxyVO get(long id) { - return null; - } - - @Override - public boolean migrate(ConsoleProxyVO vm, HostVO host) throws AgentUnavailableException, OperationTimedoutException { - return false; - } - - @Override - public HostVO prepareForMigration(ConsoleProxyVO vm) throws InsufficientCapacityException, StorageUnavailableException { - return null; - } - - @Override - public ConsoleProxyVO start(long vmId, long startEventId) throws InsufficientCapacityException, StorageUnavailableException, ConcurrentOperationException { - return null; - } - - @Override - public boolean stop(ConsoleProxyVO vm, long startEventId) throws AgentUnavailableException { - return false; - } -} + + @Override + public ConsoleProxyVO startProxy(long proxyVmId, long startEventId) { + return null; + } + + @Override + public boolean destroyProxy(long proxyVmId, long startEventId) { + return false; + } + + @Override + public boolean rebootProxy(long proxyVmId, long startEventId) { + return false; + } + + @Override + public boolean stopProxy(long proxyVmId, long startEventId) { + return false; + } + + @Override + public String getName() { + return _name; + } + + @Override + public Command cleanup(ConsoleProxyVO vm, String vmName) { + return new StopCommand(vm, vmName, null); + } + + @Override + public boolean completeMigration(ConsoleProxyVO vm, HostVO host) throws AgentUnavailableException, OperationTimedoutException { + return false; + } + + @Override + public void completeStartCommand(ConsoleProxyVO vm) { + } + + @Override + public void completeStopCommand(ConsoleProxyVO vm) { + } + + @Override + public Long convertToId(String vmName) { + if (!VirtualMachineName.isValidConsoleProxyName(vmName, _instance)) { + return null; + } + return VirtualMachineName.getConsoleProxyId(vmName); + } + + @Override + public boolean destroy(ConsoleProxyVO vm) throws AgentUnavailableException { + return false; + } + + @Override + public ConsoleProxyVO get(long id) { + return null; + } + + @Override + public boolean migrate(ConsoleProxyVO vm, HostVO host) throws AgentUnavailableException, OperationTimedoutException { + return false; + } + + @Override + public HostVO prepareForMigration(ConsoleProxyVO vm) throws InsufficientCapacityException, StorageUnavailableException { + return null; + } + + @Override + public ConsoleProxyVO start(long vmId, long startEventId) throws InsufficientCapacityException, StorageUnavailableException, + ConcurrentOperationException { + return null; + } + + @Override + public boolean stop(ConsoleProxyVO vm, long startEventId) throws AgentUnavailableException { + return false; + } +} diff --git a/server/src/com/cloud/consoleproxy/AgentBasedStandaloneConsoleProxyManager.java b/server/src/com/cloud/consoleproxy/AgentBasedStandaloneConsoleProxyManager.java index 4b5f2fb4d4c..8b0858d6e1b 100644 --- a/server/src/com/cloud/consoleproxy/AgentBasedStandaloneConsoleProxyManager.java +++ b/server/src/com/cloud/consoleproxy/AgentBasedStandaloneConsoleProxyManager.java @@ -26,7 +26,7 @@ import org.apache.log4j.Logger; import com.cloud.host.Host; import com.cloud.host.HostVO; -import com.cloud.vm.ConsoleProxyVO; +import com.cloud.info.ConsoleProxyInfo; import com.cloud.vm.UserVmVO; @Local(value={ConsoleProxyManager.class}) @@ -35,7 +35,7 @@ AgentBasedConsoleProxyManager { private static final Logger s_logger = Logger.getLogger(AgentBasedStandaloneConsoleProxyManager.class); @Override - public ConsoleProxyVO assignProxy(long dataCenterId, long userVmId) { + public ConsoleProxyInfo assignProxy(long dataCenterId, long userVmId) { UserVmVO userVm = _userVmDao.findById(userVmId); if (userVm == null) { s_logger.warn("User VM " + userVmId @@ -81,15 +81,11 @@ AgentBasedConsoleProxyManager { publicIp = allocatedHost.getPrivateIpAddress(); } - ConsoleProxyVO proxy = allocateProxy(allocatedHost, dataCenterId); - - if(allocatedHost.getProxyPort() != null && allocatedHost.getProxyPort().intValue() > 0) - proxy.setPort(allocatedHost.getProxyPort().intValue()); - else - proxy.setPort(_consoleProxyUrlPort); - - proxy.setSslEnabled(_sslEnabled); - return proxy; + int urlPort = _consoleProxyUrlPort; + if(allocatedHost.getProxyPort() != null && allocatedHost.getProxyPort().intValue() > 0) + urlPort = allocatedHost.getProxyPort().intValue(); + + return new ConsoleProxyInfo(_sslEnabled, publicIp, _consoleProxyPort, urlPort); } else { s_logger.warn("Host that VM is running is no longer available, console access to VM " + userVmId + " will be temporarily unavailable."); } diff --git a/server/src/com/cloud/consoleproxy/AgentHook.java b/server/src/com/cloud/consoleproxy/AgentHook.java new file mode 100644 index 00000000000..a25e555e92f --- /dev/null +++ b/server/src/com/cloud/consoleproxy/AgentHook.java @@ -0,0 +1,19 @@ +/** + * + */ +package com.cloud.consoleproxy; + +import com.cloud.agent.api.AgentControlAnswer; +import com.cloud.agent.api.ConsoleAccessAuthenticationCommand; +import com.cloud.agent.api.ConsoleProxyLoadReportCommand; +import com.cloud.agent.api.StartupCommand; +import com.cloud.host.HostVO; +import com.cloud.host.Status; + +public interface AgentHook { + void onLoadReport(ConsoleProxyLoadReportCommand cmd); + AgentControlAnswer onConsoleAccessAuthentication(ConsoleAccessAuthenticationCommand cmd); + void onAgentConnect(HostVO host, StartupCommand cmd); + + public void onAgentDisconnect(long agentId, Status state); +} diff --git a/core/src/com/cloud/consoleproxy/ConsoleProxyAlertEventArgs.java b/server/src/com/cloud/consoleproxy/ConsoleProxyAlertEventArgs.java similarity index 100% rename from core/src/com/cloud/consoleproxy/ConsoleProxyAlertEventArgs.java rename to server/src/com/cloud/consoleproxy/ConsoleProxyAlertEventArgs.java diff --git a/core/src/com/cloud/consoleproxy/ConsoleProxyListener.java b/server/src/com/cloud/consoleproxy/ConsoleProxyListener.java similarity index 76% rename from core/src/com/cloud/consoleproxy/ConsoleProxyListener.java rename to server/src/com/cloud/consoleproxy/ConsoleProxyListener.java index e0aa2e5750a..a8a9d992bb4 100644 --- a/core/src/com/cloud/consoleproxy/ConsoleProxyListener.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyListener.java @@ -17,7 +17,6 @@ */ package com.cloud.consoleproxy; - import org.apache.log4j.Logger; import com.cloud.agent.Listener; @@ -33,13 +32,13 @@ import com.cloud.host.Status; public class ConsoleProxyListener implements Listener { private final static Logger s_logger = Logger.getLogger(ConsoleProxyListener.class); - - ConsoleProxyManager _proxyMgr = null; - public ConsoleProxyListener(ConsoleProxyManager proxyMgr) { + AgentHook _proxyMgr = null; + + public ConsoleProxyListener(AgentHook proxyMgr) { _proxyMgr = proxyMgr; } - + @Override public boolean isRecurring() { return true; @@ -47,46 +46,46 @@ public class ConsoleProxyListener implements Listener { @Override public boolean processAnswer(long agentId, long seq, Answer[] answers) { - return true; + return true; } @Override public boolean processCommand(long agentId, long seq, Command[] commands) { return false; } - + @Override public AgentControlAnswer processControlCommand(long agentId, AgentControlCommand cmd) { - if(cmd instanceof ConsoleProxyLoadReportCommand) { - _proxyMgr.onLoadReport((ConsoleProxyLoadReportCommand)cmd); - - // return dummy answer - return new AgentControlAnswer(cmd); - } else if(cmd instanceof ConsoleAccessAuthenticationCommand) { - return _proxyMgr.onConsoleAccessAuthentication((ConsoleAccessAuthenticationCommand)cmd); - } - return null; + if (cmd instanceof ConsoleProxyLoadReportCommand) { + _proxyMgr.onLoadReport((ConsoleProxyLoadReportCommand) cmd); + + // return dummy answer + return new AgentControlAnswer(cmd); + } else if (cmd instanceof ConsoleAccessAuthenticationCommand) { + return _proxyMgr.onConsoleAccessAuthentication((ConsoleAccessAuthenticationCommand) cmd); + } + return null; } @Override public boolean processConnect(HostVO host, StartupCommand cmd) { - _proxyMgr.onAgentConnect(host, cmd); + _proxyMgr.onAgentConnect(host, cmd); return true; } - + @Override public boolean processDisconnect(long agentId, Status state) { - _proxyMgr.onAgentDisconnect(agentId, state); + _proxyMgr.onAgentDisconnect(agentId, state); return true; } - + @Override public boolean processTimeout(long agentId, long seq) { - return true; + return true; } - + @Override public int getTimeout() { - return -1; + return -1; } } diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManager.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManager.java new file mode 100644 index 00000000000..8e9329875bf --- /dev/null +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManager.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.consoleproxy; + +import com.cloud.info.ConsoleProxyInfo; +import com.cloud.utils.component.Manager; +import com.cloud.vm.ConsoleProxyVO; + +public interface ConsoleProxyManager extends Manager { + public static final int DEFAULT_PROXY_CAPACITY = 50; + public static final int DEFAULT_STANDBY_CAPACITY = 10; + public static final int DEFAULT_PROXY_VM_RAMSIZE = 1024; // 1G + + public static final int DEFAULT_PROXY_CMD_PORT = 8001; + public static final int DEFAULT_PROXY_VNC_PORT = 0; + public static final int DEFAULT_PROXY_URL_PORT = 80; + public static final int DEFAULT_PROXY_SESSION_TIMEOUT = 300000; // 5 minutes + + public static final String ALERT_SUBJECT = "proxy-alert"; + + public ConsoleProxyInfo assignProxy(long dataCenterId, long userVmId); + + public ConsoleProxyVO startProxy(long proxyVmId, long startEventId); + + public boolean stopProxy(long proxyVmId, long startEventId); + + public boolean rebootProxy(long proxyVmId, long startEventId); + + public boolean destroyProxy(long proxyVmId, long startEventId); +} diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 3cfbc1dacaf..36732052a9b 100644 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -61,15 +61,13 @@ import com.cloud.async.AsyncJobExecutor; import com.cloud.async.AsyncJobManager; import com.cloud.async.AsyncJobVO; import com.cloud.async.BaseAsyncJobExecutor; -import com.cloud.capacity.dao.CapacityDao; import com.cloud.cluster.ClusterManager; import com.cloud.configuration.Config; -import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; -import com.cloud.dc.VlanVO; import com.cloud.dc.Vlan.VlanType; +import com.cloud.dc.VlanVO; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.HostPodDao; import com.cloud.dc.dao.VlanDao; @@ -84,12 +82,12 @@ import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.StorageUnavailableException; import com.cloud.ha.HighAvailabilityManager; -import com.cloud.ha.dao.HighAvailabilityDao; import com.cloud.host.Host; -import com.cloud.host.HostVO; import com.cloud.host.Host.Type; +import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.info.ConsoleProxyConnectionInfo; +import com.cloud.info.ConsoleProxyInfo; import com.cloud.info.ConsoleProxyLoadInfo; import com.cloud.info.ConsoleProxyStatus; import com.cloud.info.RunningHostCountInfo; @@ -97,7 +95,6 @@ import com.cloud.info.RunningHostInfoAgregator; import com.cloud.info.RunningHostInfoAgregator.ZoneHostInfo; import com.cloud.maid.StackMaid; import com.cloud.network.IpAddrAllocator; -import com.cloud.network.NetworkManager; import com.cloud.network.IpAddrAllocator.networkInfo; import com.cloud.network.dao.IPAddressDao; import com.cloud.offering.ServiceOffering.GuestIpType; @@ -106,10 +103,9 @@ import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePoolVO; import com.cloud.storage.VMTemplateHostVO; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VolumeVO; -import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; -import com.cloud.storage.dao.StoragePoolDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplateHostDao; import com.cloud.storage.dao.VolumeDao; @@ -135,9 +131,9 @@ import com.cloud.vm.ConsoleProxyVO; import com.cloud.vm.State; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachine.Event; import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.VirtualMachineName; -import com.cloud.vm.VirtualMachine.Event; import com.cloud.vm.dao.ConsoleProxyDao; import com.cloud.vm.dao.VMInstanceDao; import com.google.gson.Gson; @@ -162,2202 +158,2088 @@ import com.google.gson.GsonBuilder; // because sooner or later, it will be driven into Running state // @Local(value = { ConsoleProxyManager.class }) -public class ConsoleProxyManagerImpl implements ConsoleProxyManager, - VirtualMachineManager { - private static final Logger s_logger = Logger - .getLogger(ConsoleProxyManagerImpl.class); - - private static final int DEFAULT_FIND_HOST_RETRY_COUNT = 2; - private static final int DEFAULT_CAPACITY_SCAN_INTERVAL = 30000; // 30 - // seconds - private static final int EXECUTOR_SHUTDOWN_TIMEOUT = 1000; // 1 second - - private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION = 3; // 3 - // seconds - private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC = 180; // 3 - // minutes - - private static final int API_WAIT_TIMEOUT = 5000; // 5 seconds (in - // milliseconds) - private static final int STARTUP_DELAY = 60000; // 60 seconds - - private int _consoleProxyPort = ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT; - private int _consoleProxyUrlPort = ConsoleProxyManager.DEFAULT_PROXY_URL_PORT; - - private String _mgmt_host; - private int _mgmt_port = 8250; - - private String _name; - private Adapters _consoleProxyAllocators; - - private ConsoleProxyDao _consoleProxyDao; - private DataCenterDao _dcDao; - private VlanDao _vlanDao; - private VMTemplateDao _templateDao; - private IPAddressDao _ipAddressDao; - private VolumeDao _volsDao; - private HostPodDao _podDao; - private HostDao _hostDao; - private StoragePoolDao _storagePoolDao; - private ConfigurationDao _configDao; - - private VMInstanceDao _instanceDao; - private AccountDao _accountDao; - - private VMTemplateHostDao _vmTemplateHostDao; - private CapacityDao _capacityDao; - private HighAvailabilityDao _haDao; - - private AgentManager _agentMgr; - private NetworkManager _networkMgr; - private StorageManager _storageMgr; - private HighAvailabilityManager _haMgr; - private EventDao _eventDao; - @Inject - ServiceOfferingDao _offeringDao; - private IpAddrAllocator _IpAllocator; - - private ConsoleProxyListener _listener; - - private ServiceOfferingVO _serviceOffering; - private VMTemplateVO _template; - - private AsyncJobManager _asyncMgr; - - private final ScheduledExecutorService _capacityScanScheduler = Executors - .newScheduledThreadPool(1, new NamedThreadFactory("CP-Scan")); - private final ExecutorService _requestHandlerScheduler = Executors - .newCachedThreadPool(new NamedThreadFactory("Request-handler")); - - private long _capacityScanInterval = DEFAULT_CAPACITY_SCAN_INTERVAL; - private int _capacityPerProxy = ConsoleProxyManager.DEFAULT_PROXY_CAPACITY; - private int _standbyCapacity = ConsoleProxyManager.DEFAULT_STANDBY_CAPACITY; - - private int _proxyRamSize; - private int _find_host_retry = DEFAULT_FIND_HOST_RETRY_COUNT; - private int _ssh_retry; - private int _ssh_sleep; - private boolean _use_lvm; - private boolean _use_storage_vm; - - private String _domain; - private String _instance; - - // private String _privateNetmask; - private int _proxyCmdPort = DEFAULT_PROXY_CMD_PORT; - private int _proxySessionTimeoutValue = DEFAULT_PROXY_SESSION_TIMEOUT; - private boolean _sslEnabled = false; - - private final GlobalLock _capacityScanLock = GlobalLock - .getInternLock(getCapacityScanLockName()); - private final GlobalLock _allocProxyLock = GlobalLock - .getInternLock(getAllocProxyLockName()); - - public ConsoleProxyVO assignProxy(final long dataCenterId, final long vmId) { - - final Pair result = new Pair( - this, null); - - _requestHandlerScheduler.execute(new Runnable() { - public void run() { - Transaction txn = Transaction.open(Transaction.CLOUD_DB); - try { - ConsoleProxyVO proxy = doAssignProxy(dataCenterId, vmId); - synchronized (result) { - result.second(proxy); - result.notifyAll(); - } - } catch (Throwable e) { - s_logger.warn("Unexpected exception " + e.getMessage(), e); - } finally { - StackMaid.current().exitCleanup(); - txn.close(); - } - } - }); - - synchronized (result) { - try { - result.wait(API_WAIT_TIMEOUT); - } catch (InterruptedException e) { - s_logger.info("Waiting for console proxy assignment is interrupted"); - } - } - return result.second(); - } - - public ConsoleProxyVO doAssignProxy(long dataCenterId, long vmId) { - ConsoleProxyVO proxy = null; - VMInstanceVO vm = _instanceDao.findById(vmId); - if (vm == null) { - s_logger.warn("VM " + vmId + " no longer exists, return a null proxy for vm:" + vmId); - return null; - } - - Boolean[] proxyFromStoppedPool = new Boolean[1]; - if (_allocProxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { - try { - proxy = getOrAllocProxyResource(dataCenterId, vmId, proxyFromStoppedPool); - } finally { - _allocProxyLock.unlock(); - } - } else { - s_logger.error("Unable to acquire synchronization lock to get/allocate proxy resource for vm :" - + vmId + ". Previous console proxy allocation is taking too long"); - } - - if (proxy == null) { - s_logger.warn("Unable to find or allocate console proxy resource"); - return null; - } - - long proxyVmId = proxy.getId(); - GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(proxyVmId)); - try { - if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { - try { - proxy = startProxy(proxyVmId, 0); - - if (proxy == null) { - // - // We had a situation with multi-pod configuration, where - // storage allocation of the console proxy VM may succeed, but later-on starting of it - // may fail because of running out of computing resource (CPU/memory). We - // currently don't support moving storage to another pod on the fly, to deal - // with the situation we will destroy this proxy VM and let it the whole proxy VM - // creation process re-start again, by hoping that new storage and computing - // resource may be allocated and assigned in another pod - // - if (s_logger.isInfoEnabled()) - s_logger.info("Unable to start console proxy, proxy vm Id : " + proxyVmId + " will recycle it and restart a new one"); - destroyProxy(proxyVmId, 0); - return null; - } else { - if (s_logger.isTraceEnabled()) - s_logger.trace("Console proxy " + proxy.getName() + " is started"); - - // if it is a new assignment or a changed assignment, update the - // record - if (vm.getProxyId() == null || vm.getProxyId().longValue() != proxy.getId()) - _instanceDao.updateProxyId(vmId, proxy.getId(), DateUtil.currentGMTTime()); - - proxy.setSslEnabled(_sslEnabled); - if (_sslEnabled) - proxy.setPort(443); - else - proxy.setPort(80); - return proxy; - } - } finally { - proxyLock.unlock(); - } - } else { - s_logger.error("Unable to acquire synchronization lock to start console proxy " - + proxyVmId + " for vm: " + vmId + ". It takes too long to start the proxy"); - - return null; - } - } finally { - proxyLock.releaseRef(); - } - } - - private ConsoleProxyVO getOrAllocProxyResource(long dataCenterId, - long vmId, Boolean[] proxyFromStoppedPool) { - ConsoleProxyVO proxy = null; - VMInstanceVO vm = this._instanceDao.findById(vmId); - - if (vm != null && vm.getState() != State.Running) { - if (s_logger.isInfoEnabled()) - s_logger.info("Detected that vm : " + vmId + " is not currently at running state, we will fail the proxy assignment for it"); - return null; - } - - if (vm != null && vm.getProxyId() != null) { - proxy = _consoleProxyDao.findById(vm.getProxyId()); - - if (proxy != null) { - if (!isInAssignableState(proxy)) { - if (s_logger.isInfoEnabled()) - s_logger.info("A previous assigned proxy is not assignable now, reassign console proxy for user vm : " + vmId); - proxy = null; - } else { - if (_consoleProxyDao.getProxyActiveLoad(proxy.getId()) < _capacityPerProxy - || hasPreviousSession(proxy, vm)) { - if (s_logger.isTraceEnabled()) - s_logger.trace("Assign previous allocated console proxy for user vm : " + vmId); - - if (proxy.getActiveSession() >= _capacityPerProxy) - s_logger.warn("Assign overloaded proxy to user VM as previous session exists, user vm : " + vmId); - } else { - proxy = null; - } - } - } - } - - if (proxy == null) - proxy = assignProxyFromRunningPool(dataCenterId); - - if (proxy == null) { - if (s_logger.isInfoEnabled()) - s_logger.info("No running console proxy is available, check to see if we can bring up a stopped one for data center : " + dataCenterId); - - proxy = assignProxyFromStoppedPool(dataCenterId); - if (proxy == null) { - if (s_logger.isInfoEnabled()) - s_logger.info("No stopped console proxy is available, need to allocate a new console proxy for data center : " + dataCenterId); - - proxy = startNew(dataCenterId); - } else { - if (s_logger.isInfoEnabled()) - s_logger.info("Found a stopped console proxy, bring it up to running pool. proxy vm id : " - + proxy.getId() + ", data center : " + dataCenterId); - - proxyFromStoppedPool[0] = new Boolean(true); - } - } - - return proxy; - } - - private static boolean isInAssignableState(ConsoleProxyVO proxy) { - // console proxies that are in states of being able to serve user VM - State state = proxy.getState(); - if (state == State.Running || state == State.Starting - || state == State.Creating || state == State.Migrating) - return true; - - return false; - } - - private boolean hasPreviousSession(ConsoleProxyVO proxy, VMInstanceVO vm) { - - ConsoleProxyStatus status = null; - try { - GsonBuilder gb = new GsonBuilder(); - gb.setVersion(1.3); - Gson gson = gb.create(); - - byte[] details = proxy.getSessionDetails(); - status = gson.fromJson(details != null ? new String(details, - Charset.forName("US-ASCII")) : null, - ConsoleProxyStatus.class); - } catch (Throwable e) { - s_logger.warn("Unable to parse proxy session details : " - + proxy.getSessionDetails()); - } - - if (status != null && status.getConnections() != null) { - ConsoleProxyConnectionInfo[] connections = status.getConnections(); - for (int i = 0; i < connections.length; i++) { - long taggedVmId = 0; - if (connections[i].tag != null) { - try { - taggedVmId = Long.parseLong(connections[i].tag); - } catch (NumberFormatException e) { - s_logger.warn( - "Unable to parse console proxy connection info passed through tag: " - + connections[i].tag, e); - } - } - if (taggedVmId == vm.getId()) - return true; - } - - // - // even if we are not in the list, it may because we haven't - // received load-update yet - // wait until session time - // - if (DateUtil.currentGMTTime().getTime() - vm.getProxyAssignTime().getTime() < _proxySessionTimeoutValue) - return true; - - return false; - } else { - s_logger.error("No proxy load info on an overloaded proxy ?"); - return false; - } - } - - @Override - public ConsoleProxyVO startProxy(long proxyVmId, long startEventId) { - try { - return start(proxyVmId, startEventId); - } catch (StorageUnavailableException e) { - s_logger.warn("Exception while trying to start console proxy", e); - return null; - } catch (InsufficientCapacityException e) { - s_logger.warn("Exception while trying to start console proxy", e); - return null; - } catch (ConcurrentOperationException e) { - s_logger.warn("Exception while trying to start console proxy", e); - return null; - } - } - - @Override - @DB - public ConsoleProxyVO start(long proxyId, long startEventId) - throws StorageUnavailableException, InsufficientCapacityException, - ConcurrentOperationException { - - AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor(); - if (asyncExecutor != null) { - AsyncJobVO job = asyncExecutor.getJob(); - - if (s_logger.isInfoEnabled()) - s_logger.info("Start console proxy " + proxyId + ", update async job-" + job.getId()); - _asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", proxyId); - } - - ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyId); - if (proxy == null || proxy.getRemoved() != null) { - s_logger.debug("proxy is not found: " + proxyId); - return null; - } -/* - // don't insert event here, it may be called multiple times! - saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, - EventTypes.EVENT_PROXY_START, - "Starting console proxy with Id: " + proxyId, startEventId); -*/ - - if (s_logger.isTraceEnabled()) { - s_logger.trace("Starting console proxy if it is not started, proxy vm id : " + proxyId); - } - - for (int i = 0; i < 2; i++) { - - State state = proxy.getState(); - - if (state == State.Starting /* || state == State.Migrating */) { - if (s_logger.isDebugEnabled()) - s_logger.debug("Waiting console proxy to be ready, proxy vm id : " + proxyId + " proxy VM state : " + state.toString()); - - if (proxy.getPrivateIpAddress() == null || connect(proxy.getPrivateIpAddress(), _proxyCmdPort) != null) { - if (proxy.getPrivateIpAddress() == null) - s_logger.warn("Retruning a proxy that is being started but private IP has not been allocated yet, proxy vm id : " + proxyId); - else - s_logger.warn("Waiting console proxy to be ready timed out, proxy vm id : " + proxyId); - - // TODO, it is very tricky here, if the startup process - // takes too long and it timed out here, - // we may give back a proxy that is not fully ready for - // functioning - } - return proxy; - } - - if (state == State.Running) { - if (s_logger.isTraceEnabled()) - s_logger.trace("Console proxy is already started: " + proxy.getName()); - return proxy; - } - - DataCenterVO dc = _dcDao.findById(proxy.getDataCenterId()); - HostPodVO pod = _podDao.findById(proxy.getPodId()); - List sps = _storageMgr.getStoragePoolsForVm(proxy.getId()); - StoragePoolVO sp = sps.get(0); // FIXME - - HashSet avoid = new HashSet(); - HostVO routingHost = (HostVO) _agentMgr.findHost(Host.Type.Routing, - dc, pod, sp, _serviceOffering, _template, proxy, null, - avoid); - - if (routingHost == null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Unable to find a routing host for " + proxy.toString()); - continue; - } - } - // to ensure atomic state transition to Starting state - if (!_consoleProxyDao.updateIf(proxy, Event.StartRequested, routingHost.getId())) { - if (s_logger.isDebugEnabled()) { - ConsoleProxyVO temp = _consoleProxyDao.findById(proxyId); - s_logger.debug("Unable to start console proxy " + proxy.getName() + " because it is not in a startable state : " - + ((temp != null) ? temp.getState().toString() : "null")); - } - continue; - } - - try { - Answer answer = null; - int retry = _find_host_retry; - - // Console proxy VM will be running at routing hosts as routing - // hosts have public access to outside network - do { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Trying to start console proxy on host " + routingHost.getName()); - } - - String privateIpAddress = allocPrivateIpAddress( - proxy.getDataCenterId(), routingHost.getPodId(), - proxy.getId(), proxy.getPrivateMacAddress()); - if (privateIpAddress == null && (_IpAllocator != null && !_IpAllocator.exteralIpAddressAllocatorEnabled())) { - s_logger.debug("Not enough ip addresses in " + routingHost.getPodId()); - avoid.add(routingHost); - continue; - } - - proxy.setPrivateIpAddress(privateIpAddress); - String guestIpAddress = _dcDao.allocateLinkLocalPrivateIpAddress(proxy.getDataCenterId(), routingHost.getPodId(), proxy.getId()); - proxy.setGuestIpAddress(guestIpAddress); - - _consoleProxyDao.updateIf(proxy, Event.OperationRetry, routingHost.getId()); - proxy = _consoleProxyDao.findById(proxy.getId()); - - List vols = _storageMgr.prepare(proxy, routingHost); - if (vols == null) { - s_logger.debug("Unable to prepare storage for " + routingHost); - avoid.add(routingHost); - continue; - } - - // _storageMgr.share(proxy, vols, null, true); - - // carry the console proxy port info over so that we don't - // need to configure agent on this - StartConsoleProxyCommand cmdStart = new StartConsoleProxyCommand( - _proxyCmdPort, proxy, proxy.getName(), "", vols, - Integer.toString(_consoleProxyPort), - Integer.toString(_consoleProxyUrlPort), - _mgmt_host, _mgmt_port, _sslEnabled); - - if (s_logger.isDebugEnabled()) - s_logger.debug("Sending start command for console proxy " + proxy.getName() + " to " + routingHost.getName()); - try { - answer = _agentMgr.send(routingHost.getId(), cmdStart); - - s_logger.debug("StartConsoleProxy Answer: " + (answer != null ? answer : "null")); - - if (s_logger.isDebugEnabled()) - s_logger.debug("Received answer on starting console proxy " + proxy.getName() + " on " + routingHost.getName()); - - if (answer != null && answer.getResult()) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Console proxy " + proxy.getName() + " started on " + routingHost.getName()); - } - - if (answer instanceof StartConsoleProxyAnswer) { - StartConsoleProxyAnswer rAnswer = (StartConsoleProxyAnswer) answer; - if (rAnswer.getPrivateIpAddress() != null) { - proxy.setPrivateIpAddress(rAnswer.getPrivateIpAddress()); - } - if (rAnswer.getPrivateMacAddress() != null) { - proxy.setPrivateMacAddress(rAnswer.getPrivateMacAddress()); - } - } - - final EventVO event = new EventVO(); - event.setUserId(User.UID_SYSTEM); - event.setAccountId(Account.ACCOUNT_ID_SYSTEM); - event.setType(EventTypes.EVENT_PROXY_START); - event.setLevel(EventVO.LEVEL_INFO); - event.setStartId(startEventId); - event.setDescription("Console proxy started - " + proxy.getName()); - _eventDao.persist(event); - break; - } - s_logger.debug("Unable to start " + proxy.toString() + " on host " + routingHost.toString() + " due to " + answer.getDetails()); - } catch (OperationTimedoutException e) { - if (e.isActive()) { - s_logger.debug("Unable to start vm " + proxy.getName() + " due to operation timed out and it is active so scheduling a restart."); - _haMgr.scheduleRestart(proxy, true); - return null; - } - } catch (AgentUnavailableException e) { - s_logger.debug("Agent " + routingHost.toString() + " was unavailable to start VM " - + proxy.getName()); - } - - avoid.add(routingHost); - proxy.setPrivateIpAddress(null); - freePrivateIpAddress(privateIpAddress, proxy.getDataCenterId(), proxy.getId()); - proxy.setGuestIpAddress(null); - _dcDao.releaseLinkLocalPrivateIpAddress(guestIpAddress, proxy.getDataCenterId(), proxy.getId()); - _storageMgr.unshare(proxy, vols, routingHost); - } while (--retry > 0 && (routingHost = (HostVO) _agentMgr.findHost(Host.Type.Routing, dc, pod, sp, - _serviceOffering, _template, proxy, null, avoid)) != null); - if (routingHost == null || retry <= 0) { - - SubscriptionMgr.getInstance().notifySubscribers( - ConsoleProxyManager.ALERT_SUBJECT, - this, - new ConsoleProxyAlertEventArgs( - ConsoleProxyAlertEventArgs.PROXY_START_FAILURE, - proxy.getDataCenterId(), proxy.getId(), proxy, - "Unable to find a routing host to run") - ); - - final EventVO event = new EventVO(); - event.setUserId(User.UID_SYSTEM); - event.setAccountId(Account.ACCOUNT_ID_SYSTEM); - event.setType(EventTypes.EVENT_PROXY_START); - event.setLevel(EventVO.LEVEL_ERROR); - event.setStartId(startEventId); - event.setDescription("Starting console proxy failed due to unable to find a host - " + proxy.getName()); - _eventDao.persist(event); - throw new ExecutionException("Couldn't find a routingHost to run console proxy"); - } - - _consoleProxyDao.updateIf(proxy, Event.OperationSucceeded, routingHost.getId()); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Console proxy is now started, vm id : " + proxy.getId()); - } - - // If starting the console proxy failed due to the external - // firewall not being reachable, send an alert. - if (answer != null && answer.getDetails() != null && answer.getDetails().equals("firewall")) { - - SubscriptionMgr.getInstance().notifySubscribers( - ConsoleProxyManager.ALERT_SUBJECT, - this, - new ConsoleProxyAlertEventArgs( - ConsoleProxyAlertEventArgs.PROXY_FIREWALL_ALERT, - proxy.getDataCenterId(), proxy - .getId(), proxy, null) - ); - } - - SubscriptionMgr.getInstance().notifySubscribers( - ConsoleProxyManager.ALERT_SUBJECT, - this, - new ConsoleProxyAlertEventArgs( - ConsoleProxyAlertEventArgs.PROXY_UP, proxy.getDataCenterId(), proxy.getId(), - proxy, null) - ); - - return proxy; - } catch (Throwable thr) { - s_logger.warn("Unexpected exception: ", thr); - - SubscriptionMgr.getInstance().notifySubscribers( - ConsoleProxyManager.ALERT_SUBJECT, - this, - new ConsoleProxyAlertEventArgs( - ConsoleProxyAlertEventArgs.PROXY_START_FAILURE, - proxy.getDataCenterId(), proxy.getId(), proxy, - "Unexpected exception: " + thr.getMessage())); - -/* - final EventVO event = new EventVO(); - event.setUserId(User.UID_SYSTEM); - event.setAccountId(Account.ACCOUNT_ID_SYSTEM); - event.setType(EventTypes.EVENT_PROXY_START); - event.setLevel(EventVO.LEVEL_ERROR); - event.setStartId(startEventId); - event.setDescription("Starting console proxy failed due to unhandled exception - " - + proxy.getName()); - _eventDao.persist(event); -*/ - - Transaction txn = Transaction.currentTxn(); - try { - txn.start(); - String privateIpAddress = proxy.getPrivateIpAddress(); - if (privateIpAddress != null) { - proxy.setPrivateIpAddress(null); - freePrivateIpAddress(privateIpAddress, proxy.getDataCenterId(), proxy.getId()); - } - - _consoleProxyDao.updateIf(proxy, Event.OperationFailed, null); - txn.commit(); - } catch (Exception e) { - s_logger.error("Caught exception during error recovery"); - } - - if (thr instanceof StorageUnavailableException) { - throw (StorageUnavailableException) thr; - } else if (thr instanceof ConcurrentOperationException) { - throw (ConcurrentOperationException) thr; - } else if (thr instanceof ExecutionException) { - s_logger.error("Error while starting console proxy due to " + thr.getMessage()); - } else { - s_logger.error("Error while starting console proxy ", thr); - } - return null; - } - } - - s_logger.warn("Starting console proxy encounters non-startable situation"); - return null; - } - - public ConsoleProxyVO assignProxyFromRunningPool(long dataCenterId) { - - if (s_logger.isTraceEnabled()) - s_logger.trace("Assign console proxy from running pool for request from data center : " + dataCenterId); - - ConsoleProxyAllocator allocator = getCurrentAllocator(); - assert (allocator != null); - List runningList = _consoleProxyDao.getProxyListInStates(dataCenterId, State.Running); - if (runningList != null && runningList.size() > 0) { - if (s_logger.isTraceEnabled()) { - s_logger.trace("Running proxy pool size : " - + runningList.size()); - for (ConsoleProxyVO proxy : runningList) - s_logger.trace("Running proxy instance : " - + proxy.getName()); - } - - List> l = _consoleProxyDao.getProxyLoadMatrix(); - Map loadInfo = new HashMap(); - if (l != null) { - for (Pair p : l) { - loadInfo.put(p.first(), p.second()); - - if (s_logger.isTraceEnabled()) { - s_logger.trace("Running proxy instance allocation load { proxy id : " - + p.first() + ", load : " + p.second() + "}"); - } - } - } - return allocator.allocProxy(runningList, loadInfo, dataCenterId); - } else { - if (s_logger.isTraceEnabled()) - s_logger.trace("Empty running proxy pool for now in data center : " + dataCenterId); - } - return null; - } - - public ConsoleProxyVO assignProxyFromStoppedPool(long dataCenterId) { - List l = _consoleProxyDao.getProxyListInStates( - dataCenterId, State.Creating, State.Starting, State.Stopped, - State.Migrating); - if (l != null && l.size() > 0) - return l.get(0); - - return null; - } - - public ConsoleProxyVO startNew(long dataCenterId) { - - if (s_logger.isDebugEnabled()) - s_logger.debug("Assign console proxy from a newly started instance for request from data center : " + dataCenterId); - - Map context = createProxyInstance(dataCenterId); - - long proxyVmId = (Long) context.get("proxyVmId"); - if (proxyVmId == 0) { - if (s_logger.isTraceEnabled()) - s_logger.trace("Creating proxy instance failed, data center id : " + dataCenterId); - - // release critical system resource on failure - if (context.get("publicIpAddress") != null) - freePublicIpAddress((String) context.get("publicIpAddress"), dataCenterId, 0); - - return null; - } - - ConsoleProxyVO proxy = allocProxyStorage(dataCenterId, proxyVmId); - if (proxy != null) { - SubscriptionMgr.getInstance().notifySubscribers( - ConsoleProxyManager.ALERT_SUBJECT, - this, - new ConsoleProxyAlertEventArgs( - ConsoleProxyAlertEventArgs.PROXY_CREATED, - dataCenterId, proxy.getId(), proxy, null)); - return proxy; - } else { - if (s_logger.isDebugEnabled()) - s_logger.debug("Unable to allocate console proxy storage, remove the console proxy record from DB, proxy id: " + proxyVmId); - - SubscriptionMgr.getInstance().notifySubscribers( - ConsoleProxyManager.ALERT_SUBJECT, - this, - new ConsoleProxyAlertEventArgs( - ConsoleProxyAlertEventArgs.PROXY_CREATE_FAILURE, - dataCenterId, proxyVmId, null, - "Unable to allocate storage")); - - destroyProxyDBOnly(proxyVmId); - } - return null; - } - - @DB - protected Map createProxyInstance(long dataCenterId) { - - Map context = new HashMap(); - String publicIpAddress = null; - - Transaction txn = Transaction.currentTxn(); - try { - DataCenterVO dc = _dcDao.findById(dataCenterId); - assert (dc != null); - context.put("dc", dc); - - // this will basically allocate the pod based on data center id as - // we use system user id here - Set avoidPods = new HashSet(); - Pair pod = null; - networkInfo publicIpAndVlan = null; - - // About MAC address allocation - // MAC address used by User VM is inherited from DomR MAC address, - // with the least 16 bits overrided. to avoid - // potential conflicts, domP will mask bit 31 - // - String[] macAddresses = _dcDao.getNextAvailableMacAddressPair(dataCenterId, (1L << 31)); - String privateMacAddress = macAddresses[0]; - String publicMacAddress = macAddresses[1]; - macAddresses = _dcDao.getNextAvailableMacAddressPair(dataCenterId, (1L << 31)); - String guestMacAddress = macAddresses[0]; - while ((pod = _agentMgr.findPod(_template, _serviceOffering, dc, - Account.ACCOUNT_ID_SYSTEM, avoidPods)) != null) { - publicIpAndVlan = allocPublicIpAddress(dataCenterId, pod.first().getId(), publicMacAddress); - if (publicIpAndVlan == null) { - s_logger.warn("Unable to allocate public IP address for console proxy vm in data center : " - + dataCenterId + ", pod=" + pod.first().getId()); - avoidPods.add(pod.first().getId()); - } else { - break; - } - } - - if (pod == null || publicIpAndVlan == null) { - s_logger.warn("Unable to allocate pod for console proxy vm in data center : " + dataCenterId); - - context.put("proxyVmId", (long) 0); - return context; - } - - long id = _consoleProxyDao.getNextInSequence(Long.class, "id"); - - context.put("publicIpAddress", publicIpAndVlan._ipAddr); - context.put("pod", pod); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Pod allocated " + pod.first().getName()); - } - - String cidrNetmask = NetUtils.getCidrNetmask(pod.first().getCidrSize()); - - // Find the VLAN ID, VLAN gateway, and VLAN netmask for - // publicIpAddress - publicIpAddress = publicIpAndVlan._ipAddr; - - String vlanGateway = publicIpAndVlan._gateWay; - String vlanNetmask = publicIpAndVlan._netMask; - - txn.start(); - ConsoleProxyVO proxy; - String name = VirtualMachineName.getConsoleProxyName(id, _instance).intern(); - proxy = new ConsoleProxyVO(id, name, guestMacAddress, null, NetUtils.getLinkLocalNetMask(), - privateMacAddress, null, cidrNetmask, _template.getId(), - _template.getGuestOSId(), publicMacAddress, - publicIpAddress, vlanNetmask, publicIpAndVlan._vlanDbId, publicIpAndVlan._vlanid, pod.first().getId(), dataCenterId, - vlanGateway, null, dc.getDns1(), dc.getDns2(), _domain, - _proxyRamSize, 0); - - proxy.setLastHostId(pod.second()); - proxy = _consoleProxyDao.persist(proxy); - long proxyVmId = proxy.getId(); - - final EventVO event = new EventVO(); - event.setUserId(User.UID_SYSTEM); - event.setAccountId(Account.ACCOUNT_ID_SYSTEM); - event.setType(EventTypes.EVENT_PROXY_CREATE); - event.setLevel(EventVO.LEVEL_INFO); - event.setDescription("New console proxy created - " - + proxy.getName()); - _eventDao.persist(event); - txn.commit(); - - context.put("proxyVmId", proxyVmId); - return context; - } catch (Throwable e) { - s_logger.error("Unexpected exception : ", e); - - context.put("proxyVmId", (long) 0); - return context; - } - } - - @DB - protected ConsoleProxyVO allocProxyStorage(long dataCenterId, long proxyVmId) { - ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId); - assert (proxy != null); - - DataCenterVO dc = _dcDao.findById(dataCenterId); - HostPodVO pod = _podDao.findById(proxy.getPodId()); - final AccountVO account = _accountDao.findById(Account.ACCOUNT_ID_SYSTEM); - - try { - List vols = _storageMgr.create(account, proxy, _template, dc, pod, _serviceOffering, null,0); - if (vols == null) { - s_logger.error("Unable to alloc storage for console proxy"); - return null; - } - - Transaction txn = Transaction.currentTxn(); - txn.start(); - - // update pool id - ConsoleProxyVO vo = _consoleProxyDao.findById(proxy.getId()); - _consoleProxyDao.update(proxy.getId(), vo); - - // kick the state machine - _consoleProxyDao.updateIf(proxy, Event.OperationSucceeded, null); - - txn.commit(); - return proxy; - } catch (StorageUnavailableException e) { - s_logger.error("Unable to alloc storage for console proxy: ", e); - return null; - } catch (ExecutionException e) { - s_logger.error("Unable to alloc storage for console proxy: ", e); - return null; - } - } - - private networkInfo allocPublicIpAddress(long dcId, long podId, String macAddr) { - - if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) { - IpAddrAllocator.IpAddr ip = _IpAllocator.getPublicIpAddress(macAddr, dcId, podId); - networkInfo net = new networkInfo(ip.ipaddr, ip.netMask, ip.gateway, null, "untagged"); - return net; - } - - Pair ipAndVlan = _vlanDao.assignIpAddress(dcId, - Account.ACCOUNT_ID_SYSTEM, DomainVO.ROOT_DOMAIN, - VlanType.VirtualNetwork, true); - - if (ipAndVlan == null) { - s_logger.debug("Unable to get public ip address (type=Virtual) for console proxy vm for data center : " + dcId); - ipAndVlan = _vlanDao.assignPodDirectAttachIpAddress(dcId, podId, Account.ACCOUNT_ID_SYSTEM, DomainVO.ROOT_DOMAIN); - if (ipAndVlan == null) - s_logger.debug("Unable to get public ip address (type=DirectAttach) for console proxy vm for data center : " + dcId); - } - if (ipAndVlan != null) { - VlanVO vlan = ipAndVlan.second(); - networkInfo net = new networkInfo(ipAndVlan.first(), vlan.getVlanNetmask(), vlan.getVlanGateway(), vlan.getId(), vlan.getVlanId()); - return net; - } - return null; - } - - private String allocPrivateIpAddress(Long dcId, Long podId, Long proxyId, String macAddr) { - if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) { - return _IpAllocator.getPrivateIpAddress(macAddr, dcId, podId).ipaddr; - } else { - return _dcDao.allocatePrivateIpAddress(dcId, podId, proxyId); - } - } - - private void freePrivateIpAddress(String ipAddress, Long dcId, Long podId) { - if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) { - _IpAllocator.releasePrivateIpAddress(ipAddress, dcId, podId); - } else { - _dcDao.releasePrivateIpAddress(ipAddress, dcId, podId); - } - } - - private void freePublicIpAddress(String ipAddress, long dcId, long podId) { - if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) { - _IpAllocator.releasePublicIpAddress(ipAddress, dcId, podId); - } else { - _ipAddressDao.unassignIpAddress(ipAddress); - } - } - - private ConsoleProxyAllocator getCurrentAllocator() { - // for now, only one adapter is supported - Enumeration it = _consoleProxyAllocators.enumeration(); - if (it.hasMoreElements()) - return it.nextElement(); - - return null; - } - - protected String connect(String ipAddress, int port) { - for (int i = 0; i <= _ssh_retry; i++) { - SocketChannel sch = null; - try { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Trying to connect to " + ipAddress); - } - sch = SocketChannel.open(); - sch.configureBlocking(true); - sch.socket().setSoTimeout(5000); - - InetSocketAddress addr = new InetSocketAddress(ipAddress, port); - sch.connect(addr); - return null; - } catch (IOException e) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Could not connect to " + ipAddress); - } - } finally { - if (sch != null) { - try { - sch.close(); - } catch (IOException e) { - } - } - } - try { - Thread.sleep(_ssh_sleep); - } catch (InterruptedException ex) { - } - } - - s_logger.debug("Unable to logon to " + ipAddress); - - return "Unable to connect"; - } - - public void onLoadAnswer(ConsoleProxyLoadAnswer answer) { - if (answer.getDetails() == null) - return; - - ConsoleProxyStatus status = null; - try { - GsonBuilder gb = new GsonBuilder(); - gb.setVersion(1.3); - Gson gson = gb.create(); - status = gson.fromJson(answer.getDetails(), ConsoleProxyStatus.class); - } catch (Throwable e) { - s_logger.warn("Unable to parse load info from proxy, proxy vm id : " - + answer.getProxyVmId() + ", info : " + answer.getDetails()); - } - - if (status != null) { - int count = 0; - if (status.getConnections() != null) - count = status.getConnections().length; - - byte[] details = null; - if (answer.getDetails() != null) - details = answer.getDetails().getBytes(Charset.forName("US-ASCII")); - _consoleProxyDao.update(answer.getProxyVmId(), count, DateUtil.currentGMTTime(), details); - } else { - if (s_logger.isTraceEnabled()) - s_logger.trace("Unable to get console proxy load info, id : " + answer.getProxyVmId()); - - _consoleProxyDao.update(answer.getProxyVmId(), 0, DateUtil.currentGMTTime(), null); - // TODO : something is wrong with the VM, restart it? - } - } - - 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); - } - } - - 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); - } - - private ConsoleProxyVO findConsoleProxyByHost(HostVO host) throws NumberFormatException { - String name = host.getName(); - long proxyVmId = 0; - ConsoleProxyVO proxy = null; - if (name != null && name.startsWith("v-")) { - String[] tokens = name.split("-"); - proxyVmId = Long.parseLong(tokens[1]); - proxy = this._consoleProxyDao.findById(proxyVmId); - } - return proxy; - } - @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.setPrivateNetmask(cmd.getPrivateNetmask()); - 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) { - 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 = this._consoleProxyDao.findById(proxyVmId); - if (proxy != null) { - Long hostId = proxy.getHostId(); - - // 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; - } - } - } - } - - private void checkPendingProxyVMs() { - // drive state to change away from transient states - List l = _consoleProxyDao.getProxyListInStates(State.Creating); - if (l != null && l.size() > 0) { - for (ConsoleProxyVO proxy : l) { - if (proxy.getLastUpdateTime() == null - || (proxy.getLastUpdateTime() != null && System.currentTimeMillis() - proxy.getLastUpdateTime().getTime() > 60000)) { - try { - ConsoleProxyVO readyProxy = null; - if (_allocProxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { - try { - readyProxy = allocProxyStorage(proxy.getDataCenterId(), proxy.getId()); - } finally { - _allocProxyLock.unlock(); - } - - if (readyProxy != null) { - GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(readyProxy.getId())); - try { - if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { - try { - readyProxy = start(readyProxy.getId(), 0); - } finally { - proxyLock.unlock(); - } - } else { - if (s_logger.isInfoEnabled()) - s_logger.info("Unable to acquire synchronization lock to start console proxy : " + readyProxy.getName()); - } - } finally { - proxyLock.releaseRef(); - } - } - } else { - if (s_logger.isInfoEnabled()) - s_logger.info("Unable to acquire synchronization lock to allocate proxy storage, wait for next turn"); - } - } catch (StorageUnavailableException e) { - s_logger.warn("Storage unavailable", e); - } catch (InsufficientCapacityException e) { - s_logger.warn("insuffiient capacity", e); - } catch (ConcurrentOperationException e) { - s_logger.debug("Concurrent operation: " - + e.getMessage()); - } - } - } - } - } - - private Runnable getCapacityScanTask() { - return new Runnable() { - - @Override - public void run() { - Transaction txn = Transaction.open(Transaction.CLOUD_DB); - try { - reallyRun(); - } catch (Throwable e) { - s_logger.warn("Unexpected exception " + e.getMessage(), e); - } finally { - StackMaid.current().exitCleanup(); - txn.close(); - } - } - - private void reallyRun() { - if (s_logger.isTraceEnabled()) - s_logger.trace("Begin console proxy capacity scan"); - - // config var for consoleproxy.restart check - String restart = _configDao.getValue("consoleproxy.restart"); - if(restart != null && restart.equalsIgnoreCase("false")) - { - s_logger.debug("Capacity scan disabled purposefully, consoleproxy.restart = false. This happens when the primarystorage is in maintenance mode"); - return; - } - - Map zoneHostInfoMap = getZoneHostInfo(); - if (isServiceReady(zoneHostInfoMap)) { - if (s_logger.isTraceEnabled()) - s_logger.trace("Service is ready, check to see if we need to allocate standby capacity"); - - if (!_capacityScanLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION)) { - if (s_logger.isTraceEnabled()) - s_logger.trace("Capacity scan lock is used by others, skip and wait for my turn"); - return; - } - - if (s_logger.isTraceEnabled()) - s_logger.trace("*** Begining capacity scan... ***"); - - try { - checkPendingProxyVMs(); - - // scan default data center first - long defaultId = 0; - - // proxy count info by data-centers (zone-id, zone-name, - // count) - List l = _consoleProxyDao.getDatacenterProxyLoadMatrix(); - - // running VM session count by data-centers (zone-id, - // zone-name, count) - List listVmCounts = _consoleProxyDao.getDatacenterSessionLoadMatrix(); - - // indexing load info by data-center id - Map mapVmCounts = new HashMap(); - if (listVmCounts != null) - for (ConsoleProxyLoadInfo info : listVmCounts) - mapVmCounts.put(info.getId(), info); - - for (ConsoleProxyLoadInfo info : l) { - if (info.getName().equals(_instance)) { - ConsoleProxyLoadInfo vmInfo = mapVmCounts.get(info.getId()); - - if (!checkCapacity(info, vmInfo != null ? vmInfo : new ConsoleProxyLoadInfo())) { - if (isZoneReady(zoneHostInfoMap, info.getId())) { - allocCapacity(info.getId()); - } else { - if (s_logger.isTraceEnabled()) - s_logger.trace("Zone " + info.getId() + " is not ready to alloc standy console proxy"); - } - } - - defaultId = info.getId(); - break; - } - } - - // scan rest of data-centers - for (ConsoleProxyLoadInfo info : l) { - if (info.getId() != defaultId) { - ConsoleProxyLoadInfo vmInfo = mapVmCounts.get(info.getId()); - - if (!checkCapacity(info, vmInfo != null ? vmInfo : new ConsoleProxyLoadInfo())) { - if (isZoneReady(zoneHostInfoMap, info.getId())) { - allocCapacity(info.getId()); - } else { - if (s_logger.isTraceEnabled()) - s_logger.trace("Zone " + info.getId() + " is not ready to alloc standy console proxy"); - } - } - } - } - - if (s_logger.isTraceEnabled()) - s_logger.trace("*** Stop capacity scan ***"); - } finally { - _capacityScanLock.unlock(); - } - - } else { - if (s_logger.isTraceEnabled()) - s_logger.trace("Service is not ready for capacity preallocation, wait for next time"); - } - - if (s_logger.isTraceEnabled()) - s_logger.trace("End of console proxy capacity scan"); - } - }; - } - - private boolean checkCapacity(ConsoleProxyLoadInfo proxyCountInfo, - ConsoleProxyLoadInfo vmCountInfo) { - - if (proxyCountInfo.getCount() * _capacityPerProxy - - vmCountInfo.getCount() <= _standbyCapacity) - return false; - - return true; - } - - private void allocCapacity(long dataCenterId) { - if (s_logger.isTraceEnabled()) - s_logger.trace("Allocate console proxy standby capacity for data center : " + dataCenterId); - - boolean proxyFromStoppedPool = false; - ConsoleProxyVO proxy = assignProxyFromStoppedPool(dataCenterId); - if (proxy == null) { - if (s_logger.isInfoEnabled()) - s_logger.info("No stopped console proxy is available, need to allocate a new console proxy"); - - if (_allocProxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { - try { - proxy = startNew(dataCenterId); - } finally { - _allocProxyLock.unlock(); - } - } else { - if (s_logger.isInfoEnabled()) - s_logger.info("Unable to acquire synchronization lock to allocate proxy resource for standby capacity, wait for next scan"); - return; - } - } else { - if (s_logger.isInfoEnabled()) - s_logger.info("Found a stopped console proxy, bring it up to running pool. proxy vm id : " + proxy.getId()); - proxyFromStoppedPool = true; - } - - if (proxy != null) { - long proxyVmId = proxy.getId(); - GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(proxyVmId)); - try { - if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { - try { - proxy = startProxy(proxyVmId, 0); - } finally { - proxyLock.unlock(); - } - } else { - if (s_logger.isInfoEnabled()) - s_logger.info("Unable to acquire synchronization lock to start proxy for standby capacity, proxy vm id : " + proxy.getId()); - return; - } - } finally { - proxyLock.releaseRef(); - } - - if (proxy == null) { - if (s_logger.isInfoEnabled()) - s_logger.info("Unable to start console proxy for standby capacity, proxy vm Id : " - + proxyVmId + ", will recycle it and start a new one"); - - if (proxyFromStoppedPool) - destroyProxy(proxyVmId, 0); - } else { - if (s_logger.isInfoEnabled()) - s_logger.info("Console proxy " + proxy.getName() + " is started"); - } - } - } - - public boolean isServiceReady(Map zoneHostInfoMap) { - for (ZoneHostInfo zoneHostInfo : zoneHostInfoMap.values()) { - if (isZoneHostReady(zoneHostInfo)) { - if (s_logger.isInfoEnabled()) - s_logger.info("Zone " + zoneHostInfo.getDcId() + " is ready to launch"); - return true; - } - } - - return false; - } - - public boolean isZoneReady(Map zoneHostInfoMap, - long dataCenterId) { - ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenterId); - if (zoneHostInfo != null && isZoneHostReady(zoneHostInfo)) { - VMTemplateVO template = _templateDao.findConsoleProxyTemplate(); - HostVO secondaryStorageHost = _storageMgr.getSecondaryStorageHost(dataCenterId); - boolean templateReady = false; - - if (template != null && secondaryStorageHost != null) { - VMTemplateHostVO templateHostRef = _vmTemplateHostDao.findByHostTemplate(secondaryStorageHost.getId(), template.getId()); - templateReady = (templateHostRef != null) && (templateHostRef.getDownloadState() == Status.DOWNLOADED); - } - - if (templateReady) { - List> l = _consoleProxyDao.getDatacenterStoragePoolHostInfo(dataCenterId, _use_lvm); - if (l != null && l.size() > 0 && l.get(0).second().intValue() > 0) { - return true; - } else { - if (s_logger.isTraceEnabled()) - s_logger.trace("Primary storage is not ready, wait until it is ready to launch console proxy"); - } - } else { - if (s_logger.isTraceEnabled()) - s_logger.trace("Zone host is ready, but console proxy template is not ready"); - } - } - return false; - } - - private boolean isZoneHostReady(ZoneHostInfo zoneHostInfo) { - int expectedFlags = 0; - if (_use_storage_vm) - expectedFlags = RunningHostInfoAgregator.ZoneHostInfo.ROUTING_HOST_MASK; - else - expectedFlags = RunningHostInfoAgregator.ZoneHostInfo.ALL_HOST_MASK; - - return (zoneHostInfo.getFlags() & expectedFlags) == expectedFlags; - } - - private synchronized Map getZoneHostInfo() { - Date cutTime = DateUtil.currentGMTTime(); - List l = _hostDao.getRunningHostCounts(new Date(cutTime.getTime() - ClusterManager.DEFAULT_HEARTBEAT_THRESHOLD)); - - RunningHostInfoAgregator aggregator = new RunningHostInfoAgregator(); - if (l.size() > 0) - for (RunningHostCountInfo countInfo : l) - aggregator.aggregate(countInfo); - - return aggregator.getZoneHostInfoMap(); - } - - @Override - public String getName() { - return _name; - } - - @Override - public boolean start() { - if (s_logger.isInfoEnabled()) - s_logger.info("Start console proxy manager"); - - return true; - } - - @Override - public boolean stop() { - if (s_logger.isInfoEnabled()) - s_logger.info("Stop console proxy manager"); - _capacityScanScheduler.shutdownNow(); - - try { - _capacityScanScheduler.awaitTermination(EXECUTOR_SHUTDOWN_TIMEOUT, - TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - } - - _capacityScanLock.releaseRef(); - _allocProxyLock.releaseRef(); - return true; - } - - @Override - public boolean configure(String name, Map params) - throws ConfigurationException { - if (s_logger.isInfoEnabled()) - s_logger.info("Start configuring console proxy manager : " + name); - - _name = name; - - ComponentLocator locator = ComponentLocator.getCurrentLocator(); - ConfigurationDao configDao = locator.getDao(ConfigurationDao.class); - if (configDao == null) { - throw new ConfigurationException( - "Unable to get the configuration dao."); - } - - Map configs = configDao.getConfiguration( - "management-server", params); - - _proxyRamSize = NumbersUtil.parseInt(configs - .get("consoleproxy.ram.size"), DEFAULT_PROXY_VM_RAMSIZE); - - String value = configs.get("start.retry"); - _find_host_retry = NumbersUtil.parseInt(value, - DEFAULT_FIND_HOST_RETRY_COUNT); - - value = configs.get("consoleproxy.cmd.port"); - _proxyCmdPort = NumbersUtil.parseInt(value, DEFAULT_PROXY_CMD_PORT); - - value = configs.get("consoleproxy.sslEnabled"); - if (value != null && value.equalsIgnoreCase("true")) - _sslEnabled = true; - - value = configs.get("consoleproxy.capacityscan.interval"); - _capacityScanInterval = NumbersUtil.parseLong(value, DEFAULT_CAPACITY_SCAN_INTERVAL); - - _capacityPerProxy = NumbersUtil.parseInt(configs.get("consoleproxy.session.max"), DEFAULT_PROXY_CAPACITY); - _standbyCapacity = NumbersUtil.parseInt(configs.get("consoleproxy.capacity.standby"), DEFAULT_STANDBY_CAPACITY); - _proxySessionTimeoutValue = NumbersUtil.parseInt(configs.get("consoleproxy.session.timeout"), DEFAULT_PROXY_SESSION_TIMEOUT); - - value = configs.get("consoleproxy.port"); - if (value != null) - _consoleProxyPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT); - - value = configs.get("consoleproxy.url.port"); - if (value != null) - _consoleProxyUrlPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_URL_PORT); - - value = configs.get("system.vm.use.local.storage"); - if (value != null && value.equalsIgnoreCase("true")) - _use_lvm = true; - - value = configs.get("secondary.storage.vm"); - if (value != null && value.equalsIgnoreCase("true")) - _use_storage_vm = true; - - if (s_logger.isInfoEnabled()) { - s_logger.info("Console proxy max session soft limit : " + _capacityPerProxy); - s_logger.info("Console proxy standby capacity : " + _standbyCapacity); - } - - _domain = configs.get("domain"); - if (_domain == null) { - _domain = "foo.com"; - } - - _instance = configs.get("instance.name"); - if (_instance == null) { - _instance = "DEFAULT"; - } - - value = (String) params.get("ssh.sleep"); - _ssh_sleep = NumbersUtil.parseInt(value, 5) * 1000; - - value = (String) params.get("ssh.retry"); - _ssh_retry = NumbersUtil.parseInt(value, 3); - - Map agentMgrConfigs = configDao.getConfiguration("AgentManager", params); - _mgmt_host = agentMgrConfigs.get("host"); - if (_mgmt_host == null) { - s_logger.warn("Critical warning! Please configure your management server host address right after you have started your management server and then restart it, otherwise you won't be able to do console access"); - } - - value = agentMgrConfigs.get("port"); - _mgmt_port = NumbersUtil.parseInt(value, 8250); - - _consoleProxyDao = locator.getDao(ConsoleProxyDao.class); - if (_consoleProxyDao == null) { - throw new ConfigurationException("Unable to get " + ConsoleProxyDao.class.getName()); - } - - _consoleProxyAllocators = locator.getAdapters(ConsoleProxyAllocator.class); - if (_consoleProxyAllocators == null || !_consoleProxyAllocators.isSet()) { - throw new ConfigurationException("Unable to get proxy allocators"); - } - - _dcDao = locator.getDao(DataCenterDao.class); - if (_dcDao == null) { - throw new ConfigurationException("Unable to get " + DataCenterDao.class.getName()); - } - - _templateDao = locator.getDao(VMTemplateDao.class); - if (_templateDao == null) { - throw new ConfigurationException("Unable to get " + VMTemplateDao.class.getName()); - } - - _ipAddressDao = locator.getDao(IPAddressDao.class); - if (_ipAddressDao == null) { - throw new ConfigurationException("Unable to get " + IPAddressDao.class.getName()); - } - - _volsDao = locator.getDao(VolumeDao.class); - if (_volsDao == null) { - throw new ConfigurationException("Unable to get " + VolumeDao.class.getName()); - } - - _podDao = locator.getDao(HostPodDao.class); - if (_podDao == null) { - throw new ConfigurationException("Unable to get " + HostPodDao.class.getName()); - } - - _hostDao = locator.getDao(HostDao.class); - if (_hostDao == null) { - throw new ConfigurationException("Unable to get " + HostDao.class.getName()); - } - - _eventDao = locator.getDao(EventDao.class); - if (_eventDao == null) { - throw new ConfigurationException("Unable to get " + EventDao.class.getName()); - } - - _storagePoolDao = locator.getDao(StoragePoolDao.class); - if (_storagePoolDao == null) { - throw new ConfigurationException("Unable to find " + StoragePoolDao.class); - } - - _configDao = locator.getDao(ConfigurationDao.class); - if (_configDao == null) { - throw new ConfigurationException("Unable to find " + ConfigurationDao.class); - } - - _vmTemplateHostDao = locator.getDao(VMTemplateHostDao.class); - if (_vmTemplateHostDao == null) { - throw new ConfigurationException("Unable to get " + VMTemplateHostDao.class.getName()); - } - - _instanceDao = locator.getDao(VMInstanceDao.class); - if (_instanceDao == null) - throw new ConfigurationException("Unable to get " + VMInstanceDao.class.getName()); - - _capacityDao = locator.getDao(CapacityDao.class); - if (_capacityDao == null) { - throw new ConfigurationException("Unable to get " + CapacityDao.class.getName()); - } - - _haDao = locator.getDao(HighAvailabilityDao.class); - if (_haDao == null) { - throw new ConfigurationException("Unable to get " + HighAvailabilityDao.class.getName()); - } - - _accountDao = locator.getDao(AccountDao.class); - if (_accountDao == null) { - throw new ConfigurationException("Unable to get " + AccountDao.class.getName()); - } - - _vlanDao = locator.getDao(VlanDao.class); - if (_vlanDao == null) { - throw new ConfigurationException("Unable to get " + VlanDao.class.getName()); - } - - _agentMgr = locator.getManager(AgentManager.class); - if (_agentMgr == null) { - throw new ConfigurationException("Unable to get " + AgentManager.class.getName()); - } - - _networkMgr = locator.getManager(NetworkManager.class); - if (_networkMgr == null) { - throw new ConfigurationException("Unable to get " + NetworkManager.class.getName()); - } - - _listener = new ConsoleProxyListener(this); - _agentMgr.registerForHostEvents(_listener, true, true, false); - - _haMgr = locator.getManager(HighAvailabilityManager.class); - if (_haMgr == null) { - throw new ConfigurationException("Unable to get " - + HighAvailabilityManager.class.getName()); - } - - _storageMgr = locator.getManager(StorageManager.class); - if (_storageMgr == null) { - throw new ConfigurationException("Unable to get " - + StorageManager.class.getName()); - } - - _asyncMgr = locator.getManager(AsyncJobManager.class); - if (_asyncMgr == null) { - throw new ConfigurationException("Unable to get " - + AsyncJobManager.class.getName()); - } - - Adapters ipAllocators = locator.getAdapters(IpAddrAllocator.class); - if (ipAllocators != null && ipAllocators.isSet()) { - Enumeration it = ipAllocators.enumeration(); - _IpAllocator = it.nextElement(); - } - - HighAvailabilityManager haMgr = locator.getManager(HighAvailabilityManager.class); - if (haMgr != null) { - haMgr.registerHandler(VirtualMachine.Type.ConsoleProxy, this); - } - - boolean useLocalStorage = Boolean.parseBoolean((String) params.get(Config.SystemVMUseLocalStorage.key())); - _serviceOffering = new ServiceOfferingVO("Fake Offering For DomP", 1, - _proxyRamSize, 0, 0, 0, false, null, GuestIpType.Virtualized, - useLocalStorage, true, null); - _serviceOffering.setUniqueName("Cloud.com-ConsoleProxy"); - _serviceOffering = _offeringDao.persistSystemServiceOffering(_serviceOffering); - _template = _templateDao.findConsoleProxyTemplate(); - if (_template == null) { - throw new ConfigurationException( - "Unable to find the template for console proxy VMs"); - } - - _capacityScanScheduler.scheduleAtFixedRate(getCapacityScanTask(), - STARTUP_DELAY, _capacityScanInterval, TimeUnit.MILLISECONDS); - - if (s_logger.isInfoEnabled()) - s_logger.info("Console Proxy Manager is configured."); - return true; - } - - protected ConsoleProxyManagerImpl() { - } - - @Override - public Command cleanup(ConsoleProxyVO vm, String vmName) { - if (vmName != null) { - return new StopCommand(vm, vmName, VirtualMachineName.getVnet(vmName)); - } else if (vm != null) { - ConsoleProxyVO vo = vm; - return new StopCommand(vo, null); - } else { - throw new CloudRuntimeException("Shouldn't even be here!"); - } - } - - @Override - public void completeStartCommand(ConsoleProxyVO vm) { - _consoleProxyDao.updateIf(vm, Event.AgentReportRunning, vm.getHostId()); - } - - @Override - public void completeStopCommand(ConsoleProxyVO vm) { - completeStopCommand(vm, Event.AgentReportStopped); - } - - @DB - protected void completeStopCommand(ConsoleProxyVO proxy, Event ev) { - Transaction txn = Transaction.currentTxn(); - try { - txn.start(); - String privateIpAddress = proxy.getPrivateIpAddress(); - if (privateIpAddress != null) { - proxy.setPrivateIpAddress(null); - freePrivateIpAddress(privateIpAddress, proxy.getDataCenterId(), proxy.getId()); - } - String guestIpAddress = proxy.getGuestIpAddress(); - if (guestIpAddress != null) { - proxy.setGuestIpAddress(null); - _dcDao.releaseLinkLocalPrivateIpAddress(guestIpAddress, proxy.getDataCenterId(), proxy.getId()); - } - - if (!_consoleProxyDao.updateIf(proxy, ev, null)) { - s_logger.debug("Unable to update the console proxy"); - return; - } - txn.commit(); - } catch (Exception e) { - s_logger.error("Unable to complete stop command due to ", e); - } - - if (_storageMgr.unshare(proxy, null) == null) { - s_logger.warn("Unable to set share to false for " + proxy.getId()); - } - } - - @Override - public ConsoleProxyVO get(long id) { - return _consoleProxyDao.findById(id); - } - - @Override - public Long convertToId(String vmName) { - if (!VirtualMachineName.isValidConsoleProxyName(vmName, _instance)) { - return null; - } - return VirtualMachineName.getConsoleProxyId(vmName); - } - - @Override - public boolean stopProxy(long proxyVmId, long startEventId) { - - AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor(); - if (asyncExecutor != null) { - AsyncJobVO job = asyncExecutor.getJob(); - - if (s_logger.isInfoEnabled()) - s_logger.info("Stop console proxy " + proxyVmId + ", update async job-" + job.getId()); - _asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", proxyVmId); - } - - ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId); - if (proxy == null) { - if (s_logger.isDebugEnabled()) - s_logger.debug("Stopping console proxy failed: console proxy " + proxyVmId + " no longer exists"); - return false; - } -/* - saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, - EventTypes.EVENT_PROXY_STOP, "Stopping console proxy with Id: " - + proxyVmId, startEventId); -*/ - try { - return stop(proxy, startEventId); - } catch (AgentUnavailableException e) { - if (s_logger.isDebugEnabled()) - s_logger.debug("Stopping console proxy " + proxy.getName() + " faled : exception " + e.toString()); - return false; - } - } - - @Override - public boolean rebootProxy(long proxyVmId, long startEventId) { - AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor(); - if (asyncExecutor != null) { - AsyncJobVO job = asyncExecutor.getJob(); - - if (s_logger.isInfoEnabled()) - s_logger.info("Reboot console proxy " + proxyVmId + ", update async job-" + job.getId()); - _asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", proxyVmId); - } - - final ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId); - - if (proxy == null || proxy.getState() == State.Destroyed) { - return false; - } - -/* - saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, - EventTypes.EVENT_PROXY_REBOOT, - "Rebooting console proxy with Id: " + proxyVmId, startEventId); -*/ - if (proxy.getState() == State.Running && proxy.getHostId() != null) { - final RebootCommand cmd = new RebootCommand(proxy.getInstanceName()); - final Answer answer = _agentMgr.easySend(proxy.getHostId(), cmd); - - if (answer != null) { - if (s_logger.isDebugEnabled()) - s_logger.debug("Successfully reboot console proxy " + proxy.getName()); - - SubscriptionMgr.getInstance().notifySubscribers( - ConsoleProxyManager.ALERT_SUBJECT, - this, - new ConsoleProxyAlertEventArgs( - ConsoleProxyAlertEventArgs.PROXY_REBOOTED, - proxy.getDataCenterId(), proxy.getId(), proxy, - null) - ); - - final EventVO event = new EventVO(); - event.setUserId(User.UID_SYSTEM); - event.setAccountId(Account.ACCOUNT_ID_SYSTEM); - event.setType(EventTypes.EVENT_PROXY_REBOOT); - event.setLevel(EventVO.LEVEL_INFO); - event.setStartId(startEventId); - event.setDescription("Console proxy rebooted - " + proxy.getName()); - _eventDao.persist(event); - return true; - } else { - if (s_logger.isDebugEnabled()) - s_logger.debug("failed to reboot console proxy : " + proxy.getName()); - - final EventVO event = new EventVO(); - event.setUserId(User.UID_SYSTEM); - event.setAccountId(Account.ACCOUNT_ID_SYSTEM); - event.setType(EventTypes.EVENT_PROXY_REBOOT); - event.setLevel(EventVO.LEVEL_ERROR); - event.setStartId(startEventId); - event.setDescription("Rebooting console proxy failed - " + proxy.getName()); - _eventDao.persist(event); - return false; - } - } else { - return startProxy(proxyVmId, 0) != null; - } - } - - @Override - public boolean destroy(ConsoleProxyVO proxy) throws AgentUnavailableException { - return destroyProxy(proxy.getId(), 0); - } - - @Override - @DB - public boolean destroyProxy(long vmId, long startEventId) { - AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor(); - if (asyncExecutor != null) { - AsyncJobVO job = asyncExecutor.getJob(); - - if (s_logger.isInfoEnabled()) - s_logger.info("Destroy console proxy " + vmId + ", update async job-" + job.getId()); - _asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", vmId); - } - - ConsoleProxyVO vm = _consoleProxyDao.findById(vmId); - if (vm == null || vm.getState() == State.Destroyed) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Unable to find vm or vm is destroyed: " + vmId); - } - return true; - } -/* - saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, - EventTypes.EVENT_PROXY_DESTROY, - "Destroying console proxy with Id: " + vmId, startEventId); -*/ - if (s_logger.isDebugEnabled()) { - s_logger.debug("Destroying console proxy vm " + vmId); - } - - if (!_consoleProxyDao.updateIf(vm, Event.DestroyRequested, null)) { - s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vmId); - return false; - } - - Transaction txn = Transaction.currentTxn(); - List vols = null; - try { - vols = _volsDao.findByInstance(vmId); - if (vols.size() != 0) { - _storageMgr.destroy(vm, vols); - } - - return true; - } finally { - try { - txn.start(); - // release critical system resources used by the VM before we - // delete them - if (vm.getPublicIpAddress() != null) - freePublicIpAddress(vm.getPublicIpAddress(), vm.getDataCenterId(), vm.getPodId()); - vm.setPublicIpAddress(null); - - _consoleProxyDao.remove(vm.getId()); - - final EventVO event = new EventVO(); - event.setUserId(User.UID_SYSTEM); - event.setAccountId(Account.ACCOUNT_ID_SYSTEM); - event.setType(EventTypes.EVENT_PROXY_DESTROY); - event.setLevel(EventVO.LEVEL_INFO); - event.setStartId(startEventId); - event.setDescription("Console proxy destroyed - " - + vm.getName()); - _eventDao.persist(event); - - txn.commit(); - } catch (Exception e) { - s_logger.error("Caught this error: ", e); - txn.rollback(); - return false; - } finally { - s_logger.debug("console proxy vm is destroyed : " - + vm.getName()); - } - } - } - - @DB - public boolean destroyProxyDBOnly(long vmId) { - Transaction txn = Transaction.currentTxn(); - try { - txn.start(); - _volsDao.deleteVolumesByInstance(vmId); - - ConsoleProxyVO proxy = _consoleProxyDao.findById(vmId); - if (proxy != null) { - if (proxy.getPublicIpAddress() != null) - freePublicIpAddress(proxy.getPublicIpAddress(), proxy.getDataCenterId(), proxy.getPodId()); - - _consoleProxyDao.remove(vmId); - - final EventVO event = new EventVO(); - event.setUserId(User.UID_SYSTEM); - event.setAccountId(Account.ACCOUNT_ID_SYSTEM); - event.setType(EventTypes.EVENT_PROXY_DESTROY); - event.setLevel(EventVO.LEVEL_INFO); - event.setDescription("Console proxy destroyed - " - + proxy.getName()); - _eventDao.persist(event); - } - - txn.commit(); - return true; - } catch (Exception e) { - s_logger.error("Caught this error: ", e); - txn.rollback(); - return false; - } finally { - s_logger.debug("console proxy vm is destroyed from DB : " + vmId); - } - } - - @Override - public boolean stop(ConsoleProxyVO proxy, long startEventId) - throws AgentUnavailableException { - if (!_consoleProxyDao.updateIf(proxy, Event.StopRequested, proxy.getHostId())) { - s_logger.debug("Unable to stop console proxy: " + proxy.toString()); - return false; - } - - // IPAddressVO ip = _ipAddressDao.findById(proxy.getPublicIpAddress()); - // VlanVO vlan = _vlanDao.findById(new Long(ip.getVlanDbId())); - - GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(proxy.getId())); - try { - if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { - try { - StopCommand cmd = new StopCommand(proxy, true, Integer.toString(_consoleProxyPort), - Integer.toString(_consoleProxyUrlPort), proxy.getPublicIpAddress()); - try { - Long proxyHostId = proxy.getHostId(); - if (proxyHostId == null) { - s_logger.debug("Unable to stop due to proxy " + proxy.getId() - + " as host is no longer available, proxy may already have been stopped"); - return false; - } - StopAnswer answer = (StopAnswer) _agentMgr.send(proxyHostId, cmd); - if (answer == null || !answer.getResult()) { - s_logger.debug("Unable to stop due to " + (answer == null ? "answer is null" : answer.getDetails())); - - final EventVO event = new EventVO(); - event.setUserId(User.UID_SYSTEM); - event.setAccountId(Account.ACCOUNT_ID_SYSTEM); - event.setType(EventTypes.EVENT_PROXY_STOP); - event.setLevel(EventVO.LEVEL_ERROR); - event.setStartId(startEventId); - event.setDescription("Stopping console proxy failed due to negative answer from agent - " + proxy.getName()); - _eventDao.persist(event); - return false; - } - completeStopCommand(proxy, Event.OperationSucceeded); - - SubscriptionMgr.getInstance().notifySubscribers( - ConsoleProxyManager.ALERT_SUBJECT, - this, - new ConsoleProxyAlertEventArgs( - ConsoleProxyAlertEventArgs.PROXY_DOWN, - proxy.getDataCenterId(), proxy.getId(), - proxy, null)); - - final EventVO event = new EventVO(); - event.setUserId(User.UID_SYSTEM); - event.setAccountId(Account.ACCOUNT_ID_SYSTEM); - event.setType(EventTypes.EVENT_PROXY_STOP); - event.setLevel(EventVO.LEVEL_INFO); - event.setStartId(startEventId); - event.setDescription("Console proxy stopped - " + proxy.getName()); - _eventDao.persist(event); - return true; - } catch (OperationTimedoutException e) { - final EventVO event = new EventVO(); - event.setUserId(User.UID_SYSTEM); - event.setAccountId(Account.ACCOUNT_ID_SYSTEM); - event.setType(EventTypes.EVENT_PROXY_STOP); - event.setLevel(EventVO.LEVEL_ERROR); - event.setStartId(startEventId); - event.setDescription("Stopping console proxy failed due to operation time out - " + proxy.getName()); - _eventDao.persist(event); - throw new AgentUnavailableException(proxy.getHostId()); - } - } finally { - proxyLock.unlock(); - } - } else { - s_logger.debug("Unable to acquire console proxy lock : " + proxy.toString()); - return false; - } - } finally { - proxyLock.releaseRef(); - } - } - - @Override - public boolean migrate(ConsoleProxyVO proxy, HostVO host) { - HostVO fromHost = _hostDao.findById(proxy.getId()); - - if (!_consoleProxyDao.updateIf(proxy, Event.MigrationRequested, proxy.getHostId())) { - s_logger.debug("State for " + proxy.toString() + " has changed so migration can not take place."); - return false; - } - - MigrateCommand cmd = new MigrateCommand(proxy.getInstanceName(), host.getPrivateIpAddress(), false); - Answer answer = _agentMgr.easySend(fromHost.getId(), cmd); - if (answer == null) { - return false; - } - - _storageMgr.unshare(proxy, fromHost); - - return true; - } - - @Override - public boolean completeMigration(ConsoleProxyVO proxy, HostVO host) - throws AgentUnavailableException, OperationTimedoutException { - - CheckVirtualMachineCommand cvm = new CheckVirtualMachineCommand(proxy.getInstanceName()); - CheckVirtualMachineAnswer answer = (CheckVirtualMachineAnswer) _agentMgr.send(host.getId(), cvm); - if (!answer.getResult()) { - s_logger.debug("Unable to complete migration for " + proxy.getId()); - _consoleProxyDao.updateIf(proxy, Event.AgentReportStopped, null); - return false; - } - - State state = answer.getState(); - if (state == State.Stopped) { - s_logger.warn("Unable to complete migration as we can not detect it on " + host.getId()); - _consoleProxyDao.updateIf(proxy, Event.AgentReportStopped, null); - return false; - } - - _consoleProxyDao.updateIf(proxy, Event.OperationSucceeded, host.getId()); - return true; - } - - @Override - public HostVO prepareForMigration(ConsoleProxyVO proxy) - throws StorageUnavailableException { - - VMTemplateVO template = _templateDao.findById(proxy.getTemplateId()); - long routerId = proxy.getId(); - boolean mirroredVols = proxy.isMirroredVols(); - DataCenterVO dc = _dcDao.findById(proxy.getDataCenterId()); - HostPodVO pod = _podDao.findById(proxy.getPodId()); - List sps = _storageMgr.getStoragePoolsForVm(proxy.getId()); - StoragePoolVO sp = sps.get(0); // FIXME - - List vols = _volsDao.findCreatedByInstance(routerId); - - String[] storageIps = new String[2]; - VolumeVO vol = vols.get(0); - storageIps[0] = vol.getHostIp(); - if (mirroredVols && (vols.size() == 2)) { - storageIps[1] = vols.get(1).getHostIp(); - } - - PrepareForMigrationCommand cmd = new PrepareForMigrationCommand(proxy.getName(), null, storageIps, vols, mirroredVols); - - HostVO routingHost = null; - HashSet avoid = new HashSet(); - - HostVO fromHost = _hostDao.findById(proxy.getHostId()); - if (fromHost.getClusterId() == null) { - s_logger.debug("The host is not in a cluster"); - return null; - } - avoid.add(fromHost); - - while ((routingHost = (HostVO) _agentMgr.findHost(Host.Type.Routing, dc, pod, sp, _serviceOffering, template, proxy, fromHost, avoid)) != null) { - avoid.add(routingHost); - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Trying to migrate router to host " + routingHost.getName()); - } - - if (!_storageMgr.share(proxy, vols, routingHost, false)) { - s_logger.warn("Can not share " + proxy.getName()); - throw new StorageUnavailableException(vol.getPoolId()); - } - - Answer answer = _agentMgr.easySend(routingHost.getId(), cmd); - if (answer != null && answer.getResult()) { - return routingHost; - } - _storageMgr.unshare(proxy, vols, routingHost); - } - - return null; - } - - private String getCapacityScanLockName() { - // to improve security, it may be better to return a unique mashed - // name(for example MD5 hashed) - return "consoleproxy.capacity.scan"; - } - - private String getAllocProxyLockName() { - // to improve security, it may be better to return a unique mashed - // name(for example MD5 hashed) - return "consoleproxy.alloc"; - } - - private String getProxyLockName(long id) { - return "consoleproxy." + id; - } - - private Long saveStartedEvent(Long userId, Long accountId, String type, - String description, long startEventId) { - EventVO event = new EventVO(); - event.setUserId(userId); - event.setAccountId(accountId); - event.setType(type); - event.setState(EventState.Started); - event.setDescription(description); - event.setStartId(startEventId); - event = _eventDao.persist(event); - if (event != null) - return event.getId(); - return null; - } +public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMachineManager, AgentHook { + private static final Logger s_logger = Logger.getLogger(ConsoleProxyManagerImpl.class); + + private static final int DEFAULT_FIND_HOST_RETRY_COUNT = 2; + private static final int DEFAULT_CAPACITY_SCAN_INTERVAL = 30000; // 30 + // seconds + private static final int EXECUTOR_SHUTDOWN_TIMEOUT = 1000; // 1 second + + private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION = 3; // 3 + // seconds + private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC = 180; // 3 + // minutes + + private static final int API_WAIT_TIMEOUT = 5000; // 5 seconds (in + // milliseconds) + private static final int STARTUP_DELAY = 60000; // 60 seconds + + private int _consoleProxyPort = ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT; + private int _consoleProxyUrlPort = ConsoleProxyManager.DEFAULT_PROXY_URL_PORT; + + private String _mgmt_host; + private int _mgmt_port = 8250; + + private String _name; + private Adapters _consoleProxyAllocators; + + @Inject + private ConsoleProxyDao _consoleProxyDao; + @Inject + private DataCenterDao _dcDao; + @Inject + private VlanDao _vlanDao; + @Inject + private VMTemplateDao _templateDao; + @Inject + private IPAddressDao _ipAddressDao; + @Inject + private VolumeDao _volsDao; + @Inject + private HostPodDao _podDao; + @Inject + private HostDao _hostDao; + @Inject + private ConfigurationDao _configDao; + + @Inject + private VMInstanceDao _instanceDao; + @Inject + private AccountDao _accountDao; + + @Inject + private VMTemplateHostDao _vmTemplateHostDao; + + @Inject + private AgentManager _agentMgr; + @Inject + private StorageManager _storageMgr; + @Inject + private HighAvailabilityManager _haMgr; + @Inject + private EventDao _eventDao; + @Inject + ServiceOfferingDao _offeringDao; + @Inject + private IpAddrAllocator _IpAllocator; + + private ConsoleProxyListener _listener; + + private ServiceOfferingVO _serviceOffering; + private VMTemplateVO _template; + + @Inject + private AsyncJobManager _asyncMgr; + + private final ScheduledExecutorService _capacityScanScheduler = Executors.newScheduledThreadPool(1, new NamedThreadFactory("CP-Scan")); + private final ExecutorService _requestHandlerScheduler = Executors.newCachedThreadPool(new NamedThreadFactory("Request-handler")); + + private long _capacityScanInterval = DEFAULT_CAPACITY_SCAN_INTERVAL; + private int _capacityPerProxy = ConsoleProxyManager.DEFAULT_PROXY_CAPACITY; + private int _standbyCapacity = ConsoleProxyManager.DEFAULT_STANDBY_CAPACITY; + + private int _proxyRamSize; + private int _find_host_retry = DEFAULT_FIND_HOST_RETRY_COUNT; + private int _ssh_retry; + private int _ssh_sleep; + private boolean _use_lvm; + private boolean _use_storage_vm; + + private String _domain; + private String _instance; + + // private String _privateNetmask; + private int _proxyCmdPort = DEFAULT_PROXY_CMD_PORT; + private int _proxySessionTimeoutValue = DEFAULT_PROXY_SESSION_TIMEOUT; + private boolean _sslEnabled = false; + + private final GlobalLock _capacityScanLock = GlobalLock.getInternLock(getCapacityScanLockName()); + private final GlobalLock _allocProxyLock = GlobalLock.getInternLock(getAllocProxyLockName()); + + @Override + public ConsoleProxyInfo assignProxy(final long dataCenterId, final long vmId) { + + final Pair result = new Pair(this, null); + + _requestHandlerScheduler.execute(new Runnable() { + @Override + public void run() { + Transaction txn = Transaction.open(Transaction.CLOUD_DB); + try { + ConsoleProxyVO proxy = doAssignProxy(dataCenterId, vmId); + synchronized (result) { + result.second(proxy); + result.notifyAll(); + } + } catch (Throwable e) { + s_logger.warn("Unexpected exception " + e.getMessage(), e); + } finally { + StackMaid.current().exitCleanup(); + txn.close(); + } + } + }); + + synchronized (result) { + try { + result.wait(API_WAIT_TIMEOUT); + } catch (InterruptedException e) { + s_logger.info("Waiting for console proxy assignment is interrupted"); + } + } + + ConsoleProxyVO proxy = result.second(); + if (proxy == null) + return null; + + return new ConsoleProxyInfo(proxy.isSslEnabled(), proxy.getPublicIpAddress(), _consoleProxyPort, proxy.getPort()); + } + + public ConsoleProxyVO doAssignProxy(long dataCenterId, long vmId) { + ConsoleProxyVO proxy = null; + VMInstanceVO vm = _instanceDao.findById(vmId); + if (vm == null) { + s_logger.warn("VM " + vmId + " no longer exists, return a null proxy for vm:" + vmId); + return null; + } + + Boolean[] proxyFromStoppedPool = new Boolean[1]; + if (_allocProxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { + try { + proxy = getOrAllocProxyResource(dataCenterId, vmId, proxyFromStoppedPool); + } finally { + _allocProxyLock.unlock(); + } + } else { + s_logger.error("Unable to acquire synchronization lock to get/allocate proxy resource for vm :" + vmId + + ". Previous console proxy allocation is taking too long"); + } + + if (proxy == null) { + s_logger.warn("Unable to find or allocate console proxy resource"); + return null; + } + + long proxyVmId = proxy.getId(); + GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(proxyVmId)); + try { + if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { + try { + proxy = startProxy(proxyVmId, 0); + + if (proxy == null) { + // + // We had a situation with multi-pod configuration, + // where + // storage allocation of the console proxy VM may + // succeed, but later-on starting of it + // may fail because of running out of computing resource + // (CPU/memory). We + // currently don't support moving storage to another pod + // on the fly, to deal + // with the situation we will destroy this proxy VM and + // let it the whole proxy VM + // creation process re-start again, by hoping that new + // storage and computing + // resource may be allocated and assigned in another pod + // + if (s_logger.isInfoEnabled()) + s_logger.info("Unable to start console proxy, proxy vm Id : " + proxyVmId + " will recycle it and restart a new one"); + destroyProxy(proxyVmId, 0); + return null; + } else { + if (s_logger.isTraceEnabled()) + s_logger.trace("Console proxy " + proxy.getName() + " is started"); + + // if it is a new assignment or a changed assignment, + // update the + // record + if (vm.getProxyId() == null || vm.getProxyId().longValue() != proxy.getId()) + _instanceDao.updateProxyId(vmId, proxy.getId(), DateUtil.currentGMTTime()); + + proxy.setSslEnabled(_sslEnabled); + if (_sslEnabled) + proxy.setPort(443); + else + proxy.setPort(80); + return proxy; + } + } finally { + proxyLock.unlock(); + } + } else { + s_logger.error("Unable to acquire synchronization lock to start console proxy " + proxyVmId + " for vm: " + vmId + + ". It takes too long to start the proxy"); + + return null; + } + } finally { + proxyLock.releaseRef(); + } + } + + private ConsoleProxyVO getOrAllocProxyResource(long dataCenterId, long vmId, Boolean[] proxyFromStoppedPool) { + ConsoleProxyVO proxy = null; + VMInstanceVO vm = this._instanceDao.findById(vmId); + + if (vm != null && vm.getState() != State.Running) { + if (s_logger.isInfoEnabled()) + s_logger.info("Detected that vm : " + vmId + " is not currently at running state, we will fail the proxy assignment for it"); + return null; + } + + if (vm != null && vm.getProxyId() != null) { + proxy = _consoleProxyDao.findById(vm.getProxyId()); + + if (proxy != null) { + if (!isInAssignableState(proxy)) { + if (s_logger.isInfoEnabled()) + s_logger.info("A previous assigned proxy is not assignable now, reassign console proxy for user vm : " + vmId); + proxy = null; + } else { + if (_consoleProxyDao.getProxyActiveLoad(proxy.getId()) < _capacityPerProxy || hasPreviousSession(proxy, vm)) { + if (s_logger.isTraceEnabled()) + s_logger.trace("Assign previous allocated console proxy for user vm : " + vmId); + + if (proxy.getActiveSession() >= _capacityPerProxy) + s_logger.warn("Assign overloaded proxy to user VM as previous session exists, user vm : " + vmId); + } else { + proxy = null; + } + } + } + } + + if (proxy == null) + proxy = assignProxyFromRunningPool(dataCenterId); + + if (proxy == null) { + if (s_logger.isInfoEnabled()) + s_logger.info("No running console proxy is available, check to see if we can bring up a stopped one for data center : " + + dataCenterId); + + proxy = assignProxyFromStoppedPool(dataCenterId); + if (proxy == null) { + if (s_logger.isInfoEnabled()) + s_logger.info("No stopped console proxy is available, need to allocate a new console proxy for data center : " + dataCenterId); + + proxy = startNew(dataCenterId); + } else { + if (s_logger.isInfoEnabled()) + s_logger.info("Found a stopped console proxy, bring it up to running pool. proxy vm id : " + proxy.getId() + ", data center : " + + dataCenterId); + + proxyFromStoppedPool[0] = new Boolean(true); + } + } + + return proxy; + } + + private static boolean isInAssignableState(ConsoleProxyVO proxy) { + // console proxies that are in states of being able to serve user VM + State state = proxy.getState(); + if (state == State.Running || state == State.Starting || state == State.Creating || state == State.Migrating) + return true; + + return false; + } + + private boolean hasPreviousSession(ConsoleProxyVO proxy, VMInstanceVO vm) { + + ConsoleProxyStatus status = null; + try { + GsonBuilder gb = new GsonBuilder(); + gb.setVersion(1.3); + Gson gson = gb.create(); + + byte[] details = proxy.getSessionDetails(); + status = gson.fromJson(details != null ? new String(details, Charset.forName("US-ASCII")) : null, ConsoleProxyStatus.class); + } catch (Throwable e) { + s_logger.warn("Unable to parse proxy session details : " + proxy.getSessionDetails()); + } + + if (status != null && status.getConnections() != null) { + ConsoleProxyConnectionInfo[] connections = status.getConnections(); + for (int i = 0; i < connections.length; i++) { + long taggedVmId = 0; + if (connections[i].tag != null) { + try { + taggedVmId = Long.parseLong(connections[i].tag); + } catch (NumberFormatException e) { + s_logger.warn("Unable to parse console proxy connection info passed through tag: " + connections[i].tag, e); + } + } + if (taggedVmId == vm.getId()) + return true; + } + + // + // even if we are not in the list, it may because we haven't + // received load-update yet + // wait until session time + // + if (DateUtil.currentGMTTime().getTime() - vm.getProxyAssignTime().getTime() < _proxySessionTimeoutValue) + return true; + + return false; + } else { + s_logger.error("No proxy load info on an overloaded proxy ?"); + return false; + } + } + + @Override + public ConsoleProxyVO startProxy(long proxyVmId, long startEventId) { + try { + return start(proxyVmId, startEventId); + } catch (StorageUnavailableException e) { + s_logger.warn("Exception while trying to start console proxy", e); + return null; + } catch (InsufficientCapacityException e) { + s_logger.warn("Exception while trying to start console proxy", e); + return null; + } catch (ConcurrentOperationException e) { + s_logger.warn("Exception while trying to start console proxy", e); + return null; + } + } + + @Override + @DB + public ConsoleProxyVO start(long proxyId, long startEventId) throws StorageUnavailableException, InsufficientCapacityException, + ConcurrentOperationException { + + AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor(); + if (asyncExecutor != null) { + AsyncJobVO job = asyncExecutor.getJob(); + + if (s_logger.isInfoEnabled()) + s_logger.info("Start console proxy " + proxyId + ", update async job-" + job.getId()); + _asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", proxyId); + } + + ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyId); + if (proxy == null || proxy.getRemoved() != null) { + s_logger.debug("proxy is not found: " + proxyId); + return null; + } + /* + * // don't insert event here, it may be called multiple times! + * saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, + * EventTypes.EVENT_PROXY_START, "Starting console proxy with Id: " + + * proxyId, startEventId); + */ + + if (s_logger.isTraceEnabled()) { + s_logger.trace("Starting console proxy if it is not started, proxy vm id : " + proxyId); + } + + for (int i = 0; i < 2; i++) { + + State state = proxy.getState(); + + if (state == State.Starting /* || state == State.Migrating */) { + if (s_logger.isDebugEnabled()) + s_logger.debug("Waiting console proxy to be ready, proxy vm id : " + proxyId + " proxy VM state : " + state.toString()); + + if (proxy.getPrivateIpAddress() == null || connect(proxy.getPrivateIpAddress(), _proxyCmdPort) != null) { + if (proxy.getPrivateIpAddress() == null) + s_logger.warn("Retruning a proxy that is being started but private IP has not been allocated yet, proxy vm id : " + proxyId); + else + s_logger.warn("Waiting console proxy to be ready timed out, proxy vm id : " + proxyId); + + // TODO, it is very tricky here, if the startup process + // takes too long and it timed out here, + // we may give back a proxy that is not fully ready for + // functioning + } + return proxy; + } + + if (state == State.Running) { + if (s_logger.isTraceEnabled()) + s_logger.trace("Console proxy is already started: " + proxy.getName()); + return proxy; + } + + DataCenterVO dc = _dcDao.findById(proxy.getDataCenterId()); + HostPodVO pod = _podDao.findById(proxy.getPodId()); + List sps = _storageMgr.getStoragePoolsForVm(proxy.getId()); + StoragePoolVO sp = sps.get(0); // FIXME + + HashSet avoid = new HashSet(); + HostVO routingHost = (HostVO) _agentMgr.findHost(Host.Type.Routing, dc, pod, sp, _serviceOffering, _template, proxy, null, avoid); + + if (routingHost == null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Unable to find a routing host for " + proxy.toString()); + continue; + } + } + // to ensure atomic state transition to Starting state + if (!_consoleProxyDao.updateIf(proxy, Event.StartRequested, routingHost.getId())) { + if (s_logger.isDebugEnabled()) { + ConsoleProxyVO temp = _consoleProxyDao.findById(proxyId); + s_logger.debug("Unable to start console proxy " + proxy.getName() + " because it is not in a startable state : " + + ((temp != null) ? temp.getState().toString() : "null")); + } + continue; + } + + try { + Answer answer = null; + int retry = _find_host_retry; + + // Console proxy VM will be running at routing hosts as routing + // hosts have public access to outside network + do { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Trying to start console proxy on host " + routingHost.getName()); + } + + String privateIpAddress = allocPrivateIpAddress(proxy.getDataCenterId(), routingHost.getPodId(), proxy.getId(), + proxy.getPrivateMacAddress()); + if (privateIpAddress == null && (_IpAllocator != null && !_IpAllocator.exteralIpAddressAllocatorEnabled())) { + s_logger.debug("Not enough ip addresses in " + routingHost.getPodId()); + avoid.add(routingHost); + continue; + } + + proxy.setPrivateIpAddress(privateIpAddress); + String guestIpAddress = _dcDao.allocateLinkLocalPrivateIpAddress(proxy.getDataCenterId(), routingHost.getPodId(), proxy.getId()); + proxy.setGuestIpAddress(guestIpAddress); + + _consoleProxyDao.updateIf(proxy, Event.OperationRetry, routingHost.getId()); + proxy = _consoleProxyDao.findById(proxy.getId()); + + List vols = _storageMgr.prepare(proxy, routingHost); + if (vols == null) { + s_logger.debug("Unable to prepare storage for " + routingHost); + avoid.add(routingHost); + continue; + } + + // _storageMgr.share(proxy, vols, null, true); + + // carry the console proxy port info over so that we don't + // need to configure agent on this + StartConsoleProxyCommand cmdStart = new StartConsoleProxyCommand(_proxyCmdPort, proxy, proxy.getName(), "", vols, + Integer.toString(_consoleProxyPort), Integer.toString(_consoleProxyUrlPort), _mgmt_host, _mgmt_port, _sslEnabled); + + if (s_logger.isDebugEnabled()) + s_logger.debug("Sending start command for console proxy " + proxy.getName() + " to " + routingHost.getName()); + try { + answer = _agentMgr.send(routingHost.getId(), cmdStart); + + s_logger.debug("StartConsoleProxy Answer: " + (answer != null ? answer : "null")); + + if (s_logger.isDebugEnabled()) + s_logger.debug("Received answer on starting console proxy " + proxy.getName() + " on " + routingHost.getName()); + + if (answer != null && answer.getResult()) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Console proxy " + proxy.getName() + " started on " + routingHost.getName()); + } + + if (answer instanceof StartConsoleProxyAnswer) { + StartConsoleProxyAnswer rAnswer = (StartConsoleProxyAnswer) answer; + if (rAnswer.getPrivateIpAddress() != null) { + proxy.setPrivateIpAddress(rAnswer.getPrivateIpAddress()); + } + if (rAnswer.getPrivateMacAddress() != null) { + proxy.setPrivateMacAddress(rAnswer.getPrivateMacAddress()); + } + } + + final EventVO event = new EventVO(); + event.setUserId(User.UID_SYSTEM); + event.setAccountId(Account.ACCOUNT_ID_SYSTEM); + event.setType(EventTypes.EVENT_PROXY_START); + event.setLevel(EventVO.LEVEL_INFO); + event.setStartId(startEventId); + event.setDescription("Console proxy started - " + proxy.getName()); + _eventDao.persist(event); + break; + } + s_logger.debug("Unable to start " + proxy.toString() + " on host " + routingHost.toString() + " due to " + + answer.getDetails()); + } catch (OperationTimedoutException e) { + if (e.isActive()) { + s_logger.debug("Unable to start vm " + proxy.getName() + + " due to operation timed out and it is active so scheduling a restart."); + _haMgr.scheduleRestart(proxy, true); + return null; + } + } catch (AgentUnavailableException e) { + s_logger.debug("Agent " + routingHost.toString() + " was unavailable to start VM " + proxy.getName()); + } + + avoid.add(routingHost); + proxy.setPrivateIpAddress(null); + freePrivateIpAddress(privateIpAddress, proxy.getDataCenterId(), proxy.getId()); + proxy.setGuestIpAddress(null); + _dcDao.releaseLinkLocalPrivateIpAddress(guestIpAddress, proxy.getDataCenterId(), proxy.getId()); + _storageMgr.unshare(proxy, vols, routingHost); + } while (--retry > 0 + && (routingHost = (HostVO) _agentMgr + .findHost(Host.Type.Routing, dc, pod, sp, _serviceOffering, _template, proxy, null, avoid)) != null); + if (routingHost == null || retry <= 0) { + + SubscriptionMgr.getInstance().notifySubscribers( + ConsoleProxyManager.ALERT_SUBJECT, + this, + new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_START_FAILURE, proxy.getDataCenterId(), proxy.getId(), + proxy, "Unable to find a routing host to run")); + + final EventVO event = new EventVO(); + event.setUserId(User.UID_SYSTEM); + event.setAccountId(Account.ACCOUNT_ID_SYSTEM); + event.setType(EventTypes.EVENT_PROXY_START); + event.setLevel(EventVO.LEVEL_ERROR); + event.setStartId(startEventId); + event.setDescription("Starting console proxy failed due to unable to find a host - " + proxy.getName()); + _eventDao.persist(event); + throw new ExecutionException("Couldn't find a routingHost to run console proxy"); + } + + _consoleProxyDao.updateIf(proxy, Event.OperationSucceeded, routingHost.getId()); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Console proxy is now started, vm id : " + proxy.getId()); + } + + // If starting the console proxy failed due to the external + // firewall not being reachable, send an alert. + if (answer != null && answer.getDetails() != null && answer.getDetails().equals("firewall")) { + + SubscriptionMgr.getInstance().notifySubscribers( + ConsoleProxyManager.ALERT_SUBJECT, + this, + new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_FIREWALL_ALERT, proxy.getDataCenterId(), proxy.getId(), + proxy, null)); + } + + SubscriptionMgr.getInstance().notifySubscribers(ConsoleProxyManager.ALERT_SUBJECT, this, + new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_UP, proxy.getDataCenterId(), proxy.getId(), proxy, null)); + + return proxy; + } catch (Throwable thr) { + s_logger.warn("Unexpected exception: ", thr); + + SubscriptionMgr.getInstance().notifySubscribers( + ConsoleProxyManager.ALERT_SUBJECT, + this, + new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_START_FAILURE, proxy.getDataCenterId(), proxy.getId(), proxy, + "Unexpected exception: " + thr.getMessage())); + + /* + * final EventVO event = new EventVO(); + * event.setUserId(User.UID_SYSTEM); + * event.setAccountId(Account.ACCOUNT_ID_SYSTEM); + * event.setType(EventTypes.EVENT_PROXY_START); + * event.setLevel(EventVO.LEVEL_ERROR); + * event.setStartId(startEventId); event.setDescription( + * "Starting console proxy failed due to unhandled exception - " + * + proxy.getName()); _eventDao.persist(event); + */ + + Transaction txn = Transaction.currentTxn(); + try { + txn.start(); + String privateIpAddress = proxy.getPrivateIpAddress(); + if (privateIpAddress != null) { + proxy.setPrivateIpAddress(null); + freePrivateIpAddress(privateIpAddress, proxy.getDataCenterId(), proxy.getId()); + } + + _consoleProxyDao.updateIf(proxy, Event.OperationFailed, null); + txn.commit(); + } catch (Exception e) { + s_logger.error("Caught exception during error recovery"); + } + + if (thr instanceof StorageUnavailableException) { + throw (StorageUnavailableException) thr; + } else if (thr instanceof ConcurrentOperationException) { + throw (ConcurrentOperationException) thr; + } else if (thr instanceof ExecutionException) { + s_logger.error("Error while starting console proxy due to " + thr.getMessage()); + } else { + s_logger.error("Error while starting console proxy ", thr); + } + return null; + } + } + + s_logger.warn("Starting console proxy encounters non-startable situation"); + return null; + } + + public ConsoleProxyVO assignProxyFromRunningPool(long dataCenterId) { + + if (s_logger.isTraceEnabled()) + s_logger.trace("Assign console proxy from running pool for request from data center : " + dataCenterId); + + ConsoleProxyAllocator allocator = getCurrentAllocator(); + assert (allocator != null); + List runningList = _consoleProxyDao.getProxyListInStates(dataCenterId, State.Running); + if (runningList != null && runningList.size() > 0) { + if (s_logger.isTraceEnabled()) { + s_logger.trace("Running proxy pool size : " + runningList.size()); + for (ConsoleProxyVO proxy : runningList) + s_logger.trace("Running proxy instance : " + proxy.getName()); + } + + List> l = _consoleProxyDao.getProxyLoadMatrix(); + Map loadInfo = new HashMap(); + if (l != null) { + for (Pair p : l) { + loadInfo.put(p.first(), p.second()); + + if (s_logger.isTraceEnabled()) { + s_logger.trace("Running proxy instance allocation load { proxy id : " + p.first() + ", load : " + p.second() + "}"); + } + } + } + return allocator.allocProxy(runningList, loadInfo, dataCenterId); + } else { + if (s_logger.isTraceEnabled()) + s_logger.trace("Empty running proxy pool for now in data center : " + dataCenterId); + } + return null; + } + + public ConsoleProxyVO assignProxyFromStoppedPool(long dataCenterId) { + List l = _consoleProxyDao.getProxyListInStates(dataCenterId, State.Creating, State.Starting, State.Stopped, State.Migrating); + if (l != null && l.size() > 0) + return l.get(0); + + return null; + } + + public ConsoleProxyVO startNewConsoleProxy(long dataCenterId) { + if (s_logger.isDebugEnabled()) + s_logger.debug("Assign console proxy from a newly started instance for request from data center : " + dataCenterId); + + Map context = createProxyInstance(dataCenterId); + + long proxyVmId = (Long) context.get("proxyVmId"); + if (proxyVmId == 0) { + if (s_logger.isTraceEnabled()) + s_logger.trace("Creating proxy instance failed, data center id : " + dataCenterId); + + // release critical system resource on failure + if (context.get("publicIpAddress") != null) + freePublicIpAddress((String) context.get("publicIpAddress"), dataCenterId, 0); + + return null; + } + + ConsoleProxyVO proxy = allocProxyStorage(dataCenterId, proxyVmId); + if (proxy != null) { + SubscriptionMgr.getInstance().notifySubscribers(ConsoleProxyManager.ALERT_SUBJECT, this, + new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_CREATED, dataCenterId, proxy.getId(), proxy, null)); + return proxy; + } else { + if (s_logger.isDebugEnabled()) + s_logger.debug("Unable to allocate console proxy storage, remove the console proxy record from DB, proxy id: " + proxyVmId); + + SubscriptionMgr.getInstance().notifySubscribers( + ConsoleProxyManager.ALERT_SUBJECT, + this, + new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_CREATE_FAILURE, dataCenterId, proxyVmId, null, + "Unable to allocate storage")); + + destroyProxyDBOnly(proxyVmId); + } + return null; + } + + public ConsoleProxyVO startNew(long dataCenterId) { + + if (s_logger.isDebugEnabled()) + s_logger.debug("Assign console proxy from a newly started instance for request from data center : " + dataCenterId); + + Map context = createProxyInstance(dataCenterId); + + long proxyVmId = (Long) context.get("proxyVmId"); + if (proxyVmId == 0) { + if (s_logger.isTraceEnabled()) + s_logger.trace("Creating proxy instance failed, data center id : " + dataCenterId); + + // release critical system resource on failure + if (context.get("publicIpAddress") != null) + freePublicIpAddress((String) context.get("publicIpAddress"), dataCenterId, 0); + + return null; + } + + ConsoleProxyVO proxy = allocProxyStorage(dataCenterId, proxyVmId); + if (proxy != null) { + SubscriptionMgr.getInstance().notifySubscribers(ConsoleProxyManager.ALERT_SUBJECT, this, + new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_CREATED, dataCenterId, proxy.getId(), proxy, null)); + return proxy; + } else { + if (s_logger.isDebugEnabled()) + s_logger.debug("Unable to allocate console proxy storage, remove the console proxy record from DB, proxy id: " + proxyVmId); + + SubscriptionMgr.getInstance().notifySubscribers( + ConsoleProxyManager.ALERT_SUBJECT, + this, + new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_CREATE_FAILURE, dataCenterId, proxyVmId, null, + "Unable to allocate storage")); + + destroyProxyDBOnly(proxyVmId); + } + return null; + } + + @DB + protected Map createProxyInstance(long dataCenterId) { + + Map context = new HashMap(); + String publicIpAddress = null; + + Transaction txn = Transaction.currentTxn(); + try { + DataCenterVO dc = _dcDao.findById(dataCenterId); + assert (dc != null); + context.put("dc", dc); + + // this will basically allocate the pod based on data center id as + // we use system user id here + Set avoidPods = new HashSet(); + Pair pod = null; + networkInfo publicIpAndVlan = null; + + // About MAC address allocation + // MAC address used by User VM is inherited from DomR MAC address, + // with the least 16 bits overrided. to avoid + // potential conflicts, domP will mask bit 31 + // + String[] macAddresses = _dcDao.getNextAvailableMacAddressPair(dataCenterId, (1L << 31)); + String privateMacAddress = macAddresses[0]; + String publicMacAddress = macAddresses[1]; + macAddresses = _dcDao.getNextAvailableMacAddressPair(dataCenterId, (1L << 31)); + String guestMacAddress = macAddresses[0]; + while ((pod = _agentMgr.findPod(_template, _serviceOffering, dc, Account.ACCOUNT_ID_SYSTEM, avoidPods)) != null) { + publicIpAndVlan = allocPublicIpAddress(dataCenterId, pod.first().getId(), publicMacAddress); + if (publicIpAndVlan == null) { + s_logger.warn("Unable to allocate public IP address for console proxy vm in data center : " + dataCenterId + ", pod=" + + pod.first().getId()); + avoidPods.add(pod.first().getId()); + } else { + break; + } + } + + if (pod == null || publicIpAndVlan == null) { + s_logger.warn("Unable to allocate pod for console proxy vm in data center : " + dataCenterId); + + context.put("proxyVmId", (long) 0); + return context; + } + + long id = _consoleProxyDao.getNextInSequence(Long.class, "id"); + + context.put("publicIpAddress", publicIpAndVlan._ipAddr); + context.put("pod", pod); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Pod allocated " + pod.first().getName()); + } + + String cidrNetmask = NetUtils.getCidrNetmask(pod.first().getCidrSize()); + + // Find the VLAN ID, VLAN gateway, and VLAN netmask for + // publicIpAddress + publicIpAddress = publicIpAndVlan._ipAddr; + + String vlanGateway = publicIpAndVlan._gateWay; + String vlanNetmask = publicIpAndVlan._netMask; + + txn.start(); + ConsoleProxyVO proxy; + String name = VirtualMachineName.getConsoleProxyName(id, _instance).intern(); + proxy = new ConsoleProxyVO(id, name, guestMacAddress, null, NetUtils.getLinkLocalNetMask(), privateMacAddress, null, cidrNetmask, + _template.getId(), _template.getGuestOSId(), publicMacAddress, publicIpAddress, vlanNetmask, publicIpAndVlan._vlanDbId, + publicIpAndVlan._vlanid, pod.first().getId(), dataCenterId, vlanGateway, null, dc.getDns1(), dc.getDns2(), _domain, + _proxyRamSize, 0); + + proxy.setLastHostId(pod.second()); + proxy = _consoleProxyDao.persist(proxy); + long proxyVmId = proxy.getId(); + + final EventVO event = new EventVO(); + event.setUserId(User.UID_SYSTEM); + event.setAccountId(Account.ACCOUNT_ID_SYSTEM); + event.setType(EventTypes.EVENT_PROXY_CREATE); + event.setLevel(EventVO.LEVEL_INFO); + event.setDescription("New console proxy created - " + proxy.getName()); + _eventDao.persist(event); + txn.commit(); + + context.put("proxyVmId", proxyVmId); + return context; + } catch (Throwable e) { + s_logger.error("Unexpected exception : ", e); + + context.put("proxyVmId", (long) 0); + return context; + } + } + + @DB + protected ConsoleProxyVO allocProxyStorage(long dataCenterId, long proxyVmId) { + ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId); + assert (proxy != null); + + DataCenterVO dc = _dcDao.findById(dataCenterId); + HostPodVO pod = _podDao.findById(proxy.getPodId()); + final AccountVO account = _accountDao.findById(Account.ACCOUNT_ID_SYSTEM); + + try { + List vols = _storageMgr.create(account, proxy, _template, dc, pod, _serviceOffering, null, 0); + if (vols == null) { + s_logger.error("Unable to alloc storage for console proxy"); + return null; + } + + Transaction txn = Transaction.currentTxn(); + txn.start(); + + // update pool id + ConsoleProxyVO vo = _consoleProxyDao.findById(proxy.getId()); + _consoleProxyDao.update(proxy.getId(), vo); + + // kick the state machine + _consoleProxyDao.updateIf(proxy, Event.OperationSucceeded, null); + + txn.commit(); + return proxy; + } catch (StorageUnavailableException e) { + s_logger.error("Unable to alloc storage for console proxy: ", e); + return null; + } catch (ExecutionException e) { + s_logger.error("Unable to alloc storage for console proxy: ", e); + return null; + } + } + + private networkInfo allocPublicIpAddress(long dcId, long podId, String macAddr) { + + if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) { + IpAddrAllocator.IpAddr ip = _IpAllocator.getPublicIpAddress(macAddr, dcId, podId); + networkInfo net = new networkInfo(ip.ipaddr, ip.netMask, ip.gateway, null, "untagged"); + return net; + } + + Pair ipAndVlan = _vlanDao.assignIpAddress(dcId, Account.ACCOUNT_ID_SYSTEM, DomainVO.ROOT_DOMAIN, VlanType.VirtualNetwork, + true); + + if (ipAndVlan == null) { + s_logger.debug("Unable to get public ip address (type=Virtual) for console proxy vm for data center : " + dcId); + ipAndVlan = _vlanDao.assignPodDirectAttachIpAddress(dcId, podId, Account.ACCOUNT_ID_SYSTEM, DomainVO.ROOT_DOMAIN); + if (ipAndVlan == null) + s_logger.debug("Unable to get public ip address (type=DirectAttach) for console proxy vm for data center : " + dcId); + } + if (ipAndVlan != null) { + VlanVO vlan = ipAndVlan.second(); + networkInfo net = new networkInfo(ipAndVlan.first(), vlan.getVlanNetmask(), vlan.getVlanGateway(), vlan.getId(), vlan.getVlanId()); + return net; + } + return null; + } + + private String allocPrivateIpAddress(Long dcId, Long podId, Long proxyId, String macAddr) { + if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) { + return _IpAllocator.getPrivateIpAddress(macAddr, dcId, podId).ipaddr; + } else { + return _dcDao.allocatePrivateIpAddress(dcId, podId, proxyId); + } + } + + private void freePrivateIpAddress(String ipAddress, Long dcId, Long podId) { + if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) { + _IpAllocator.releasePrivateIpAddress(ipAddress, dcId, podId); + } else { + _dcDao.releasePrivateIpAddress(ipAddress, dcId, podId); + } + } + + private void freePublicIpAddress(String ipAddress, long dcId, long podId) { + if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) { + _IpAllocator.releasePublicIpAddress(ipAddress, dcId, podId); + } else { + _ipAddressDao.unassignIpAddress(ipAddress); + } + } + + private ConsoleProxyAllocator getCurrentAllocator() { + // for now, only one adapter is supported + Enumeration it = _consoleProxyAllocators.enumeration(); + if (it.hasMoreElements()) + return it.nextElement(); + + return null; + } + + protected String connect(String ipAddress, int port) { + for (int i = 0; i <= _ssh_retry; i++) { + SocketChannel sch = null; + try { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Trying to connect to " + ipAddress); + } + sch = SocketChannel.open(); + sch.configureBlocking(true); + sch.socket().setSoTimeout(5000); + + InetSocketAddress addr = new InetSocketAddress(ipAddress, port); + sch.connect(addr); + return null; + } catch (IOException e) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Could not connect to " + ipAddress); + } + } finally { + if (sch != null) { + try { + sch.close(); + } catch (IOException e) { + } + } + } + try { + Thread.sleep(_ssh_sleep); + } catch (InterruptedException ex) { + } + } + + s_logger.debug("Unable to logon to " + ipAddress); + + return "Unable to connect"; + } + + public void onLoadAnswer(ConsoleProxyLoadAnswer answer) { + if (answer.getDetails() == null) + return; + + ConsoleProxyStatus status = null; + try { + GsonBuilder gb = new GsonBuilder(); + gb.setVersion(1.3); + Gson gson = gb.create(); + status = gson.fromJson(answer.getDetails(), ConsoleProxyStatus.class); + } catch (Throwable e) { + s_logger.warn("Unable to parse load info from proxy, proxy vm id : " + answer.getProxyVmId() + ", info : " + answer.getDetails()); + } + + if (status != null) { + int count = 0; + if (status.getConnections() != null) + count = status.getConnections().length; + + byte[] details = null; + if (answer.getDetails() != null) + details = answer.getDetails().getBytes(Charset.forName("US-ASCII")); + _consoleProxyDao.update(answer.getProxyVmId(), count, DateUtil.currentGMTTime(), details); + } else { + if (s_logger.isTraceEnabled()) + s_logger.trace("Unable to get console proxy load info, id : " + answer.getProxyVmId()); + + _consoleProxyDao.update(answer.getProxyVmId(), 0, DateUtil.currentGMTTime(), null); + // TODO : something is wrong with the VM, restart it? + } + } + + @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 = 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); + } + + private ConsoleProxyVO findConsoleProxyByHost(HostVO host) throws NumberFormatException { + String name = host.getName(); + long proxyVmId = 0; + ConsoleProxyVO proxy = null; + if (name != null && name.startsWith("v-")) { + String[] tokens = name.split("-"); + proxyVmId = Long.parseLong(tokens[1]); + proxy = this._consoleProxyDao.findById(proxyVmId); + } + return proxy; + } + + @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.setPrivateNetmask(cmd.getPrivateNetmask()); + 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) { + 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 = this._consoleProxyDao.findById(proxyVmId); + if (proxy != null) { + Long hostId = proxy.getHostId(); + + // 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; + } + } + } + } + + private void checkPendingProxyVMs() { + // drive state to change away from transient states + List l = _consoleProxyDao.getProxyListInStates(State.Creating); + if (l != null && l.size() > 0) { + for (ConsoleProxyVO proxy : l) { + if (proxy.getLastUpdateTime() == null + || (proxy.getLastUpdateTime() != null && System.currentTimeMillis() - proxy.getLastUpdateTime().getTime() > 60000)) { + try { + ConsoleProxyVO readyProxy = null; + if (_allocProxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { + try { + readyProxy = allocProxyStorage(proxy.getDataCenterId(), proxy.getId()); + } finally { + _allocProxyLock.unlock(); + } + + if (readyProxy != null) { + GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(readyProxy.getId())); + try { + if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { + try { + readyProxy = start(readyProxy.getId(), 0); + } finally { + proxyLock.unlock(); + } + } else { + if (s_logger.isInfoEnabled()) + s_logger.info("Unable to acquire synchronization lock to start console proxy : " + readyProxy.getName()); + } + } finally { + proxyLock.releaseRef(); + } + } + } else { + if (s_logger.isInfoEnabled()) + s_logger.info("Unable to acquire synchronization lock to allocate proxy storage, wait for next turn"); + } + } catch (StorageUnavailableException e) { + s_logger.warn("Storage unavailable", e); + } catch (InsufficientCapacityException e) { + s_logger.warn("insuffiient capacity", e); + } catch (ConcurrentOperationException e) { + s_logger.debug("Concurrent operation: " + e.getMessage()); + } + } + } + } + } + + private Runnable getCapacityScanTask() { + return new Runnable() { + + @Override + public void run() { + Transaction txn = Transaction.open(Transaction.CLOUD_DB); + try { + reallyRun(); + } catch (Throwable e) { + s_logger.warn("Unexpected exception " + e.getMessage(), e); + } finally { + StackMaid.current().exitCleanup(); + txn.close(); + } + } + + private void reallyRun() { + if (s_logger.isTraceEnabled()) + s_logger.trace("Begin console proxy capacity scan"); + + // config var for consoleproxy.restart check + String restart = _configDao.getValue("consoleproxy.restart"); + if (restart != null && restart.equalsIgnoreCase("false")) { + s_logger.debug("Capacity scan disabled purposefully, consoleproxy.restart = false. This happens when the primarystorage is in maintenance mode"); + return; + } + + Map zoneHostInfoMap = getZoneHostInfo(); + if (isServiceReady(zoneHostInfoMap)) { + if (s_logger.isTraceEnabled()) + s_logger.trace("Service is ready, check to see if we need to allocate standby capacity"); + + if (!_capacityScanLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION)) { + if (s_logger.isTraceEnabled()) + s_logger.trace("Capacity scan lock is used by others, skip and wait for my turn"); + return; + } + + if (s_logger.isTraceEnabled()) + s_logger.trace("*** Begining capacity scan... ***"); + + try { + checkPendingProxyVMs(); + + // scan default data center first + long defaultId = 0; + + // proxy count info by data-centers (zone-id, zone-name, + // count) + List l = _consoleProxyDao.getDatacenterProxyLoadMatrix(); + + // running VM session count by data-centers (zone-id, + // zone-name, count) + List listVmCounts = _consoleProxyDao.getDatacenterSessionLoadMatrix(); + + // indexing load info by data-center id + Map mapVmCounts = new HashMap(); + if (listVmCounts != null) + for (ConsoleProxyLoadInfo info : listVmCounts) + mapVmCounts.put(info.getId(), info); + + for (ConsoleProxyLoadInfo info : l) { + if (info.getName().equals(_instance)) { + ConsoleProxyLoadInfo vmInfo = mapVmCounts.get(info.getId()); + + if (!checkCapacity(info, vmInfo != null ? vmInfo : new ConsoleProxyLoadInfo())) { + if (isZoneReady(zoneHostInfoMap, info.getId())) { + allocCapacity(info.getId()); + } else { + if (s_logger.isTraceEnabled()) + s_logger.trace("Zone " + info.getId() + " is not ready to alloc standy console proxy"); + } + } + + defaultId = info.getId(); + break; + } + } + + // scan rest of data-centers + for (ConsoleProxyLoadInfo info : l) { + if (info.getId() != defaultId) { + ConsoleProxyLoadInfo vmInfo = mapVmCounts.get(info.getId()); + + if (!checkCapacity(info, vmInfo != null ? vmInfo : new ConsoleProxyLoadInfo())) { + if (isZoneReady(zoneHostInfoMap, info.getId())) { + allocCapacity(info.getId()); + } else { + if (s_logger.isTraceEnabled()) + s_logger.trace("Zone " + info.getId() + " is not ready to alloc standy console proxy"); + } + } + } + } + + if (s_logger.isTraceEnabled()) + s_logger.trace("*** Stop capacity scan ***"); + } finally { + _capacityScanLock.unlock(); + } + + } else { + if (s_logger.isTraceEnabled()) + s_logger.trace("Service is not ready for capacity preallocation, wait for next time"); + } + + if (s_logger.isTraceEnabled()) + s_logger.trace("End of console proxy capacity scan"); + } + }; + } + + private boolean checkCapacity(ConsoleProxyLoadInfo proxyCountInfo, ConsoleProxyLoadInfo vmCountInfo) { + + if (proxyCountInfo.getCount() * _capacityPerProxy - vmCountInfo.getCount() <= _standbyCapacity) + return false; + + return true; + } + + private void allocCapacity(long dataCenterId) { + if (s_logger.isTraceEnabled()) + s_logger.trace("Allocate console proxy standby capacity for data center : " + dataCenterId); + + boolean proxyFromStoppedPool = false; + ConsoleProxyVO proxy = assignProxyFromStoppedPool(dataCenterId); + if (proxy == null) { + if (s_logger.isInfoEnabled()) + s_logger.info("No stopped console proxy is available, need to allocate a new console proxy"); + + if (_allocProxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { + try { + proxy = startNew(dataCenterId); + } finally { + _allocProxyLock.unlock(); + } + } else { + if (s_logger.isInfoEnabled()) + s_logger.info("Unable to acquire synchronization lock to allocate proxy resource for standby capacity, wait for next scan"); + return; + } + } else { + if (s_logger.isInfoEnabled()) + s_logger.info("Found a stopped console proxy, bring it up to running pool. proxy vm id : " + proxy.getId()); + proxyFromStoppedPool = true; + } + + if (proxy != null) { + long proxyVmId = proxy.getId(); + GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(proxyVmId)); + try { + if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { + try { + proxy = startProxy(proxyVmId, 0); + } finally { + proxyLock.unlock(); + } + } else { + if (s_logger.isInfoEnabled()) + s_logger.info("Unable to acquire synchronization lock to start proxy for standby capacity, proxy vm id : " + proxy.getId()); + return; + } + } finally { + proxyLock.releaseRef(); + } + + if (proxy == null) { + if (s_logger.isInfoEnabled()) + s_logger.info("Unable to start console proxy for standby capacity, proxy vm Id : " + proxyVmId + + ", will recycle it and start a new one"); + + if (proxyFromStoppedPool) + destroyProxy(proxyVmId, 0); + } else { + if (s_logger.isInfoEnabled()) + s_logger.info("Console proxy " + proxy.getName() + " is started"); + } + } + } + + public boolean isServiceReady(Map zoneHostInfoMap) { + for (ZoneHostInfo zoneHostInfo : zoneHostInfoMap.values()) { + if (isZoneHostReady(zoneHostInfo)) { + if (s_logger.isInfoEnabled()) + s_logger.info("Zone " + zoneHostInfo.getDcId() + " is ready to launch"); + return true; + } + } + + return false; + } + + public boolean isZoneReady(Map zoneHostInfoMap, long dataCenterId) { + ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenterId); + if (zoneHostInfo != null && isZoneHostReady(zoneHostInfo)) { + VMTemplateVO template = _templateDao.findConsoleProxyTemplate(); + HostVO secondaryStorageHost = _storageMgr.getSecondaryStorageHost(dataCenterId); + boolean templateReady = false; + + if (template != null && secondaryStorageHost != null) { + VMTemplateHostVO templateHostRef = _vmTemplateHostDao.findByHostTemplate(secondaryStorageHost.getId(), template.getId()); + templateReady = (templateHostRef != null) && (templateHostRef.getDownloadState() == Status.DOWNLOADED); + } + + if (templateReady) { + List> l = _consoleProxyDao.getDatacenterStoragePoolHostInfo(dataCenterId, _use_lvm); + if (l != null && l.size() > 0 && l.get(0).second().intValue() > 0) { + return true; + } else { + if (s_logger.isTraceEnabled()) + s_logger.trace("Primary storage is not ready, wait until it is ready to launch console proxy"); + } + } else { + if (s_logger.isTraceEnabled()) + s_logger.trace("Zone host is ready, but console proxy template is not ready"); + } + } + return false; + } + + private boolean isZoneHostReady(ZoneHostInfo zoneHostInfo) { + int expectedFlags = 0; + if (_use_storage_vm) + expectedFlags = RunningHostInfoAgregator.ZoneHostInfo.ROUTING_HOST_MASK; + else + expectedFlags = RunningHostInfoAgregator.ZoneHostInfo.ALL_HOST_MASK; + + return (zoneHostInfo.getFlags() & expectedFlags) == expectedFlags; + } + + private synchronized Map getZoneHostInfo() { + Date cutTime = DateUtil.currentGMTTime(); + List l = _hostDao.getRunningHostCounts(new Date(cutTime.getTime() - ClusterManager.DEFAULT_HEARTBEAT_THRESHOLD)); + + RunningHostInfoAgregator aggregator = new RunningHostInfoAgregator(); + if (l.size() > 0) + for (RunningHostCountInfo countInfo : l) + aggregator.aggregate(countInfo); + + return aggregator.getZoneHostInfoMap(); + } + + @Override + public String getName() { + return _name; + } + + @Override + public boolean start() { + if (s_logger.isInfoEnabled()) + s_logger.info("Start console proxy manager"); + + return true; + } + + @Override + public boolean stop() { + if (s_logger.isInfoEnabled()) + s_logger.info("Stop console proxy manager"); + _capacityScanScheduler.shutdownNow(); + + try { + _capacityScanScheduler.awaitTermination(EXECUTOR_SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + } + + _capacityScanLock.releaseRef(); + _allocProxyLock.releaseRef(); + return true; + } + + @Override + public Command cleanup(ConsoleProxyVO vm, String vmName) { + if (vmName != null) { + return new StopCommand(vm, vmName, VirtualMachineName.getVnet(vmName)); + } else if (vm != null) { + ConsoleProxyVO vo = vm; + return new StopCommand(vo, null); + } else { + throw new CloudRuntimeException("Shouldn't even be here!"); + } + } + + @Override + public void completeStartCommand(ConsoleProxyVO vm) { + _consoleProxyDao.updateIf(vm, Event.AgentReportRunning, vm.getHostId()); + } + + @Override + public void completeStopCommand(ConsoleProxyVO vm) { + completeStopCommand(vm, Event.AgentReportStopped); + } + + @DB + protected void completeStopCommand(ConsoleProxyVO proxy, Event ev) { + Transaction txn = Transaction.currentTxn(); + try { + txn.start(); + String privateIpAddress = proxy.getPrivateIpAddress(); + if (privateIpAddress != null) { + proxy.setPrivateIpAddress(null); + freePrivateIpAddress(privateIpAddress, proxy.getDataCenterId(), proxy.getId()); + } + String guestIpAddress = proxy.getGuestIpAddress(); + if (guestIpAddress != null) { + proxy.setGuestIpAddress(null); + _dcDao.releaseLinkLocalPrivateIpAddress(guestIpAddress, proxy.getDataCenterId(), proxy.getId()); + } + + if (!_consoleProxyDao.updateIf(proxy, ev, null)) { + s_logger.debug("Unable to update the console proxy"); + return; + } + txn.commit(); + } catch (Exception e) { + s_logger.error("Unable to complete stop command due to ", e); + } + + if (_storageMgr.unshare(proxy, null) == null) { + s_logger.warn("Unable to set share to false for " + proxy.getId()); + } + } + + @Override + public ConsoleProxyVO get(long id) { + return _consoleProxyDao.findById(id); + } + + @Override + public Long convertToId(String vmName) { + if (!VirtualMachineName.isValidConsoleProxyName(vmName, _instance)) { + return null; + } + return VirtualMachineName.getConsoleProxyId(vmName); + } + + @Override + public boolean stopProxy(long proxyVmId, long startEventId) { + + AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor(); + if (asyncExecutor != null) { + AsyncJobVO job = asyncExecutor.getJob(); + + if (s_logger.isInfoEnabled()) + s_logger.info("Stop console proxy " + proxyVmId + ", update async job-" + job.getId()); + _asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", proxyVmId); + } + + ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId); + if (proxy == null) { + if (s_logger.isDebugEnabled()) + s_logger.debug("Stopping console proxy failed: console proxy " + proxyVmId + " no longer exists"); + return false; + } + /* + * saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, + * EventTypes.EVENT_PROXY_STOP, "Stopping console proxy with Id: " + + * proxyVmId, startEventId); + */ + try { + return stop(proxy, startEventId); + } catch (AgentUnavailableException e) { + if (s_logger.isDebugEnabled()) + s_logger.debug("Stopping console proxy " + proxy.getName() + " faled : exception " + e.toString()); + return false; + } + } + + @Override + public boolean rebootProxy(long proxyVmId, long startEventId) { + AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor(); + if (asyncExecutor != null) { + AsyncJobVO job = asyncExecutor.getJob(); + + if (s_logger.isInfoEnabled()) + s_logger.info("Reboot console proxy " + proxyVmId + ", update async job-" + job.getId()); + _asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", proxyVmId); + } + + final ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId); + + if (proxy == null || proxy.getState() == State.Destroyed) { + return false; + } + + /* + * saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, + * EventTypes.EVENT_PROXY_REBOOT, "Rebooting console proxy with Id: " + + * proxyVmId, startEventId); + */ + if (proxy.getState() == State.Running && proxy.getHostId() != null) { + final RebootCommand cmd = new RebootCommand(proxy.getInstanceName()); + final Answer answer = _agentMgr.easySend(proxy.getHostId(), cmd); + + if (answer != null) { + if (s_logger.isDebugEnabled()) + s_logger.debug("Successfully reboot console proxy " + proxy.getName()); + + SubscriptionMgr.getInstance() + .notifySubscribers( + ConsoleProxyManager.ALERT_SUBJECT, + this, + new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_REBOOTED, proxy.getDataCenterId(), proxy.getId(), + proxy, null)); + + final EventVO event = new EventVO(); + event.setUserId(User.UID_SYSTEM); + event.setAccountId(Account.ACCOUNT_ID_SYSTEM); + event.setType(EventTypes.EVENT_PROXY_REBOOT); + event.setLevel(EventVO.LEVEL_INFO); + event.setStartId(startEventId); + event.setDescription("Console proxy rebooted - " + proxy.getName()); + _eventDao.persist(event); + return true; + } else { + if (s_logger.isDebugEnabled()) + s_logger.debug("failed to reboot console proxy : " + proxy.getName()); + + final EventVO event = new EventVO(); + event.setUserId(User.UID_SYSTEM); + event.setAccountId(Account.ACCOUNT_ID_SYSTEM); + event.setType(EventTypes.EVENT_PROXY_REBOOT); + event.setLevel(EventVO.LEVEL_ERROR); + event.setStartId(startEventId); + event.setDescription("Rebooting console proxy failed - " + proxy.getName()); + _eventDao.persist(event); + return false; + } + } else { + return startProxy(proxyVmId, 0) != null; + } + } + + @Override + public boolean destroy(ConsoleProxyVO proxy) throws AgentUnavailableException { + return destroyProxy(proxy.getId(), 0); + } + + @Override + @DB + public boolean destroyProxy(long vmId, long startEventId) { + AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor(); + if (asyncExecutor != null) { + AsyncJobVO job = asyncExecutor.getJob(); + + if (s_logger.isInfoEnabled()) + s_logger.info("Destroy console proxy " + vmId + ", update async job-" + job.getId()); + _asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", vmId); + } + + ConsoleProxyVO vm = _consoleProxyDao.findById(vmId); + if (vm == null || vm.getState() == State.Destroyed) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Unable to find vm or vm is destroyed: " + vmId); + } + return true; + } + /* + * saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, + * EventTypes.EVENT_PROXY_DESTROY, "Destroying console proxy with Id: " + * + vmId, startEventId); + */ + if (s_logger.isDebugEnabled()) { + s_logger.debug("Destroying console proxy vm " + vmId); + } + + if (!_consoleProxyDao.updateIf(vm, Event.DestroyRequested, null)) { + s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vmId); + return false; + } + + Transaction txn = Transaction.currentTxn(); + List vols = null; + try { + vols = _volsDao.findByInstance(vmId); + if (vols.size() != 0) { + _storageMgr.destroy(vm, vols); + } + + return true; + } finally { + try { + txn.start(); + // release critical system resources used by the VM before we + // delete them + if (vm.getPublicIpAddress() != null) + freePublicIpAddress(vm.getPublicIpAddress(), vm.getDataCenterId(), vm.getPodId()); + vm.setPublicIpAddress(null); + + _consoleProxyDao.remove(vm.getId()); + + final EventVO event = new EventVO(); + event.setUserId(User.UID_SYSTEM); + event.setAccountId(Account.ACCOUNT_ID_SYSTEM); + event.setType(EventTypes.EVENT_PROXY_DESTROY); + event.setLevel(EventVO.LEVEL_INFO); + event.setStartId(startEventId); + event.setDescription("Console proxy destroyed - " + vm.getName()); + _eventDao.persist(event); + + txn.commit(); + } catch (Exception e) { + s_logger.error("Caught this error: ", e); + txn.rollback(); + return false; + } finally { + s_logger.debug("console proxy vm is destroyed : " + vm.getName()); + } + } + } + + @DB + public boolean destroyProxyDBOnly(long vmId) { + Transaction txn = Transaction.currentTxn(); + try { + txn.start(); + _volsDao.deleteVolumesByInstance(vmId); + + ConsoleProxyVO proxy = _consoleProxyDao.findById(vmId); + if (proxy != null) { + if (proxy.getPublicIpAddress() != null) + freePublicIpAddress(proxy.getPublicIpAddress(), proxy.getDataCenterId(), proxy.getPodId()); + + _consoleProxyDao.remove(vmId); + + final EventVO event = new EventVO(); + event.setUserId(User.UID_SYSTEM); + event.setAccountId(Account.ACCOUNT_ID_SYSTEM); + event.setType(EventTypes.EVENT_PROXY_DESTROY); + event.setLevel(EventVO.LEVEL_INFO); + event.setDescription("Console proxy destroyed - " + proxy.getName()); + _eventDao.persist(event); + } + + txn.commit(); + return true; + } catch (Exception e) { + s_logger.error("Caught this error: ", e); + txn.rollback(); + return false; + } finally { + s_logger.debug("console proxy vm is destroyed from DB : " + vmId); + } + } + + @Override + public boolean stop(ConsoleProxyVO proxy, long startEventId) throws AgentUnavailableException { + if (!_consoleProxyDao.updateIf(proxy, Event.StopRequested, proxy.getHostId())) { + s_logger.debug("Unable to stop console proxy: " + proxy.toString()); + return false; + } + + // IPAddressVO ip = _ipAddressDao.findById(proxy.getPublicIpAddress()); + // VlanVO vlan = _vlanDao.findById(new Long(ip.getVlanDbId())); + + GlobalLock proxyLock = GlobalLock.getInternLock(getProxyLockName(proxy.getId())); + try { + if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { + try { + StopCommand cmd = new StopCommand(proxy, true, Integer.toString(_consoleProxyPort), Integer.toString(_consoleProxyUrlPort), + proxy.getPublicIpAddress()); + try { + Long proxyHostId = proxy.getHostId(); + if (proxyHostId == null) { + s_logger.debug("Unable to stop due to proxy " + proxy.getId() + + " as host is no longer available, proxy may already have been stopped"); + return false; + } + StopAnswer answer = (StopAnswer) _agentMgr.send(proxyHostId, cmd); + if (answer == null || !answer.getResult()) { + s_logger.debug("Unable to stop due to " + (answer == null ? "answer is null" : answer.getDetails())); + + final EventVO event = new EventVO(); + event.setUserId(User.UID_SYSTEM); + event.setAccountId(Account.ACCOUNT_ID_SYSTEM); + event.setType(EventTypes.EVENT_PROXY_STOP); + event.setLevel(EventVO.LEVEL_ERROR); + event.setStartId(startEventId); + event.setDescription("Stopping console proxy failed due to negative answer from agent - " + proxy.getName()); + _eventDao.persist(event); + return false; + } + completeStopCommand(proxy, Event.OperationSucceeded); + + SubscriptionMgr.getInstance().notifySubscribers( + ConsoleProxyManager.ALERT_SUBJECT, + this, + new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_DOWN, proxy.getDataCenterId(), proxy.getId(), proxy, + null)); + + final EventVO event = new EventVO(); + event.setUserId(User.UID_SYSTEM); + event.setAccountId(Account.ACCOUNT_ID_SYSTEM); + event.setType(EventTypes.EVENT_PROXY_STOP); + event.setLevel(EventVO.LEVEL_INFO); + event.setStartId(startEventId); + event.setDescription("Console proxy stopped - " + proxy.getName()); + _eventDao.persist(event); + return true; + } catch (OperationTimedoutException e) { + final EventVO event = new EventVO(); + event.setUserId(User.UID_SYSTEM); + event.setAccountId(Account.ACCOUNT_ID_SYSTEM); + event.setType(EventTypes.EVENT_PROXY_STOP); + event.setLevel(EventVO.LEVEL_ERROR); + event.setStartId(startEventId); + event.setDescription("Stopping console proxy failed due to operation time out - " + proxy.getName()); + _eventDao.persist(event); + throw new AgentUnavailableException(proxy.getHostId()); + } + } finally { + proxyLock.unlock(); + } + } else { + s_logger.debug("Unable to acquire console proxy lock : " + proxy.toString()); + return false; + } + } finally { + proxyLock.releaseRef(); + } + } + + @Override + public boolean migrate(ConsoleProxyVO proxy, HostVO host) { + HostVO fromHost = _hostDao.findById(proxy.getId()); + + if (!_consoleProxyDao.updateIf(proxy, Event.MigrationRequested, proxy.getHostId())) { + s_logger.debug("State for " + proxy.toString() + " has changed so migration can not take place."); + return false; + } + + MigrateCommand cmd = new MigrateCommand(proxy.getInstanceName(), host.getPrivateIpAddress(), false); + Answer answer = _agentMgr.easySend(fromHost.getId(), cmd); + if (answer == null) { + return false; + } + + _storageMgr.unshare(proxy, fromHost); + + return true; + } + + @Override + public boolean completeMigration(ConsoleProxyVO proxy, HostVO host) throws AgentUnavailableException, OperationTimedoutException { + + CheckVirtualMachineCommand cvm = new CheckVirtualMachineCommand(proxy.getInstanceName()); + CheckVirtualMachineAnswer answer = (CheckVirtualMachineAnswer) _agentMgr.send(host.getId(), cvm); + if (!answer.getResult()) { + s_logger.debug("Unable to complete migration for " + proxy.getId()); + _consoleProxyDao.updateIf(proxy, Event.AgentReportStopped, null); + return false; + } + + State state = answer.getState(); + if (state == State.Stopped) { + s_logger.warn("Unable to complete migration as we can not detect it on " + host.getId()); + _consoleProxyDao.updateIf(proxy, Event.AgentReportStopped, null); + return false; + } + + _consoleProxyDao.updateIf(proxy, Event.OperationSucceeded, host.getId()); + return true; + } + + @Override + public HostVO prepareForMigration(ConsoleProxyVO proxy) throws StorageUnavailableException { + + VMTemplateVO template = _templateDao.findById(proxy.getTemplateId()); + long routerId = proxy.getId(); + boolean mirroredVols = proxy.isMirroredVols(); + DataCenterVO dc = _dcDao.findById(proxy.getDataCenterId()); + HostPodVO pod = _podDao.findById(proxy.getPodId()); + List sps = _storageMgr.getStoragePoolsForVm(proxy.getId()); + StoragePoolVO sp = sps.get(0); // FIXME + + List vols = _volsDao.findCreatedByInstance(routerId); + + String[] storageIps = new String[2]; + VolumeVO vol = vols.get(0); + storageIps[0] = vol.getHostIp(); + if (mirroredVols && (vols.size() == 2)) { + storageIps[1] = vols.get(1).getHostIp(); + } + + PrepareForMigrationCommand cmd = new PrepareForMigrationCommand(proxy.getName(), null, storageIps, vols, mirroredVols); + + HostVO routingHost = null; + HashSet avoid = new HashSet(); + + HostVO fromHost = _hostDao.findById(proxy.getHostId()); + if (fromHost.getClusterId() == null) { + s_logger.debug("The host is not in a cluster"); + return null; + } + avoid.add(fromHost); + + while ((routingHost = (HostVO) _agentMgr.findHost(Host.Type.Routing, dc, pod, sp, _serviceOffering, template, proxy, fromHost, avoid)) != null) { + avoid.add(routingHost); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Trying to migrate router to host " + routingHost.getName()); + } + + if (!_storageMgr.share(proxy, vols, routingHost, false)) { + s_logger.warn("Can not share " + proxy.getName()); + throw new StorageUnavailableException(vol.getPoolId()); + } + + Answer answer = _agentMgr.easySend(routingHost.getId(), cmd); + if (answer != null && answer.getResult()) { + return routingHost; + } + _storageMgr.unshare(proxy, vols, routingHost); + } + + return null; + } + + private String getCapacityScanLockName() { + // to improve security, it may be better to return a unique mashed + // name(for example MD5 hashed) + return "consoleproxy.capacity.scan"; + } + + private String getAllocProxyLockName() { + // to improve security, it may be better to return a unique mashed + // name(for example MD5 hashed) + return "consoleproxy.alloc"; + } + + private String getProxyLockName(long id) { + return "consoleproxy." + id; + } + + private Long saveStartedEvent(Long userId, Long accountId, String type, String description, long startEventId) { + EventVO event = new EventVO(); + event.setUserId(userId); + event.setAccountId(accountId); + event.setType(type); + event.setState(EventState.Started); + event.setDescription(description); + event.setStartId(startEventId); + event = _eventDao.persist(event); + if (event != null) + return event.getId(); + return null; + } + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + if (s_logger.isInfoEnabled()) + s_logger.info("Start configuring console proxy manager : " + name); + + _name = name; + + ComponentLocator locator = ComponentLocator.getCurrentLocator(); + ConfigurationDao configDao = locator.getDao(ConfigurationDao.class); + if (configDao == null) { + throw new ConfigurationException("Unable to get the configuration dao."); + } + + Map configs = configDao.getConfiguration("management-server", params); + + _proxyRamSize = NumbersUtil.parseInt(configs.get("consoleproxy.ram.size"), DEFAULT_PROXY_VM_RAMSIZE); + + String value = configs.get("start.retry"); + _find_host_retry = NumbersUtil.parseInt(value, DEFAULT_FIND_HOST_RETRY_COUNT); + + value = configs.get("consoleproxy.cmd.port"); + _proxyCmdPort = NumbersUtil.parseInt(value, DEFAULT_PROXY_CMD_PORT); + + value = configs.get("consoleproxy.sslEnabled"); + if (value != null && value.equalsIgnoreCase("true")) + _sslEnabled = true; + + value = configs.get("consoleproxy.capacityscan.interval"); + _capacityScanInterval = NumbersUtil.parseLong(value, DEFAULT_CAPACITY_SCAN_INTERVAL); + + _capacityPerProxy = NumbersUtil.parseInt(configs.get("consoleproxy.session.max"), DEFAULT_PROXY_CAPACITY); + _standbyCapacity = NumbersUtil.parseInt(configs.get("consoleproxy.capacity.standby"), DEFAULT_STANDBY_CAPACITY); + _proxySessionTimeoutValue = NumbersUtil.parseInt(configs.get("consoleproxy.session.timeout"), DEFAULT_PROXY_SESSION_TIMEOUT); + + value = configs.get("consoleproxy.port"); + if (value != null) + _consoleProxyPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT); + + value = configs.get("consoleproxy.url.port"); + if (value != null) + _consoleProxyUrlPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_URL_PORT); + + value = configs.get("system.vm.use.local.storage"); + if (value != null && value.equalsIgnoreCase("true")) + _use_lvm = true; + + value = configs.get("secondary.storage.vm"); + if (value != null && value.equalsIgnoreCase("true")) + _use_storage_vm = true; + + if (s_logger.isInfoEnabled()) { + s_logger.info("Console proxy max session soft limit : " + _capacityPerProxy); + s_logger.info("Console proxy standby capacity : " + _standbyCapacity); + } + + _domain = configs.get("domain"); + if (_domain == null) { + _domain = "foo.com"; + } + + _instance = configs.get("instance.name"); + if (_instance == null) { + _instance = "DEFAULT"; + } + + value = (String) params.get("ssh.sleep"); + _ssh_sleep = NumbersUtil.parseInt(value, 5) * 1000; + + value = (String) params.get("ssh.retry"); + _ssh_retry = NumbersUtil.parseInt(value, 3); + + Map agentMgrConfigs = configDao.getConfiguration("AgentManager", params); + _mgmt_host = agentMgrConfigs.get("host"); + if (_mgmt_host == null) { + s_logger.warn("Critical warning! Please configure your management server host address right after you have started your management server and then restart it, otherwise you won't be able to do console access"); + } + + value = agentMgrConfigs.get("port"); + _mgmt_port = NumbersUtil.parseInt(value, 8250); + + _consoleProxyAllocators = locator.getAdapters(ConsoleProxyAllocator.class); + if (_consoleProxyAllocators == null || !_consoleProxyAllocators.isSet()) { + throw new ConfigurationException("Unable to get proxy allocators"); + } + + _listener = new ConsoleProxyListener(this); + _agentMgr.registerForHostEvents(_listener, true, true, false); + + Adapters ipAllocators = locator.getAdapters(IpAddrAllocator.class); + if (ipAllocators != null && ipAllocators.isSet()) { + Enumeration it = ipAllocators.enumeration(); + _IpAllocator = it.nextElement(); + } + + HighAvailabilityManager haMgr = locator.getManager(HighAvailabilityManager.class); + if (haMgr != null) { + haMgr.registerHandler(VirtualMachine.Type.ConsoleProxy, this); + } + + boolean useLocalStorage = Boolean.parseBoolean((String) params.get(Config.SystemVMUseLocalStorage.key())); + _serviceOffering = new ServiceOfferingVO("Fake Offering For DomP", 1, _proxyRamSize, 0, 0, 0, false, null, GuestIpType.Virtualized, + useLocalStorage, true, null); + _serviceOffering.setUniqueName("Cloud.com-ConsoleProxy"); + _serviceOffering = _offeringDao.persistSystemServiceOffering(_serviceOffering); + _template = _templateDao.findConsoleProxyTemplate(); + if (_template == null) { + throw new ConfigurationException("Unable to find the template for console proxy VMs"); + } + + _capacityScanScheduler.scheduleAtFixedRate(getCapacityScanTask(), STARTUP_DELAY, _capacityScanInterval, TimeUnit.MILLISECONDS); + + if (s_logger.isInfoEnabled()) + s_logger.info("Console Proxy Manager is configured."); + return true; + } + + protected ConsoleProxyManagerImpl() { + } } diff --git a/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java b/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java index 285b51776f2..549e0081048 100644 --- a/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java +++ b/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java @@ -24,8 +24,9 @@ import javax.ejb.Local; import javax.naming.ConfigurationException; import com.cloud.configuration.dao.ConfigurationDao; -import com.cloud.host.HostVO; import com.cloud.host.Host.Type; +import com.cloud.host.HostVO; +import com.cloud.info.ConsoleProxyInfo; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.component.Inject; import com.cloud.vm.ConsoleProxyVO; @@ -46,31 +47,8 @@ public class StaticConsoleProxyManager extends AgentBasedConsoleProxyManager imp } @Override - public ConsoleProxyVO assignProxy(long dataCenterId, long userVmId) { - ConsoleProxyVO proxy = new ConsoleProxyVO(1l, "EmbeddedProxy", null, null, null, - "02:02:02:02:02:02", - "127.0.0.1", - "255.255.255.0", - 1l, - 1l, - "03:03:03:03:03:03", - _ip, - "255.255.255.0", - null, - "untagged", - 1l, - dataCenterId, - "0.0.0.0", - 0L, - "dns1", - "dn2", - "domain", - 0, - 0); - - proxy.setPort(_consoleProxyUrlPort); - proxy.setSslEnabled(false); - return proxy; + public ConsoleProxyInfo assignProxy(long dataCenterId, long userVmId) { + return new ConsoleProxyInfo(false, _ip, _consoleProxyPort, _consoleProxyUrlPort); } @Override diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 54883bb42a6..2a5d57d5b8d 100644 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -351,9 +351,6 @@ public class ManagementServerImpl implements ManagementServer { private final Map _configs; private String _domain; - private int _consoleProxyPort = ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT; - // private int _consoleProxyUrlPort = - // ConsoleProxyManager.DEFAULT_PROXY_URL_PORT; private final int _routerRamSize; private final int _proxyRamSize; @@ -447,16 +444,7 @@ public class ManagementServerImpl implements ManagementServer { _domain = "." + _domain; } - String value = _configs.get("consoleproxy.port"); - if (value != null) - _consoleProxyPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT); - - // value = _configs.get("consoleproxy.url.port"); - // if(value != null) - // _consoleProxyUrlPort = NumbersUtil.parseInt(value, - // ConsoleProxyManager.DEFAULT_PROXY_URL_PORT); - - value = _configs.get("account.cleanup.interval"); + String value = _configs.get("account.cleanup.interval"); int cleanup = NumbersUtil.parseInt(value, 60 * 60 * 24); // 1 hour. // Parse the max number of UserVMs and public IPs from server-setup.xml, @@ -771,6 +759,7 @@ public class ManagementServerImpl implements ManagementServer { return user; } + @Override public User getUser(long userId, boolean active) { if (s_logger.isDebugEnabled()) { s_logger.debug("Retrieiving user with id: " + userId + " and active = " + active); @@ -1240,6 +1229,7 @@ public class ManagementServerImpl implements ManagementServer { /* * Save event after starting execution of an async job */ + @Override public Long saveStartedEvent(Long userId, Long accountId, String type, String description, long startEventId) { EventVO event = new EventVO(); event.setUserId(userId); @@ -2874,6 +2864,7 @@ public class ManagementServerImpl implements ManagementServer { return _hostDao.findById(hostId); } + @Override public void updateHost(long hostId, long guestOSCategoryId) throws InvalidParameterValueException { // Verify that the guest OS Category exists if (guestOSCategoryId > 0) { @@ -2885,6 +2876,7 @@ public class ManagementServerImpl implements ManagementServer { _agentMgr.updateHost(hostId, guestOSCategoryId); } + @Override public boolean deleteHost(long hostId) { return _agentMgr.deleteHost(hostId); } @@ -5950,6 +5942,7 @@ public class ManagementServerImpl implements ManagementServer { return _asyncMgr.submitAsyncJob(job); } + @Override public void deleteRule(long ruleId, long userId, long accountId) throws InvalidParameterValueException, PermissionDeniedException, InternalErrorException { Exception e = null; try { @@ -6006,6 +5999,7 @@ public class ManagementServerImpl implements ManagementServer { } } + @Override public long deleteRuleAsync(long id, long userId, long accountId) { DeleteRuleParam param = new DeleteRuleParam(id, userId, accountId); Gson gson = GsonHelper.getBuilder().create(); @@ -6019,10 +6013,12 @@ public class ManagementServerImpl implements ManagementServer { return _asyncMgr.submitAsyncJob(job); } + @Override public List listAllTemplates() { return _templateDao.listAll(); } + @Override public List listGuestOSByCriteria(Criteria c) { @@ -6047,6 +6043,7 @@ public class ManagementServerImpl implements ManagementServer { return _guestOSDao.search(sc, searchFilter); } + @Override public List listGuestOSCategoriesByCriteria(Criteria c) { Filter searchFilter = new Filter(GuestOSCategoryVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit()); @@ -6064,34 +6061,37 @@ public class ManagementServerImpl implements ManagementServer { return _guestOSCategoryDao.search(sc, searchFilter); } + @Override public String getConfigurationValue(String name) { return _configDao.getValue(name); } + @Override public ConsoleProxyInfo getConsoleProxy(long dataCenterId, long userVmId) { - ConsoleProxyVO proxy = _consoleProxyMgr.assignProxy(dataCenterId, userVmId); - if (proxy == null) - return null; - - return new ConsoleProxyInfo(proxy.isSslEnabled(), proxy.getPublicIpAddress(), _consoleProxyPort, proxy.getPort()); + return _consoleProxyMgr.assignProxy(dataCenterId, userVmId); } + @Override public ConsoleProxyVO startConsoleProxy(long instanceId, long startEventId) throws InternalErrorException { return _consoleProxyMgr.startProxy(instanceId, startEventId); } + @Override public boolean stopConsoleProxy(long instanceId, long startEventId) { return _consoleProxyMgr.stopProxy(instanceId, startEventId); } + @Override public boolean rebootConsoleProxy(long instanceId, long startEventId) { return _consoleProxyMgr.rebootProxy(instanceId, startEventId); } + @Override public boolean destroyConsoleProxy(long instanceId, long startEventId) { return _consoleProxyMgr.destroyProxy(instanceId, startEventId); } + @Override public long startConsoleProxyAsync(long instanceId) { long eventId = saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_START, "starting console proxy with Id: "+instanceId); VMOperationParam param = new VMOperationParam(0, instanceId, null, eventId); @@ -6106,6 +6106,7 @@ public class ManagementServerImpl implements ManagementServer { return _asyncMgr.submitAsyncJob(job, true); } + @Override public long stopConsoleProxyAsync(long instanceId) { long eventId = saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_STOP, "stopping console proxy with Id: "+instanceId); VMOperationParam param = new VMOperationParam(0, instanceId, null, eventId); @@ -6122,6 +6123,7 @@ public class ManagementServerImpl implements ManagementServer { return _asyncMgr.submitAsyncJob(job, true); } + @Override public long rebootConsoleProxyAsync(long instanceId) { long eventId = saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_REBOOT, "rebooting console proxy with Id: "+instanceId); VMOperationParam param = new VMOperationParam(0, instanceId, null, eventId); @@ -6138,6 +6140,7 @@ public class ManagementServerImpl implements ManagementServer { return _asyncMgr.submitAsyncJob(job, true); } + @Override public long destroyConsoleProxyAsync(long instanceId) { long eventId = saveScheduledEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_PROXY_DESTROY, "destroying console proxy with Id: "+instanceId); VMOperationParam param = new VMOperationParam(0, instanceId, null, eventId); @@ -6152,6 +6155,7 @@ public class ManagementServerImpl implements ManagementServer { return _asyncMgr.submitAsyncJob(job); } + @Override public String getConsoleAccessUrlRoot(long vmId) { VMInstanceVO vm = this.findVMInstanceById(vmId); if (vm != null) { @@ -6162,6 +6166,7 @@ public class ManagementServerImpl implements ManagementServer { return null; } + @Override public int getVncPort(VirtualMachine vm) { if (vm.getHostId() == null) { s_logger.warn("VM " + vm.getName() + " does not have host, return -1 for its VNC port"); @@ -6180,10 +6185,12 @@ public class ManagementServerImpl implements ManagementServer { return port; } + @Override public ConsoleProxyVO findConsoleProxyById(long instanceId) { return _consoleProxyDao.findById(instanceId); } + @Override public List searchForDomains(Criteria c) { Filter searchFilter = new Filter(DomainVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit()); Long domainId = (Long) c.getCriteria(Criteria.ID); @@ -6223,6 +6230,7 @@ public class ManagementServerImpl implements ManagementServer { return _domainDao.search(sc, searchFilter); } + @Override public List searchForDomainChildren(Criteria c) { Filter searchFilter = new Filter(DomainVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit()); Long domainId = (Long) c.getCriteria(Criteria.ID); @@ -6354,6 +6362,7 @@ public class ManagementServerImpl implements ManagementServer { return success && deleteDomainSuccess; } + @Override public void updateDomain(Long domainId, String domainName) { SearchCriteria sc = _domainDao.createSearchCriteria(); sc.addAnd("name", SearchCriteria.Op.EQ, domainName); @@ -6368,6 +6377,7 @@ public class ManagementServerImpl implements ManagementServer { } } + @Override public Long findDomainIdByAccountId(Long accountId) { if (accountId == null) { return null; @@ -6381,6 +6391,7 @@ public class ManagementServerImpl implements ManagementServer { return null; } + @Override public DomainVO findDomainIdById(Long domainId) { return _domainDao.findById(domainId); } @@ -6447,6 +6458,7 @@ public class ManagementServerImpl implements ManagementServer { return _capacityDao.search(sc, searchFilter); } + @Override public long getMemoryUsagebyHost(Long hostId) { long mem = 0; List vms = _vmInstanceDao.listUpByHostIdTypes(hostId, VirtualMachine.Type.DomainRouter); @@ -8266,6 +8278,7 @@ public class ManagementServerImpl implements ManagementServer { return null; } + @Override public ArrayList getCloudIdentifierResponse(long userId) { Criteria c = new Criteria (); @@ -8477,12 +8490,14 @@ public class ManagementServerImpl implements ManagementServer { return _configMgr.addConfig(category, instance, component, name, value, description); } - public boolean preparePrimaryStorageForMaintenance(long primaryStorageId, long userId) { + @Override + public boolean preparePrimaryStorageForMaintenance(long primaryStorageId, long userId) { return _storageMgr.preparePrimaryStorageForMaintenance(primaryStorageId, userId); } - public long preparePrimaryStorageForMaintenanceAsync(long primaryStorageId) throws InvalidParameterValueException + @Override + public long preparePrimaryStorageForMaintenanceAsync(long primaryStorageId) throws InvalidParameterValueException { StoragePoolVO primaryStorage = _poolDao.findById(primaryStorageId); @@ -8512,12 +8527,14 @@ public class ManagementServerImpl implements ManagementServer { } + @Override public boolean cancelPrimaryStorageMaintenance(long primaryStorageId, long userId) { return _storageMgr.cancelPrimaryStorageForMaintenance(primaryStorageId, userId); } - public long cancelPrimaryStorageMaintenanceAsync(long primaryStorageId) throws InvalidParameterValueException + @Override + public long cancelPrimaryStorageMaintenanceAsync(long primaryStorageId) throws InvalidParameterValueException { StoragePoolVO primaryStorage = _poolDao.findById(primaryStorageId); diff --git a/server/src/com/cloud/vm/VmManager.java b/server/src/com/cloud/vm/VmManager.java index 068da4e084d..a9833ec82bf 100644 --- a/server/src/com/cloud/vm/VmManager.java +++ b/server/src/com/cloud/vm/VmManager.java @@ -32,12 +32,12 @@ import com.cloud.user.AccountVO; public interface VmManager { VMInstanceVO allocate(VMInstanceVO vm, - ServiceOfferingVO serviceOffering, - Long rootSize, - List networkOfferings, - Map diskOfferings, - DataCenterVO dc, - AccountVO owner); + ServiceOfferingVO serviceOffering, + Long rootSize, + List networkOfferings, + Map diskOfferings, + DataCenterVO dc, + AccountVO owner); VMInstanceVO allocate(VMInstanceVO vm, ServiceOfferingVO serviceOffering, From f0b82f856560995b48ec4818faae4e857093409f Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Fri, 20 Aug 2010 11:36:15 -0700 Subject: [PATCH 06/17] move source of resource properties from UI folder to client folder move source of resource properties from UI folder to client folder move source of resource properties from UI folder to client folder --- build/build-cloud.xml | 137 +++++++++--------- build/package.xml | 2 +- .../classes}/resources/resource.properties | 0 .../classes}/resources/resource_zh.properties | 0 4 files changed, 72 insertions(+), 67 deletions(-) rename {ui => client/WEB-INF/classes}/resources/resource.properties (100%) rename {ui => client/WEB-INF/classes}/resources/resource_zh.properties (100%) diff --git a/build/build-cloud.xml b/build/build-cloud.xml index b11abe57254..548eedeea1b 100755 --- a/build/build-cloud.xml +++ b/build/build-cloud.xml @@ -3,8 +3,8 @@ - Cloud Stack ant build file - + Cloud Stack ant build file + + @@ -137,7 +137,7 @@ - + @@ -176,7 +176,7 @@ - + @@ -223,9 +223,9 @@ - + @@ -237,9 +237,14 @@ - + + + + + + @@ -252,45 +257,45 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - @@ -304,12 +309,12 @@ - + - - - - + + + + @@ -343,7 +348,7 @@ - + @@ -517,20 +522,20 @@ - - - + + + - - - - - - - - - - + + + + + + + + + + @@ -562,8 +567,8 @@ - - + + diff --git a/build/package.xml b/build/package.xml index a8995cd2349..82781c61a2f 100755 --- a/build/package.xml +++ b/build/package.xml @@ -135,7 +135,7 @@ - + diff --git a/ui/resources/resource.properties b/client/WEB-INF/classes/resources/resource.properties similarity index 100% rename from ui/resources/resource.properties rename to client/WEB-INF/classes/resources/resource.properties diff --git a/ui/resources/resource_zh.properties b/client/WEB-INF/classes/resources/resource_zh.properties similarity index 100% rename from ui/resources/resource_zh.properties rename to client/WEB-INF/classes/resources/resource_zh.properties From eae268d5d934e50db789b047c3316f414e6af146 Mon Sep 17 00:00:00 2001 From: "Manuel Amador (Rudd-O)" Date: Fri, 20 Aug 2010 12:24:59 -0700 Subject: [PATCH 07/17] Undo unnecessary reformatting that is complicating the merges --- build/build-cloud.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/build-cloud.xml b/build/build-cloud.xml index 548eedeea1b..beb115bfac2 100755 --- a/build/build-cloud.xml +++ b/build/build-cloud.xml @@ -3,8 +3,8 @@ - Cloud Stack ant build file - + Cloud Stack ant build file + console proxy + private ConsoleProxyVO proxy; + private int proxyCmdPort; + private String vncPort; + private String urlPort; + private String mgmt_host; + private int mgmt_port; + private boolean sslEnabled; + + ----->abstract + protected String vmName; + protected String storageHosts[] = new String[2]; + protected List volumes; + protected boolean mirroredVols = false; + protected BootloaderType bootloader = BootloaderType.PyGrub; + + */ + + @Override + public boolean executeInSequence() { + return true; + } + + public Start2Command() { + } +} diff --git a/core/src/com/cloud/agent/api/to/HostTO.java b/core/src/com/cloud/agent/api/to/HostTO.java index 717412f4c1e..91cfa65437e 100644 --- a/core/src/com/cloud/agent/api/to/HostTO.java +++ b/core/src/com/cloud/agent/api/to/HostTO.java @@ -18,7 +18,6 @@ package com.cloud.agent.api.to; import com.cloud.host.HostVO; -import com.cloud.vm.NetworkTO; public class HostTO { private String guid; diff --git a/api/src/com/cloud/vm/NetworkTO.java b/core/src/com/cloud/agent/api/to/NetworkTO.java similarity index 60% rename from api/src/com/cloud/vm/NetworkTO.java rename to core/src/com/cloud/agent/api/to/NetworkTO.java index 844b1943e12..d6e428831f3 100644 --- a/api/src/com/cloud/vm/NetworkTO.java +++ b/core/src/com/cloud/agent/api/to/NetworkTO.java @@ -15,7 +15,10 @@ * along with this program. If not, see . * */ -package com.cloud.vm; +package com.cloud.agent.api.to; + +import com.cloud.network.Network.BroadcastDomainType; +import com.cloud.network.Network.TrafficType; /** * Transfer object to transfer network settings. @@ -28,11 +31,65 @@ public class NetworkTO { private String mac; private String dns1; private String dns2; - private String vlan; + private Long vlan; + private BroadcastDomainType broadcastType; + private TrafficType type; - protected NetworkTO() { + public NetworkTO() { } + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public Long getVlan() { + return vlan; + } + + public void setVlan(Long vlan) { + this.vlan = vlan; + } + + public BroadcastDomainType getBroadcastType() { + return broadcastType; + } + + public void setBroadcastType(BroadcastDomainType broadcastType) { + this.broadcastType = broadcastType; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public void setNetmask(String netmask) { + this.netmask = netmask; + } + + public void setGateway(String gateway) { + this.gateway = gateway; + } + + public void setMac(String mac) { + this.mac = mac; + } + + public void setDns1(String dns1) { + this.dns1 = dns1; + } + + public void setDns2(String dns2) { + this.dns2 = dns2; + } + + public void setType(TrafficType type) { + this.type = type; + } + /** * This constructor is usually for hosts where the other information are not important. * @@ -56,7 +113,7 @@ public class NetworkTO { * @param dns1 * @param dns2 */ - public NetworkTO(String ip, String vlan, String netmask, String mac, String gateway, String dns1, String dns2) { + public NetworkTO(String ip, Long vlan, String netmask, String mac, String gateway, String dns1, String dns2) { this.ip = ip; this.netmask = netmask; this.mac = mac; @@ -89,4 +146,8 @@ public class NetworkTO { public String getDns2() { return dns2; } + + public TrafficType getType() { + return type; + } } diff --git a/core/src/com/cloud/agent/api/to/NicTO.java b/core/src/com/cloud/agent/api/to/NicTO.java new file mode 100644 index 00000000000..42e4f66bd94 --- /dev/null +++ b/core/src/com/cloud/agent/api/to/NicTO.java @@ -0,0 +1,36 @@ +/** + * + */ +package com.cloud.agent.api.to; + +public class NicTO extends NetworkTO { + int deviceId; + Integer controlPort; + Integer networkRateMbps; + Integer networkRateMulticastMbps; + + public NicTO() { + super(); + controlPort = null; + } + + public void setDeviceId(int deviceId) { + this.deviceId = deviceId; + } + + public int getDeviceId() { + return deviceId; + } + + public Integer getControlPort() { + return controlPort; + } + + public Integer getNetworkRateMbps() { + return networkRateMbps; + } + + public Integer getNetworkRateMulticastMbps() { + return networkRateMulticastMbps; + } +} diff --git a/core/src/com/cloud/agent/api/to/VirtualMachineTO.java b/core/src/com/cloud/agent/api/to/VirtualMachineTO.java new file mode 100644 index 00000000000..b37c2fd2426 --- /dev/null +++ b/core/src/com/cloud/agent/api/to/VirtualMachineTO.java @@ -0,0 +1,173 @@ +/** + * 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.to; + +import java.util.Map; + +import com.cloud.template.VirtualMachineTemplate.BootloaderType; +import com.cloud.vm.VirtualMachine.Type; + +public class VirtualMachineTO { + private long id; + private String name; + private BootloaderType bootloader; + Type type; + int cpus; + Integer weight; + Integer utilization; + long minRam; + long maxRam; + String hostName; + String arch; + String os; + String bootArgs; + String[] bootupScripts; + boolean rebootOnCrash; + + VolumeTO[] disks; + NicTO[] nics; + + public VirtualMachineTO() { + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Type getType() { + return type; + } + + public BootloaderType getBootloader() { + return bootloader; + } + + public void setBootloader(BootloaderType bootloader) { + this.bootloader = bootloader; + } + + public int getCpus() { + return cpus; + } + + public void setCpus(int cpus) { + this.cpus = cpus; + } + + public Integer getWeight() { + return weight; + } + + public void setWeight(Integer weight) { + this.weight = weight; + } + + public Integer getUtilization() { + return utilization; + } + + public void setUtiliziation(Integer utilization) { + this.utilization = utilization; + } + + public long getMinRam() { + return minRam; + } + + public void setRam(long minRam, long maxRam) { + this.minRam = minRam; + this.maxRam = maxRam; + } + + public long getMaxRam() { + return maxRam; + } + + public String getHostName() { + return hostName; + } + + public void setHostName(String hostName) { + this.hostName = hostName; + } + + public String getArch() { + return arch; + } + + public void setArch(String arch) { + this.arch = arch; + } + + public String getOs() { + return os; + } + + public void setOs(String os) { + this.os = os; + } + + public String getBootArgs() { + return bootArgs; + } + + public void setBootArgs(Map bootParams) { + StringBuilder buf = new StringBuilder(); + for (Map.Entry entry : bootParams.entrySet()) { + buf.append(" ").append(entry.getKey()).append("=").append(entry.getValue()); + } + bootArgs = buf.toString(); + } + + public String[] getBootupScripts() { + return bootupScripts; + } + + public void setBootupScripts(String[] bootupScripts) { + this.bootupScripts = bootupScripts; + } + + public VolumeTO[] getDisks() { + return disks; + } + + public void setDisks(VolumeTO[] disks) { + this.disks = disks; + } + + public NicTO[] getNetworks() { + return nics; + } + + public void setNics(NicTO[] nics) { + this.nics = nics; + } + +} diff --git a/core/src/com/cloud/agent/api/to/VmTO.java b/core/src/com/cloud/agent/api/to/VmTO.java deleted file mode 100644 index 5cacc391a1c..00000000000 --- a/core/src/com/cloud/agent/api/to/VmTO.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * 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.to; - -import com.cloud.vm.NetworkTO; -import com.cloud.vm.VMInstanceVO; - -public class VmTO { - private long id; - private String name; - NetworkTO[] networks; - - public VmTO() { - } - - // FIXME: Preferrably NetworkTO is constructed inside the TO objects. - // But we're press for time so I'm going to let the conversion - // happen outside. - public VmTO(VMInstanceVO instance, NetworkTO[] networks) { - id = instance.getId(); - name = instance.getName(); - this.networks = networks; - } - -} diff --git a/core/src/com/cloud/agent/api/to/VolumeTO.java b/core/src/com/cloud/agent/api/to/VolumeTO.java index 39561f9d310..15853b13098 100644 --- a/core/src/com/cloud/agent/api/to/VolumeTO.java +++ b/core/src/com/cloud/agent/api/to/VolumeTO.java @@ -18,12 +18,11 @@ package com.cloud.agent.api.to; import com.cloud.storage.Storage; -import com.cloud.storage.Storage.StorageResourceType; +import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.StoragePoolVO; import com.cloud.storage.VMTemplateStoragePoolVO; import com.cloud.storage.Volume; import com.cloud.storage.VolumeVO; -import com.cloud.storage.Storage.StoragePoolType; public class VolumeTO { @@ -39,6 +38,7 @@ public class VolumeTO { private Storage.StorageResourceType resourceType; private StoragePoolType storagePoolType; private long poolId; + private int deviceId; public VolumeTO(long id, Volume.VolumeType type, Storage.StorageResourceType resourceType, StoragePoolType poolType, String name, String mountPoint, String path, long size) { this.id = id; @@ -70,6 +70,10 @@ public class VolumeTO { this.storagePoolType = pool.getPoolType(); this.mountPoint = pool.getPath(); } + + public int getDeviceId() { + return deviceId; + } public Storage.StorageResourceType getResourceType() { return resourceType; diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index cf0a7932969..24997f1110a 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -104,6 +104,8 @@ import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.RebootRouterCommand; import com.cloud.agent.api.SetupAnswer; import com.cloud.agent.api.SetupCommand; +import com.cloud.agent.api.Start2Answer; +import com.cloud.agent.api.Start2Command; import com.cloud.agent.api.StartAnswer; import com.cloud.agent.api.StartCommand; import com.cloud.agent.api.StartConsoleProxyAnswer; @@ -141,22 +143,26 @@ import com.cloud.agent.api.storage.DownloadAnswer; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; import com.cloud.agent.api.storage.ShareAnswer; import com.cloud.agent.api.storage.ShareCommand; +import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.StoragePoolTO; +import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.api.to.VolumeTO; import com.cloud.exception.InternalErrorException; import com.cloud.host.Host.Type; import com.cloud.hypervisor.Hypervisor; +import com.cloud.network.Network.BroadcastDomainType; +import com.cloud.network.Network.TrafficType; import com.cloud.resource.ServerResource; import com.cloud.storage.Storage; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; -import com.cloud.storage.Storage.StorageResourceType; import com.cloud.storage.StorageLayer; import com.cloud.storage.StoragePoolVO; import com.cloud.storage.Volume.VolumeType; import com.cloud.storage.VolumeVO; import com.cloud.storage.resource.StoragePoolResource; import com.cloud.storage.template.TemplateInfo; +import com.cloud.template.VirtualMachineTemplate.BootloaderType; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; import com.cloud.utils.Ternary; @@ -169,6 +175,7 @@ import com.cloud.vm.DiskCharacteristics; import com.cloud.vm.DomainRouter; import com.cloud.vm.SecondaryStorageVmVO; import com.cloud.vm.State; +import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineName; import com.trilead.ssh2.SCPClient; import com.xensource.xenapi.APIVersion; @@ -683,10 +690,377 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR return execute((ModifySshKeysCommand) cmd); } else if (cmd instanceof PoolEjectCommand) { return execute((PoolEjectCommand) cmd); + } else if (cmd instanceof Start2Command) { + return execute((Start2Command)cmd); } else { return Answer.createUnsupportedCommandAnswer(cmd); } } + + Pair getNetworkForTraffic(Connection conn, TrafficType type) throws XenAPIException, XmlRpcException { + if (type == TrafficType.Guest) { + return new Pair(Network.getByUuid(conn, _host.guestNetwork), _host.guestPif); + } else if (type == TrafficType.LinkLocal) { + return new Pair(Network.getByUuid(conn, _host.linkLocalNetwork), null); + } else if (type == TrafficType.Management) { + return new Pair(Network.getByUuid(conn, _host.privateNetwork), _host.privatePif); + } else if (type == TrafficType.Public) { + return new Pair(Network.getByUuid(conn, _host.publicNetwork), _host.publicPif); + } else if (type == TrafficType.Storage) { + return new Pair(Network.getByUuid(conn, _host.storageNetwork1), _host.storagePif1); + } else if (type == TrafficType.Vpn) { + return new Pair(Network.getByUuid(conn, _host.publicNetwork), _host.publicPif); + } + + throw new CloudRuntimeException("Unsupported network type: " + type); + } + + protected VIF createVif(Connection conn, String vmName, VM vm, NicTO nic) throws XmlRpcException, XenAPIException { + VIF.Record vifr = new VIF.Record(); + vifr.VM = vm; + vifr.device = Integer.toString(nic.getDeviceId()); + vifr.MAC = nic.getMac(); + + Pair network = getNetworkForTraffic(conn, nic.getType()); + if (nic.getBroadcastType() == BroadcastDomainType.Vlan) { + vifr.network = enableVlanNetwork(conn, nic.getVlan(), network.first(), network.second()); + } else { + vifr.network = network.first(); + } + + if (nic.getNetworkRateMbps() != null) { + vifr.qosAlgorithmType = "ratelimit"; + vifr.qosAlgorithmParams = new HashMap(); + vifr.qosAlgorithmParams.put("kbps", Integer.toString(nic.getNetworkRateMbps() * 1000)); + } + + VIF vif = VIF.create(conn, vifr); + if (s_logger.isDebugEnabled()) { + vifr = vif.getRecord(conn); + s_logger.debug("Created a vif " + vifr.uuid + " on " + nic.getDeviceId()); + } + + return vif; + } + + protected VDI mount(Connection conn, String vmName, VolumeTO volume) throws XmlRpcException, XenAPIException { + if (volume.getType() == VolumeType.ISO) { + String isopath = volume.getPath(); + int index = isopath.lastIndexOf("/"); + + String mountpoint = isopath.substring(0, index); + URI uri; + try { + uri = new URI(mountpoint); + } catch (URISyntaxException e) { + throw new CloudRuntimeException("Incorrect uri " + mountpoint, e); + } + SR isoSr = createIsoSRbyURI(uri, vmName, false); + + String isoname = isopath.substring(index + 1); + + VDI isoVdi = getVDIbyLocationandSR(isoname, isoSr); + + if (isoVdi == null) { + throw new CloudRuntimeException("Unable to find ISO " + volume.getPath()); + } + return isoVdi; + } else { + return VDI.getByUuid(conn, volume.getPath()); + } + } + + protected VBD createVbd(Connection conn, String vmName, VM vm, VolumeTO volume, boolean patch) throws XmlRpcException, XenAPIException { + VolumeType type = volume.getType(); + + VDI vdi = mount(conn, vmName, volume); + + if (patch) { + if (!patchSystemVm(vdi, vmName)) { + throw new CloudRuntimeException("Unable to patch system vm"); + } + } + + VBD.Record vbdr = new VBD.Record(); + vbdr.VM = vm; + vbdr.VDI = vdi; + if (type == VolumeType.ROOT) { + vbdr.bootable = true; + } + vbdr.userdevice = Long.toString(volume.getDeviceId()); + if (volume.getType() == VolumeType.ISO) { + vbdr.mode = Types.VbdMode.RO; + vbdr.type = Types.VbdType.CD; + } else { + vbdr.mode = Types.VbdMode.RW; + vbdr.type = Types.VbdType.DISK; + + } + + VBD vbd = VBD.create(conn, vbdr); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("VBD " + vbd.getUuid(conn) + " created for " + volume); + } + + return vbd; + } + + protected Pair createVmFromTemplate(Connection conn, VirtualMachineTO vmSpec, Host host) throws XenAPIException, XmlRpcException { + String guestOsTypeName = getGuestOsType(vmSpec.getOs()); + Set templates = VM.getByNameLabel(conn, guestOsTypeName); + assert templates.size() == 1 : "Should only have 1 template but found " + templates.size(); + VM template = templates.iterator().next(); + + VM vm = template.createClone(conn, vmSpec.getName()); + vm.setAffinity(conn, host); + + VM.Record vmr = vm.getRecord(conn); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Created VM " + vmr.uuid + " for " + vmSpec.getName()); + } + + for (Console console : vmr.consoles) { + console.destroy(conn); + } + + vm.setIsATemplate(conn, false); + vm.removeFromOtherConfig(conn, "disks"); + vm.setNameLabel(conn, vmSpec.getName()); + setMemory(conn, vm, vmSpec.getMinRam()); + vm.setVCPUsAtStartup(conn, (long)vmSpec.getCpus()); + vm.setVCPUsMax(conn, (long)vmSpec.getCpus()); + vm.setVCPUsNumberLive(conn, (long)vmSpec.getCpus()); + + Map vcpuParams = new HashMap(); + + if (vmSpec.getWeight() != null) { + vcpuParams.put("weight", Integer.toString(vmSpec.getWeight())); + } + if (vmSpec.getUtilization() != null) { + vcpuParams.put("cap", Integer.toString(vmSpec.getUtilization())); + } + if (vcpuParams.size() > 0) { + vm.setVCPUsParams(conn, vcpuParams); + } + + vm.setActionsAfterCrash(conn, Types.OnCrashBehaviour.DESTROY); + vm.setActionsAfterShutdown(conn, Types.OnNormalExit.DESTROY); + + String bootArgs = vmSpec.getBootArgs(); + if (bootArgs != null && bootArgs.length() > 0) { + String pvargs = vm.getPVArgs(conn); + pvargs = pvargs + vmSpec.getBootArgs(); + if (s_logger.isDebugEnabled()) { + s_logger.debug("PV args are " + pvargs); + } + vm.setPVArgs(conn, pvargs); + } + + if (!(guestOsTypeName.startsWith("Windows") || guestOsTypeName.startsWith("Citrix") || guestOsTypeName.startsWith("Other"))) { + if (vmSpec.getBootloader() == BootloaderType.CD) { + vm.setPVBootloader(conn, "eliloader"); + vm.addToOtherConfig(conn, "install-repository", "cdrom"); + } else if (vmSpec.getBootloader() == BootloaderType.PyGrub ){ + vm.setPVBootloader(conn, "pygrub"); + } else { + vm.destroy(conn); + throw new CloudRuntimeException("Unable to handle boot loader type: " + vmSpec.getBootloader()); + } + } + + return new Pair(vm, vmr.uuid); + } + + protected String handleVmStartFailure(String vmName, VM vm, String message, Throwable th) { + String msg = "Unable to start " + vmName + " due to " + message; + s_logger.warn(msg, th); + + if (vm == null) { + return msg; + } + + Connection conn = getConnection(); + try { + VM.Record vmr = vm.getRecord(conn); + if (vmr.powerState == VmPowerState.RUNNING) { + try { + vm.hardShutdown(conn); + } catch (Exception e) { + s_logger.warn("VM hardshutdown failed due to ", e); + } + } + if (vm.getPowerState(conn) == VmPowerState.HALTED) { + try { + vm.destroy(conn); + } catch (Exception e) { + s_logger.warn("VM destroy failed due to ", e); + } + } + for (VBD vbd : vmr.VBDs) { + try { + vbd.unplug(conn); + vbd.destroy(conn); + } catch (Exception e) { + s_logger.warn("Unable to clean up VBD due to ", e); + } + } + for (VIF vif : vmr.VIFs) { + try { + vif.unplug(conn); + vif.destroy(conn); + } catch (Exception e) { + s_logger.warn("Unable to cleanup VIF", e); + } + } + } catch (Exception e) { + s_logger.warn("VM getRecord failed due to ", e); + } + + return msg; + } + + protected Start2Answer execute(Start2Command cmd) { + VirtualMachineTO vmSpec = cmd.getVirtualMachine(); + String vmName = vmSpec.getName(); + + Connection conn = getConnection(); + State state = State.Stopped; + VM vm = null; + try { + Host host = Host.getByUuid(conn, _host.uuid); + synchronized (_vms) { + _vms.put(vmName, State.Starting); + } + + Pair v = createVmFromTemplate(conn, vmSpec, host); + vm = v.first(); + String vmUuid = v.second(); + + for (VolumeTO disk : vmSpec.getDisks()) { + createVbd(conn, vmName, vm, disk, disk.getType() == VolumeType.ROOT && vmSpec.getType() != VirtualMachine.Type.User); + } + + NicTO controlNic = null; + for (NicTO nic : vmSpec.getNetworks()) { + if (nic.getControlPort() != null) { + controlNic = nic; + } + createVif(conn, vmName, vm, nic); + } + + /* + * + VBD.Record vbdr = new VBD.Record(); + Ternary mount = mounts.get(0); + vbdr.VM = vm; + vbdr.VDI = mount.second(); + vbdr.bootable = !bootFromISO; + vbdr.userdevice = "0"; + vbdr.mode = Types.VbdMode.RW; + vbdr.type = Types.VbdType.DISK; + VBD.create(conn, vbdr); + + for (int i = 1; i < mounts.size(); i++) { + mount = mounts.get(i); + // vdi.setNameLabel(conn, cmd.getVmName() + "-DATA"); + vbdr.VM = vm; + vbdr.VDI = mount.second(); + vbdr.bootable = false; + vbdr.userdevice = Long.toString(mount.third().getDeviceId()); + vbdr.mode = Types.VbdMode.RW; + vbdr.type = Types.VbdType.DISK; + vbdr.unpluggable = true; + VBD.create(conn, vbdr); + + } + + VBD.Record cdromVBDR = new VBD.Record(); + cdromVBDR.VM = vm; + cdromVBDR.empty = true; + cdromVBDR.bootable = bootFromISO; + cdromVBDR.userdevice = "3"; + cdromVBDR.mode = Types.VbdMode.RO; + cdromVBDR.type = Types.VbdType.CD; + VBD cdromVBD = VBD.create(conn, cdromVBDR); + + String isopath = cmd.getISOPath(); + if (isopath != null) { + int index = isopath.lastIndexOf("/"); + + String mountpoint = isopath.substring(0, index); + URI uri = new URI(mountpoint); + isosr = createIsoSRbyURI(uri, cmd.getVmName(), false); + + String isoname = isopath.substring(index + 1); + + VDI isovdi = getVDIbyLocationandSR(isoname, isosr); + + if (isovdi == null) { + String msg = " can not find ISO " + cmd.getISOPath(); + s_logger.warn(msg); + return new StartAnswer(cmd, msg); + } else { + cdromVBD.insert(conn, isovdi); + } + + } + */ + + vm.startOn(conn, host, false, true); + + if (_canBridgeFirewall) { + String result = null; + if (vmSpec.getType() != VirtualMachine.Type.User) { + result = callHostPlugin("vmops", "default_network_rules_systemvm", "vmName", vmName); + } else { + } + + if (result == null || result.isEmpty() || !Boolean.parseBoolean(result)) { + s_logger.warn("Failed to program default network rules for " + vmName); + } else { + s_logger.info("Programmed default network rules for " + vmName); + } + } + + if (controlNic != null) { + String privateIp = controlNic.getIp(); + int cmdPort = controlNic.getControlPort(); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Ping command port, " + privateIp + ":" + cmdPort); + } + + String result = connect(vmName, privateIp, cmdPort); + if (result != null) { + throw new CloudRuntimeException("Can not ping System vm " + vmName + "due to:" + result); + } + if (s_logger.isDebugEnabled()) { + s_logger.debug("Ping command port succeeded for vm " + vmName); + } + } + + state = State.Running; + return new Start2Answer(cmd); + } catch (XmlRpcException e) { + String msg = handleVmStartFailure(vmName, vm, "", e); + return new Start2Answer(cmd, msg); + } catch (XenAPIException e) { + String msg = handleVmStartFailure(vmName, vm, "", e); + return new Start2Answer(cmd, msg); + } catch (Exception e) { + String msg = handleVmStartFailure(vmName, vm, "", e); + return new Start2Answer(cmd, msg); + } finally { + synchronized (_vms) { + if (state != State.Stopped) { + _vms.put(vmName, state); + } else { + _vms.remove(vmName); + } + } + } + } protected Answer execute(ModifySshKeysCommand cmd) { String publickey = cmd.getPubKey(); @@ -1695,6 +2069,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR } } + @Override public DownloadAnswer execute(final PrimaryStorageDownloadCommand cmd) { SR tmpltsr = null; String tmplturl = cmd.getUrl(); @@ -3292,6 +3667,45 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR return null; } + protected synchronized Network getNetworkByName(Connection conn, String name, boolean lookForPif) throws XenAPIException, XmlRpcException { + Network found = null; + Set networks = Network.getByNameLabel(conn, name); + if (networks.size() == 1) { + found = networks.iterator().next(); + } else if (networks.size() > 1) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Found more than one network with the name " + name); + } + for (Network network : networks) { + if (!lookForPif) { + found = network; + break; + } + + Network.Record netr = network.getRecord(conn); + s_logger.debug("Checking network " + netr.uuid); + if (netr.PIFs.size() == 0) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Network " + netr.uuid + " has no pifs so skipping that."); + } + } else { + for (PIF pif : netr.PIFs) { + PIF.Record pifr = pif.getRecord(conn); + if (_host.uuid.equals(pifr.host.getUuid(conn))) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Network " + netr.uuid + " has a pif " + pifr.uuid + " for our host "); + } + found = network; + break; + } + } + } + } + } + + return found; + } + protected Network enableVlanNetwork(long tag, String networkUuid, String pifUuid) throws XenAPIException, XmlRpcException { // In XenServer, vlan is added by // 1. creating a network. @@ -3344,6 +3758,60 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR return vlanNetwork; } + protected Network enableVlanNetwork(Connection conn, long tag, Network network, String pifUuid) throws XenAPIException, XmlRpcException { + // In XenServer, vlan is added by + // 1. creating a network. + // 2. creating a vlan associating network with the pif. + // We always create + // 1. a network with VLAN[vlan id in decimal] + // 2. a vlan associating the network created with the pif to private + // network. + + Network vlanNetwork = null; + String name = "VLAN" + Long.toString(tag); + + vlanNetwork = getNetworkByName(conn, name, true); + if (vlanNetwork == null) { // Can't find it, then create it. + if (s_logger.isDebugEnabled()) { + s_logger.debug("Creating VLAN network for " + tag + " on host " + _host.ip); + } + Network.Record nwr = new Network.Record(); + nwr.nameLabel = name; + nwr.bridge = name; + vlanNetwork = Network.create(conn, nwr); + } + + PIF nPif = PIF.getByUuid(conn, pifUuid); + PIF.Record nPifr = nPif.getRecord(conn); + + Network.Record vlanNetworkr = vlanNetwork.getRecord(conn); + if (vlanNetworkr.PIFs != null) { + for (PIF pif : vlanNetworkr.PIFs) { + PIF.Record pifr = pif.getRecord(conn); + if (pifr.device.equals(nPifr.device) && pifr.host.equals(nPifr.host)) { + pif.plug(conn); + return vlanNetwork; + } + } + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Creating VLAN " + tag + " on host " + _host.ip + " on device " + nPifr.device); + } + VLAN vlan = VLAN.create(conn, nPif, tag, vlanNetwork); + VLAN.Record vlanr = vlan.getRecord(conn); + if (s_logger.isDebugEnabled()) { + s_logger.debug("VLAN is created for " + tag + ". The uuid is " + vlanr.uuid); + } + + PIF untaggedPif = vlanr.untaggedPIF; + if (!untaggedPif.getCurrentlyAttached(conn)) { + untaggedPif.plug(conn); + } + + return vlanNetwork; + } + protected void disableVlanNetwork(Network network) throws InternalErrorException { try { Connection conn = getConnection(); @@ -4263,6 +4731,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR } } + @Override public CreateAnswer execute(CreateCommand cmd) { StoragePoolTO pool = cmd.getPool(); DiskCharacteristics dskch = cmd.getDiskCharacteristics(); @@ -4762,6 +5231,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR } } + @Override public Answer execute(DestroyCommand cmd) { VolumeTO vol = cmd.getVolume(); @@ -4805,6 +5275,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR return new Answer(cmd, true, "Success"); } + @Override public ShareAnswer execute(final ShareCommand cmd) { if (!cmd.isShare()) { SR sr = getISOSRbyVmName(cmd.getVmName()); @@ -4824,6 +5295,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR return new ShareAnswer(cmd, new HashMap()); } + @Override public CopyVolumeAnswer execute(final CopyVolumeCommand cmd) { String volumeUUID = cmd.getVolumePath(); StoragePoolVO pool = cmd.getPool(); @@ -6076,10 +6548,12 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR _agentControl = agentControl; } + @Override public boolean IsRemoteAgent() { return _isRemoteAgent; } + @Override public void setRemoteAgent(boolean remote) { _isRemoteAgent = remote; } diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 5f87093cb8a..21ee3bcd874 100644 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -77,6 +77,14 @@ DROP TABLE IF EXISTS `cloud`.`nics`; DROP TABLE IF EXISTS `cloud`.`network_profiles`; DROP TABLE IF EXISTS `cloud`.`network_offerings`; DROP TABLE IF EXISTS `cloud`.`host_master`; +DROP TABLE IF EXISTS `cloud`.`hypervisor_properties`; + +CREATE TABLE `cloud`.`hypervsior_properties` ( + `hypervisor` varchar(32) NOT NULL UNIQUE COMMENT 'hypervisor type', + `max_storage_devices` int(10) NOT NULL COMMENT 'maximum number of storage devices', + `cdrom_device` int(10) NOT NULL COMMENT 'device id reserved for cdrom', + `max_network_devices` int(10) NOT NULL COMMENT 'maximum number of network devices', +) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `cloud`.`network_profiles` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', From 40a78f166eea8200a00ce24cec9331ffabb191a0 Mon Sep 17 00:00:00 2001 From: "Manuel Amador (Rudd-O)" Date: Fri, 20 Aug 2010 14:02:41 -0700 Subject: [PATCH 12/17] build-cloud.xml build-cloud FAILS until now. It had references to files in directories that were moved. --- build/build-cloud.xml | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/build/build-cloud.xml b/build/build-cloud.xml index ccea6bd8138..db9e5a7c5af 100755 --- a/build/build-cloud.xml +++ b/build/build-cloud.xml @@ -273,26 +273,22 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + From bf3db195edf13392e828eabe5dd7a758a9e19f7c Mon Sep 17 00:00:00 2001 From: Edison Su Date: Fri, 20 Aug 2010 18:51:17 -0400 Subject: [PATCH 13/17] fix typo --- setup/db/create-schema.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 21ee3bcd874..43098ef070c 100644 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -83,7 +83,7 @@ CREATE TABLE `cloud`.`hypervsior_properties` ( `hypervisor` varchar(32) NOT NULL UNIQUE COMMENT 'hypervisor type', `max_storage_devices` int(10) NOT NULL COMMENT 'maximum number of storage devices', `cdrom_device` int(10) NOT NULL COMMENT 'device id reserved for cdrom', - `max_network_devices` int(10) NOT NULL COMMENT 'maximum number of network devices', + `max_network_devices` int(10) NOT NULL COMMENT 'maximum number of network devices' ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `cloud`.`network_profiles` ( From 440662c9383a56c2f5393e0418ddda7378192dbe Mon Sep 17 00:00:00 2001 From: jessica Date: Fri, 20 Aug 2010 16:19:51 -0700 Subject: [PATCH 14/17] Issue #: 5986 Volume page - grid - make action links stay left-aligned --- ui/content/tab_storage.html | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ui/content/tab_storage.html b/ui/content/tab_storage.html index 90c75b95dba..f11ad64b1ef 100644 --- a/ui/content/tab_storage.html +++ b/ui/content/tab_storage.html @@ -611,7 +611,11 @@
Name
+<<<<<<< HEAD
+======= +
+>>>>>>> 418f895... Issue #: 5986
Type
@@ -631,7 +635,7 @@
Size
-
+
State
@@ -703,7 +707,11 @@
Name
+<<<<<<< HEAD
+======= +
+>>>>>>> 418f895... Issue #: 5986
Type
@@ -723,7 +731,7 @@
size
-
+
state
From 65b9f29941446a4dbcf2ede52f9723be7cd61059 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Thu, 19 Aug 2010 14:28:18 -0700 Subject: [PATCH 15/17] Issue #: 5975 (1) API-side: make listDomains, ListDomainChildren return all items (2) UI-side: make domains page show all domains by specifying pageSize=-1 --- .../cloud/api/commands/ListDomainChildrenCmd.java | 8 +++++++- .../src/com/cloud/api/commands/ListDomainsCmd.java | 8 +++++++- ui/scripts/cloud.core.domains.js | 12 ++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/server/src/com/cloud/api/commands/ListDomainChildrenCmd.java b/server/src/com/cloud/api/commands/ListDomainChildrenCmd.java index 6e17f9a862a..605e332627d 100644 --- a/server/src/com/cloud/api/commands/ListDomainChildrenCmd.java +++ b/server/src/com/cloud/api/commands/ListDomainChildrenCmd.java @@ -89,7 +89,13 @@ public class ListDomainChildrenCmd extends BaseCmd { } } - Criteria c = new Criteria("id", Boolean.TRUE, startIndex, Long.valueOf(pageSizeNum)); + //temporary solution at API level. We need a permanent solution for all "listXXXXXXX & pageSize = -1" in the future. + Criteria c; + if(pageSizeNum != -1) + c = new Criteria("id", Boolean.TRUE, startIndex, Long.valueOf(pageSizeNum)); + else + c = new Criteria("id", Boolean.TRUE, null, null); + if (keyword != null) { c.addCriteria(Criteria.KEYWORD, keyword); diff --git a/server/src/com/cloud/api/commands/ListDomainsCmd.java b/server/src/com/cloud/api/commands/ListDomainsCmd.java index 6b503a14fee..b722e9f1951 100644 --- a/server/src/com/cloud/api/commands/ListDomainsCmd.java +++ b/server/src/com/cloud/api/commands/ListDomainsCmd.java @@ -85,7 +85,13 @@ public class ListDomainsCmd extends BaseCmd { startIndex = Long.valueOf(pageSizeNum * (pageNum-1)); } } - Criteria c = new Criteria("id", Boolean.TRUE, startIndex, Long.valueOf(pageSizeNum)); + + //temporary solution at API level. We need a permanent solution for all "listXXXXXXX & pageSize = -1" in the future. + Criteria c; + if(pageSizeNum != -1) + c = new Criteria("id", Boolean.TRUE, startIndex, Long.valueOf(pageSizeNum)); + else + c = new Criteria("id", Boolean.TRUE, null, null); if (keyword != null) { c.addCriteria(Criteria.KEYWORD, keyword); diff --git a/ui/scripts/cloud.core.domains.js b/ui/scripts/cloud.core.domains.js index 921b158b177..7e57eebc5e1 100644 --- a/ui/scripts/cloud.core.domains.js +++ b/ui/scripts/cloud.core.domains.js @@ -66,7 +66,11 @@ function showDomainsTab() { function drawTree(id, level, container) { $.ajax({ +<<<<<<< HEAD data: createURL("command=listDomainChildren&id="+id+"&response=json"), +======= + data: "command=listDomainChildren&id="+id+"&response=json&pageSize=-1", +>>>>>>> e8446f8... Issue #: 5975 dataType: "json", async: false, success: function(json) { @@ -321,7 +325,11 @@ function showDomainsTab() { rightPanelSearchResult.show(); var keyword = searchInput.val(); $.ajax({ +<<<<<<< HEAD data: createURL("command=listDomains&keyword="+keyword+"&response=json"+maxPageSize), +======= + data: "command=listDomains&keyword="+keyword+"&response=json&pageSize=-1", //pageSize=-1 will return all items (no limitation) +>>>>>>> e8446f8... Issue #: 5975 dataType: "json", async: false, success: function(json) { @@ -350,7 +358,11 @@ function showDomainsTab() { function drawRootNode(rootDomainId) { treeContentBox.empty(); $.ajax({ +<<<<<<< HEAD data: createURL("command=listDomains&id="+rootDomainId+"&response=json"), +======= + data: "command=listDomains&id="+rootDomainId+"&response=json&pageSize=-1", //pageSize=-1 will return all items (no limitation) +>>>>>>> e8446f8... Issue #: 5975 dataType: "json", async: false, success: function(json) { From c17cda2a37bcb0eb5ba01f2ceb5add0403f70925 Mon Sep 17 00:00:00 2001 From: jessica Date: Fri, 20 Aug 2010 18:15:24 -0700 Subject: [PATCH 16/17] resolve failed merge markers --- ui/content/tab_storage.html | 8 -------- ui/scripts/cloud.core.domains.js | 24 ++++++------------------ 2 files changed, 6 insertions(+), 26 deletions(-) diff --git a/ui/content/tab_storage.html b/ui/content/tab_storage.html index f11ad64b1ef..3abfa48568f 100644 --- a/ui/content/tab_storage.html +++ b/ui/content/tab_storage.html @@ -611,11 +611,7 @@
Name
-<<<<<<< HEAD -
-=======
->>>>>>> 418f895... Issue #: 5986
Type
@@ -707,11 +703,7 @@
Name
-<<<<<<< HEAD -
-=======
->>>>>>> 418f895... Issue #: 5986
Type
diff --git a/ui/scripts/cloud.core.domains.js b/ui/scripts/cloud.core.domains.js index 7e57eebc5e1..db94223d8f1 100644 --- a/ui/scripts/cloud.core.domains.js +++ b/ui/scripts/cloud.core.domains.js @@ -65,12 +65,8 @@ function showDomainsTab() { } function drawTree(id, level, container) { - $.ajax({ -<<<<<<< HEAD - data: createURL("command=listDomainChildren&id="+id+"&response=json"), -======= - data: "command=listDomainChildren&id="+id+"&response=json&pageSize=-1", ->>>>>>> e8446f8... Issue #: 5975 + $.ajax({ + data: "command=listDomainChildren&id="+id+"&response=json&pageSize=-1", dataType: "json", async: false, success: function(json) { @@ -324,12 +320,8 @@ function showDomainsTab() { rightPanelDetailContent.hide(); rightPanelSearchResult.show(); var keyword = searchInput.val(); - $.ajax({ -<<<<<<< HEAD - data: createURL("command=listDomains&keyword="+keyword+"&response=json"+maxPageSize), -======= - data: "command=listDomains&keyword="+keyword+"&response=json&pageSize=-1", //pageSize=-1 will return all items (no limitation) ->>>>>>> e8446f8... Issue #: 5975 + $.ajax({ + data: "command=listDomains&keyword="+keyword+"&response=json&pageSize=-1", //pageSize=-1 will return all items (no limitation) dataType: "json", async: false, success: function(json) { @@ -357,12 +349,8 @@ function showDomainsTab() { //draw root node function drawRootNode(rootDomainId) { treeContentBox.empty(); - $.ajax({ -<<<<<<< HEAD - data: createURL("command=listDomains&id="+rootDomainId+"&response=json"), -======= - data: "command=listDomains&id="+rootDomainId+"&response=json&pageSize=-1", //pageSize=-1 will return all items (no limitation) ->>>>>>> e8446f8... Issue #: 5975 + $.ajax({ + data: "command=listDomains&id="+rootDomainId+"&response=json&pageSize=-1", //pageSize=-1 will return all items (no limitation) dataType: "json", async: false, success: function(json) { From 89cd3131bf12ba67113f5794018e625ea4d9b5d9 Mon Sep 17 00:00:00 2001 From: kishan Date: Mon, 23 Aug 2010 17:19:31 +0530 Subject: [PATCH 17/17] add zone id for create template event --- .../com/cloud/async/executor/CreatePrivateTemplateExecutor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/com/cloud/async/executor/CreatePrivateTemplateExecutor.java b/server/src/com/cloud/async/executor/CreatePrivateTemplateExecutor.java index 32fda8b7ac9..d1f13bbcdf0 100644 --- a/server/src/com/cloud/async/executor/CreatePrivateTemplateExecutor.java +++ b/server/src/com/cloud/async/executor/CreatePrivateTemplateExecutor.java @@ -145,7 +145,7 @@ public class CreatePrivateTemplateExecutor extends VolumeOperationExecutor { jobStatus = AsyncJobResult.STATUS_SUCCEEDED; resultCode = 0; details = null; - String eventParams = "id="+template.getId()+"\nname=" + template.getName() +"\nsize="+volume.getSize(); + String eventParams = "id="+template.getId()+"\nname=" + template.getName() +"\nsize="+volume.getSize()+ "\ndcId="+volume.getDataCenterId(); managerServer.saveEvent(param.getUserId(), param.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_TEMPLATE_CREATE, "Successfully created Template " +param.getName(), eventParams ,param.getEventId()); resultObject = composeResultObject(template, templateHostRef, volume.getDataCenterId()); }