content: // Licensed to the Apache Software Foundation (ASF) under one
  // or more contributor license agreements.  See the NOTICE file
  // distributed with this work for additional information
  // regarding copyright ownership.  The ASF licenses this file
  // to you under the Apache License, Version 2.0 (the
  // "License"); you may not use this file except in compliance
  // with the License.  You may obtain a copy of the License at
  //
  //   http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing,
  // software distributed under the License is distributed on an
  // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  // KIND, either express or implied.  See the License for the
  // specific language governing permissions and limitations
  // under the License.
  package com.cloud.consoleproxy;
  
  import java.util.Map;
  
  import javax.inject.Inject;
  import javax.naming.ConfigurationException;
  
  import com.cloud.dc.dao.HostPodDao;
  import org.apache.cloudstack.consoleproxy.ConsoleAccessManager;
  import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
  import org.apache.cloudstack.framework.security.keys.KeysManager;
  import org.apache.cloudstack.framework.security.keystore.KeystoreManager;
  
  import com.cloud.agent.AgentManager;
  import com.cloud.agent.api.GetVncPortAnswer;
  import com.cloud.agent.api.GetVncPortCommand;
  import com.cloud.agent.api.StartupProxyCommand;
  import com.cloud.deploy.DeploymentPlanner;
  import com.cloud.host.HostVO;
  import com.cloud.host.dao.HostDao;
  import com.cloud.info.ConsoleProxyInfo;
  import com.cloud.server.ManagementServer;
  import com.cloud.utils.NumbersUtil;
  import com.cloud.utils.component.ManagerBase;
  import com.cloud.vm.ConsoleProxyVO;
  import com.cloud.vm.VMInstanceVO;
  import com.cloud.vm.VirtualMachine;
  import com.cloud.vm.VirtualMachineManager;
  import com.cloud.vm.VirtualMachineProfile;
  import com.cloud.vm.dao.ConsoleProxyDao;
  import com.cloud.vm.dao.UserVmDao;
  import com.cloud.vm.dao.VMInstanceDao;
  
  public class AgentBasedConsoleProxyManager extends ManagerBase implements ConsoleProxyManager {
  
      @Inject
      protected HostDao _hostDao;
      @Inject
      protected HostPodDao podDao;
      @Inject
      protected UserVmDao _userVmDao;
      protected String _consoleProxyUrlDomain;
      @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;
      @Inject
      VirtualMachineManager _itMgr;
      @Inject
      protected ConsoleProxyDao _cpDao;
      @Inject
      protected KeystoreManager _ksMgr;
      @Inject
      protected ConsoleAccessManager consoleAccessManager;
  
      @Inject
      ConfigurationDao _configDao;
      @Inject
      ManagementServer _ms;
      @Inject
      KeysManager _keysMgr;
  
      public class AgentBasedAgentHook extends AgentHookBase {
  
          public AgentBasedAgentHook(VMInstanceDao instanceDao, HostDao hostDao, ConfigurationDao cfgDao, KeystoreManager ksMgr,
                                     AgentManager agentMgr, KeysManager keysMgr, ConsoleAccessManager consoleAccessManager) {
              super(instanceDao, hostDao, cfgDao, ksMgr, agentMgr, keysMgr, consoleAccessManager);
          }
  
          @Override
          protected HostVO findConsoleProxyHost(StartupProxyCommand cmd) {
              return _hostDao.findByGuid(cmd.getGuid());
          }
  
      }
  
      public int getVncPort(VMInstanceVO vm) {
          if (vm.getHostId() == null) {
              return -1;
          }
          GetVncPortAnswer answer = (GetVncPortAnswer)_agentMgr.easySend(vm.getHostId(), new GetVncPortCommand(vm.getId(), vm.getHostName()));
          return (answer == null || !answer.getResult()) ? -1 : answer.getPort();
      }
  
      @Override
      public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
  
          if (logger.isInfoEnabled()) {
              logger.info("Start configuring AgentBasedConsoleProxyManager");
          }
  
          Map<String, String> 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);
          }
  
          value = configs.get("consoleproxy.port");
          if (value != null) {
              _consoleProxyPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT);
          }
  
          Boolean sslEnabled = ConsoleProxySslEnabled.value();
          if (Boolean.TRUE.equals(sslEnabled)) {
              _sslEnabled = true;
          }
  
          _consoleProxyUrlDomain = ConsoleProxyUrlDomain.value();
  
          _listener = new ConsoleProxyListener(new AgentBasedAgentHook(_instanceDao, _hostDao, _configDao, _ksMgr,
                  _agentMgr, _keysMgr, consoleAccessManager));
          _agentMgr.registerForHostEvents(_listener, true, true, false);
  
          if (logger.isInfoEnabled()) {
              logger.info("AgentBasedConsoleProxyManager has been configured. SSL enabled: " + _sslEnabled);
          }
          return true;
      }
  
      HostVO findHost(VMInstanceVO vm) {
          return _hostDao.findById(vm.getHostId());
      }
  
      @Override
      public ConsoleProxyInfo assignProxy(long dataCenterId, VMInstanceVO userVm) {
          HostVO host = findHost(userVm);
          if (host != null) {
              if (logger.isDebugEnabled()) {
                  logger.debug("Assign embedded console proxy running at {} to user vm {} with public IP {}", host, userVm, 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 (logger.isDebugEnabled()) {
                      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();
              }
  
              _sslEnabled = ConsoleProxySslEnabled.valueIn(dataCenterId);
              _consoleProxyUrlDomain = ConsoleProxyUrlDomain.valueIn(dataCenterId);
              return new ConsoleProxyInfo(_sslEnabled, publicIp, _consoleProxyPort, urlPort, _consoleProxyUrlDomain);
          } else {
              logger.warn("Host that VM is running is no longer available, console access to VM {} will be temporarily unavailable.", userVm);
          }
          return null;
      }
  
      @Override
      public ConsoleProxyVO startProxy(long proxyVmId, boolean ignoreRestartSetting) {
          return null;
      }
  
      @Override
      public void startProxyForHA(VirtualMachine vm, Map<VirtualMachineProfile.Param, Object> params,
              DeploymentPlanner planner) {
      }
  
      @Override
      public boolean destroyProxy(long proxyVmId) {
          return false;
      }
  
      @Override
      public int getVncPort(Long dataCenterId) {
          return _consoleProxyPort;
      }
  
      @Override
      public boolean rebootProxy(long proxyVmId) {
          return false;
      }
  
      @Override
      public boolean stopProxy(long proxyVmId) {
          return false;
      }
  
      @Override
      public void setManagementState(ConsoleProxyManagementState state) {
      }
  
      @Override
      public ConsoleProxyManagementState getManagementState() {
          return null;
      }
  
      @Override
      public void resumeLastManagementState() {
      }
  
      @Override
      public String getName() {
          return _name;
      }
  }
  