| // 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.nio.charset.Charset; |
| import java.util.ArrayList; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.UUID; |
| |
| import javax.ejb.Local; |
| import javax.inject.Inject; |
| import javax.naming.ConfigurationException; |
| |
| import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; |
| import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; |
| import org.apache.log4j.Logger; |
| |
| import com.cloud.agent.AgentManager; |
| import com.cloud.agent.api.Answer; |
| import com.cloud.agent.api.ConsoleProxyLoadReportCommand; |
| import com.cloud.agent.api.RebootCommand; |
| import com.cloud.agent.api.StartupCommand; |
| import com.cloud.agent.api.StartupProxyCommand; |
| import com.cloud.agent.api.StopAnswer; |
| import com.cloud.agent.api.check.CheckSshAnswer; |
| import com.cloud.agent.api.check.CheckSshCommand; |
| import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer; |
| import com.cloud.agent.api.to.NicTO; |
| import com.cloud.agent.api.to.VirtualMachineTO; |
| import com.cloud.agent.manager.Commands; |
| import com.cloud.certificate.dao.CertificateDao; |
| import com.cloud.cluster.ClusterManager; |
| import com.cloud.configuration.Config; |
| import com.cloud.configuration.ZoneConfig; |
| import com.cloud.configuration.dao.ConfigurationDao; |
| import com.cloud.dc.DataCenter; |
| import com.cloud.dc.DataCenter.NetworkType; |
| import com.cloud.dc.DataCenterVO; |
| import com.cloud.dc.HostPodVO; |
| import com.cloud.dc.dao.DataCenterDao; |
| import com.cloud.dc.dao.HostPodDao; |
| import com.cloud.deploy.DataCenterDeployment; |
| import com.cloud.deploy.DeployDestination; |
| import com.cloud.exception.ConcurrentOperationException; |
| import com.cloud.exception.InsufficientCapacityException; |
| import com.cloud.exception.ResourceUnavailableException; |
| import com.cloud.exception.StorageUnavailableException; |
| import com.cloud.host.Host; |
| import com.cloud.host.Host.Type; |
| import com.cloud.host.HostVO; |
| import com.cloud.host.dao.HostDao; |
| import com.cloud.hypervisor.Hypervisor.HypervisorType; |
| 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; |
| import com.cloud.info.RunningHostInfoAgregator; |
| import com.cloud.info.RunningHostInfoAgregator.ZoneHostInfo; |
| import com.cloud.keystore.KeystoreDao; |
| import com.cloud.keystore.KeystoreManager; |
| import com.cloud.keystore.KeystoreVO; |
| import com.cloud.network.Network; |
| import com.cloud.network.NetworkManager; |
| import com.cloud.network.NetworkModel; |
| import com.cloud.network.Networks.TrafficType; |
| import com.cloud.network.dao.IPAddressDao; |
| import com.cloud.network.dao.IPAddressVO; |
| import com.cloud.network.dao.NetworkDao; |
| import com.cloud.network.dao.NetworkVO; |
| import com.cloud.network.rules.RulesManager; |
| import com.cloud.offering.DiskOffering; |
| import com.cloud.offering.NetworkOffering; |
| import com.cloud.offering.ServiceOffering; |
| import com.cloud.offerings.dao.NetworkOfferingDao; |
| import com.cloud.resource.ResourceManager; |
| import com.cloud.resource.ResourceStateAdapter; |
| import com.cloud.resource.ServerResource; |
| import com.cloud.resource.UnableDeleteHostException; |
| import com.cloud.server.ManagementServer; |
| import com.cloud.service.ServiceOfferingVO; |
| import com.cloud.service.dao.ServiceOfferingDao; |
| import com.cloud.servlet.ConsoleProxyPasswordBasedEncryptor; |
| import com.cloud.storage.StorageManager; |
| import com.cloud.storage.StoragePoolStatus; |
| import com.cloud.storage.VMTemplateHostVO; |
| import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; |
| import com.cloud.storage.VMTemplateVO; |
| import com.cloud.storage.dao.DiskOfferingDao; |
| import com.cloud.storage.dao.VMTemplateDao; |
| import com.cloud.storage.dao.VMTemplateHostDao; |
| import com.cloud.template.TemplateManager; |
| import com.cloud.user.Account; |
| import com.cloud.user.AccountManager; |
| import com.cloud.user.User; |
| import com.cloud.user.UserContext; |
| import com.cloud.utils.DateUtil; |
| import com.cloud.utils.NumbersUtil; |
| import com.cloud.utils.Pair; |
| import com.cloud.utils.component.ManagerBase; |
| import com.cloud.utils.db.DB; |
| import com.cloud.utils.db.GlobalLock; |
| import com.cloud.utils.db.SearchCriteria.Op; |
| import com.cloud.utils.db.SearchCriteria2; |
| import com.cloud.utils.db.SearchCriteriaService; |
| import com.cloud.utils.db.Transaction; |
| import com.cloud.utils.events.SubscriptionMgr; |
| import com.cloud.utils.exception.CloudRuntimeException; |
| import com.cloud.utils.net.NetUtils; |
| import com.cloud.vm.ConsoleProxyVO; |
| import com.cloud.vm.NicProfile; |
| import com.cloud.vm.ReservationContext; |
| import com.cloud.vm.SystemVmLoadScanHandler; |
| import com.cloud.vm.SystemVmLoadScanner; |
| import com.cloud.vm.SystemVmLoadScanner.AfterScanAction; |
| import com.cloud.vm.VMInstanceVO; |
| import com.cloud.vm.VirtualMachine; |
| import com.cloud.vm.VirtualMachine.State; |
| import com.cloud.vm.VirtualMachineGuru; |
| import com.cloud.vm.VirtualMachineManager; |
| import com.cloud.vm.VirtualMachineName; |
| import com.cloud.vm.VirtualMachineProfile; |
| import com.cloud.vm.dao.ConsoleProxyDao; |
| import com.cloud.vm.dao.UserVmDetailsDao; |
| import com.cloud.vm.dao.VMInstanceDao; |
| import com.google.gson.Gson; |
| import com.google.gson.GsonBuilder; |
| |
| // |
| // Possible console proxy state transition cases |
| // Stopped --> Starting -> Running |
| // HA -> Stopped -> Starting -> Running |
| // Migrating -> Running (if previous state is Running before it enters into Migrating state |
| // Migrating -> Stopped (if previous state is not Running before it enters into Migrating state) |
| // Running -> HA (if agent lost connection) |
| // Stopped -> Destroyed |
| // |
| // Starting, HA, Migrating, Running state are all counted as "Open" for available capacity calculation |
| // because sooner or later, it will be driven into Running state |
| // |
| @Local(value = { ConsoleProxyManager.class, ConsoleProxyService.class }) |
| public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxyManager, |
| VirtualMachineGuru<ConsoleProxyVO>, SystemVmLoadScanHandler<Long>, ResourceStateAdapter { |
| private static final Logger s_logger = Logger.getLogger(ConsoleProxyManagerImpl.class); |
| |
| private static final int DEFAULT_CAPACITY_SCAN_INTERVAL = 30000; // 30 seconds |
| private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC = 180; // 3 minutes |
| |
| private static final int STARTUP_DELAY = 60000; // 60 seconds |
| |
| private int _consoleProxyPort = ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT; |
| |
| private String _mgmt_host; |
| private int _mgmt_port = 8250; |
| |
| @Inject |
| private List<ConsoleProxyAllocator> _consoleProxyAllocators; |
| |
| @Inject |
| private ConsoleProxyDao _consoleProxyDao; |
| @Inject |
| private DataCenterDao _dcDao; |
| @Inject |
| private VMTemplateDao _templateDao; |
| @Inject |
| private HostPodDao _podDao; |
| @Inject |
| private HostDao _hostDao; |
| @Inject |
| private ConfigurationDao _configDao; |
| @Inject |
| private CertificateDao _certDao; |
| @Inject |
| private VMInstanceDao _instanceDao; |
| @Inject |
| private VMTemplateHostDao _vmTemplateHostDao; |
| @Inject |
| private AgentManager _agentMgr; |
| @Inject |
| private StorageManager _storageMgr; |
| @Inject |
| NetworkManager _networkMgr; |
| @Inject |
| NetworkModel _networkModel; |
| @Inject |
| AccountManager _accountMgr; |
| @Inject |
| ServiceOfferingDao _offeringDao; |
| @Inject |
| DiskOfferingDao _diskOfferingDao; |
| @Inject |
| NetworkOfferingDao _networkOfferingDao; |
| @Inject |
| PrimaryDataStoreDao _storagePoolDao; |
| @Inject |
| UserVmDetailsDao _vmDetailsDao; |
| @Inject |
| ResourceManager _resourceMgr; |
| @Inject |
| NetworkDao _networkDao; |
| @Inject |
| RulesManager _rulesMgr; |
| @Inject |
| TemplateManager templateMgr; |
| @Inject |
| IPAddressDao _ipAddressDao; |
| @Inject |
| ManagementServer _ms; |
| |
| private ConsoleProxyListener _listener; |
| |
| private ServiceOfferingVO _serviceOffering; |
| |
| NetworkOffering _publicNetworkOffering; |
| NetworkOffering _managementNetworkOffering; |
| NetworkOffering _linkLocalNetworkOffering; |
| |
| @Inject |
| private VirtualMachineManager _itMgr; |
| |
| /* |
| * 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 boolean _use_lvm; |
| private boolean _use_storage_vm; |
| private boolean _disable_rp_filter = false; |
| private String _instance; |
| |
| private int _proxySessionTimeoutValue = DEFAULT_PROXY_SESSION_TIMEOUT; |
| private boolean _sslEnabled = true; |
| |
| // global load picture at zone basis |
| private SystemVmLoadScanner<Long> _loadScanner; |
| private Map<Long, ZoneHostInfo> _zoneHostInfoMap; // map <zone id, info about running host in zone> |
| private Map<Long, ConsoleProxyLoadInfo> _zoneProxyCountMap; // map <zone id, info about proxy VMs count in zone> |
| private Map<Long, ConsoleProxyLoadInfo> _zoneVmCountMap; // map <zone id, info about running VMs count in zone> |
| |
| private String _staticPublicIp; |
| private int _staticPort; |
| |
| private final GlobalLock _allocProxyLock = GlobalLock.getInternLock(getAllocProxyLockName()); |
| |
| /* |
| * private final String keyContent = |
| * "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALV5vGlkiWwoZX4hTRplPXP8qtST\n" |
| * + "hwZhko8noeY5vf8ECwmd+vrCTw/JvnOtkx/8oYNbg/SeUt1EfOsk6gqJdBblGFBZRMcUJlIpqE9z\n" + |
| * "uv68U9G8Gfi/qvRSY336hibw0J5bZ4vn1QqmyHDB+Czea9AjFUV7AEVG15+vED7why+/AgMBAAEC\n" |
| * + "gYBmFBPnNKYYMKDmUdUNA+WNWJK/ADzzWe8WlzR6TACTcbLDthl289WFC/YVG42mcHRpbxDKiEQU\n" + |
| * "MnIR0rHTO34Qb/2HcuyweStU2gqR6omxBvMnFpJr90nD1HcOMJzeLHsphau0/EmKKey+gk4PyieD\n" |
| * + "KqTM7LTjjHv8xPM4n+WAAQJBAOMNCeFKlJ4kMokWhU74B5/w/NGyT1BHUN0VmilHSiJC8JqS4BiI\n" + |
| * "ZpAeET3VmilO6QTGh2XVhEDGteu3uZR6ipUCQQDMnRzMgQ/50LFeIQo4IBtwlEouczMlPQF4c21R\n" |
| * + "1d720moxILVPT0NJZTQUDDmmgbL+B7CgtcCR2NlP5sKPZVADAkEAh4Xq1cy8dMBKYcVNgNtPQcqI\n" + |
| * "PWpfKR3ISI5yXB0vRNAL6Vet5zbTcUZhKDVtNSbis3UEsGYH8NorEC2z2cpjGQJANhJi9Ow6c5Mh\n" |
| * + "/DURBUn+1l5pyCKrZnDbvaALSLATLvjmFTuGjoHszy2OeKnOZmEqExWnKKE/VYuPyhy6V7i3TwJA\n" + |
| * "f8skDgtPK0OsBCa6IljPaHoWBjPc4kFkSTSS1d56hUcWSikTmiuKdLyBb85AADSZYsvHWrte4opN\n" + "dhNukMJuRA==\n"; |
| * |
| * private final String certContent = "-----BEGIN CERTIFICATE-----\n" + |
| * "MIIE3jCCA8agAwIBAgIFAqv56tIwDQYJKoZIhvcNAQEFBQAwgcoxCzAJBgNVBAYT\n" |
| * + "AlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYD\n" + |
| * "VQQKExFHb0RhZGR5LmNvbSwgSW5jLjEzMDEGA1UECxMqaHR0cDovL2NlcnRpZmlj\n" |
| * + "YXRlcy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5MTAwLgYDVQQDEydHbyBEYWRkeSBT\n" + |
| * "ZWN1cmUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxETAPBgNVBAUTCDA3OTY5Mjg3\n" |
| * + "MB4XDTA5MDIxMTA0NTc1NloXDTEyMDIwNzA1MTEyM1owWTEZMBcGA1UECgwQKi5y\n" + |
| * "ZWFsaG9zdGlwLmNvbTEhMB8GA1UECwwYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVk\n" |
| * + "MRkwFwYDVQQDDBAqLnJlYWxob3N0aXAuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GN\n" + |
| * "ADCBiQKBgQC1ebxpZIlsKGV+IU0aZT1z/KrUk4cGYZKPJ6HmOb3/BAsJnfr6wk8P\n" |
| * + "yb5zrZMf/KGDW4P0nlLdRHzrJOoKiXQW5RhQWUTHFCZSKahPc7r+vFPRvBn4v6r0\n" + |
| * "UmN9+oYm8NCeW2eL59UKpshwwfgs3mvQIxVFewBFRtefrxA+8IcvvwIDAQABo4IB\n" |
| * + "vTCCAbkwDwYDVR0TAQH/BAUwAwEBADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB\n" + |
| * "BQUHAwIwDgYDVR0PAQH/BAQDAgWgMDIGA1UdHwQrMCkwJ6AloCOGIWh0dHA6Ly9j\n" |
| * + "cmwuZ29kYWRkeS5jb20vZ2RzMS0yLmNybDBTBgNVHSAETDBKMEgGC2CGSAGG/W0B\n" + |
| * "BxcBMDkwNwYIKwYBBQUHAgEWK2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j\n" |
| * + "b20vcmVwb3NpdG9yeS8wgYAGCCsGAQUFBwEBBHQwcjAkBggrBgEFBQcwAYYYaHR0\n" + |
| * "cDovL29jc3AuZ29kYWRkeS5jb20vMEoGCCsGAQUFBzAChj5odHRwOi8vY2VydGlm\n" |
| * + "aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkvZ2RfaW50ZXJtZWRpYXRlLmNy\n" + |
| * "dDAfBgNVHSMEGDAWgBT9rGEyk2xF1uLuhV+auud2mWjM5zArBgNVHREEJDAighAq\n" |
| * + "LnJlYWxob3N0aXAuY29tgg5yZWFsaG9zdGlwLmNvbTAdBgNVHQ4EFgQUHxwmdK5w\n" + |
| * "9/YVeZ/3fHyi6nQfzoYwDQYJKoZIhvcNAQEFBQADggEBABv/XinvId6oWXJtmku+\n" |
| * + "7m90JhSVH0ycoIGjgdaIkcExQGP08MCilbUsPcbhLheSFdgn/cR4e1MP083lacoj\n" + |
| * "OGauY7b8f/cuquGkT49Ns14awPlEzRjjycQEjjLxFEuL5CFWa2t2gKRE1dSfhDQ+\n" |
| * + "fJ6GBCs1XgZLuhkKS8fPf+YmG2ZjHzYDjYoSx7paDXgEm+kbYIZdCK51lA0BUAjP\n" + |
| * "9ZMGhsu/PpAbh5U/DtcIqxY0xeqD4TeGsBzXg6uLhv+jKHDtXg5fYPe+z0n5DCEL\n" |
| * + "k0fLF4+i/pt9hVCz0QrZ28RUhXf825+EOL0Gw+Uzt+7RV2cCaJrlu4cDrDom2FRy\n" + "E8I=\n" + |
| * "-----END CERTIFICATE-----\n"; |
| */ |
| public static final String keyContent = |
| "-----BEGIN PRIVATE KEY-----\n" + |
| "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCDT9AtEfs+s/I8QXp6rrCw0iNJ\n" + |
| "0+GgsybNHheU+JpL39LMTZykCrZhZnyDvwdxCoOfE38Sa32baHKNds+y2SHnMNsOkw8OcNucHEBX\n" + |
| "1FIpOBGph9D6xC+umx9od6xMWETUv7j6h2u+WC3OhBM8fHCBqIiAol31/IkcqDxxsHlQ8S/oCfTl\n" + |
| "XJUY6Yn628OA1XijKdRnadV0hZ829cv/PZKljjwQUTyrd0KHQeksBH+YAYSo2JUl8ekNLsOi8/cP\n" + |
| "tfojnltzRI1GXi0ZONs8VnDzJ0a2gqZY+uxlz+CGbLnGnlN4j9cBpE+MfUE+35Dq121sTpsSgF85\n" + |
| "Mz+pVhn2S633AgMBAAECggEAH/Szd9RxbVADenCA6wxKSa3KErRyq1YN8ksJeCKMAj0FIt0caruE\n" + |
| "qO11DebWW8cwQu1Otl/cYI6pmg24/BBldMrp9IELX/tNJo+lhPpRyGAxxC0eSXinFfoASb8d+jJd\n" + |
| "Bd1mmemM6fSxqRlxSP4LrzIhjhR1g2CiyYuTsiM9UtoVKGyHwe7KfFwirUOJo3Mr18zUVNm7YqY4\n" + |
| "IVhOSq59zkH3ULBlYq4bG50jpxa5mNSCZ7IpafPY/kE/CbR+FWNt30+rk69T+qb5abg6+XGm+OAm\n" + |
| "bnQ18yZEqX6nJLk7Ch0cfA5orGgrTMOrM71wK7tBBDQ308kOxDGebx6j0qD36QKBgQDTRDr8kuhA\n" + |
| "9sUyKr9vk2DQCMpNvEeiwI3JRMqmmxpNAtg01aJ3Ya57vX5Fc+zcuV87kP6FM1xgpHQvnw5LWo2J\n" + |
| "s7ANwQcP8ricEW5zkZhSjI4ssMeAubmsHOloGxmLFYZqwx0JI7CWViGTLMcUlqKblmHcjeQDeDfP\n" + |
| "P1TaCItFmwKBgQCfHZwVvIcaDs5vxVpZ4ftvflIrW8qq0uOVK6QIf9A/YTGhCXl2qxxTg2A6+0rg\n" + |
| "ZqI7zKzUDxIbVv0KlgCbpHDC9d5+sdtDB3wW2pimuJ3p1z4/RHb4n/lDwXCACZl1S5l24yXX2pFZ\n" + |
| "wdPCXmy5PYkHMssFLNhI24pprUIQs66M1QKBgQDQwjAjWisD3pRXESSfZRsaFkWJcM28hdbVFhPF\n" + |
| "c6gWhwQLmTp0CuL2RPXcPUPFi6sN2iWWi3zxxi9Eyz+9uBn6AsOpo56N5MME/LiOnETO9TKb+Ib6\n" + |
| "rQtKhjshcv3XkIqFPo2XdVvOAgglPO7vajX91iiXXuH7h7RmJud6l0y/lwKBgE+bi90gLuPtpoEr\n" + |
| "VzIDKz40ED5bNYHT80NNy0rpT7J2GVN9nwStRYXPBBVeZq7xCpgqpgmO5LtDAWULeZBlbHlOdBwl\n" + |
| "NhNKKl5wzdEUKwW0yBL1WSS5PQgWPwgARYP25/ggW22sj+49WIo1neXsEKPGWObk8e050f1fTt92\n" + |
| "Vo1lAoGAb1gCoyBCzvi7sqFxm4V5oapnJeiQQJFjhoYWqGa26rQ+AvXXNuBcigIeDXNJPctSF0Uc\n" + |
| "p11KbbCgiruBbckvM1vGsk6Sx4leRk+IFHRpJktFUek4o0eUg0shOsyyvyet48Dfg0a8FvcxROs0\n" + |
| "gD+IYds5doiob/hcm1hnNB/3vk4=\n" + |
| "-----END PRIVATE KEY-----\n"; |
| |
| public static final String certContent = |
| "-----BEGIN CERTIFICATE-----\n" + |
| "MIIFZTCCBE2gAwIBAgIHKBCduBUoKDANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE\n" + |
| "BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY\n" + |
| "BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlm\n" + |
| "aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5\n" + |
| "IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5Njky\n" + |
| "ODcwHhcNMTIwMjAzMDMzMDQwWhcNMTcwMjA3MDUxMTIzWjBZMRkwFwYDVQQKDBAq\n" + |
| "LnJlYWxob3N0aXAuY29tMSEwHwYDVQQLDBhEb21haW4gQ29udHJvbCBWYWxpZGF0\n" + |
| "ZWQxGTAXBgNVBAMMECoucmVhbGhvc3RpcC5jb20wggEiMA0GCSqGSIb3DQEBAQUA\n" + |
| "A4IBDwAwggEKAoIBAQCDT9AtEfs+s/I8QXp6rrCw0iNJ0+GgsybNHheU+JpL39LM\n" + |
| "TZykCrZhZnyDvwdxCoOfE38Sa32baHKNds+y2SHnMNsOkw8OcNucHEBX1FIpOBGp\n" + |
| "h9D6xC+umx9od6xMWETUv7j6h2u+WC3OhBM8fHCBqIiAol31/IkcqDxxsHlQ8S/o\n" + |
| "CfTlXJUY6Yn628OA1XijKdRnadV0hZ829cv/PZKljjwQUTyrd0KHQeksBH+YAYSo\n" + |
| "2JUl8ekNLsOi8/cPtfojnltzRI1GXi0ZONs8VnDzJ0a2gqZY+uxlz+CGbLnGnlN4\n" + |
| "j9cBpE+MfUE+35Dq121sTpsSgF85Mz+pVhn2S633AgMBAAGjggG+MIIBujAPBgNV\n" + |
| "HRMBAf8EBTADAQEAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNV\n" + |
| "HQ8BAf8EBAMCBaAwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5nb2RhZGR5\n" + |
| "LmNvbS9nZHMxLTY0LmNybDBTBgNVHSAETDBKMEgGC2CGSAGG/W0BBxcBMDkwNwYI\n" + |
| "KwYBBQUHAgEWK2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3Np\n" + |
| "dG9yeS8wgYAGCCsGAQUFBwEBBHQwcjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Au\n" + |
| "Z29kYWRkeS5jb20vMEoGCCsGAQUFBzAChj5odHRwOi8vY2VydGlmaWNhdGVzLmdv\n" + |
| "ZGFkZHkuY29tL3JlcG9zaXRvcnkvZ2RfaW50ZXJtZWRpYXRlLmNydDAfBgNVHSME\n" + |
| "GDAWgBT9rGEyk2xF1uLuhV+auud2mWjM5zArBgNVHREEJDAighAqLnJlYWxob3N0\n" + |
| "aXAuY29tgg5yZWFsaG9zdGlwLmNvbTAdBgNVHQ4EFgQUZyJz9/QLy5TWIIscTXID\n" + |
| "E8Xk47YwDQYJKoZIhvcNAQEFBQADggEBAKiUV3KK16mP0NpS92fmQkCLqm+qUWyN\n" + |
| "BfBVgf9/M5pcT8EiTZlS5nAtzAE/eRpBeR3ubLlaAogj4rdH7YYVJcDDLLoB2qM3\n" + |
| "qeCHu8LFoblkb93UuFDWqRaVPmMlJRnhsRkL1oa2gM2hwQTkBDkP7w5FG1BELCgl\n" + |
| "gZI2ij2yxjge6pOEwSyZCzzbCcg9pN+dNrYyGEtB4k+BBnPA3N4r14CWbk+uxjrQ\n" + |
| "6j2Ip+b7wOc5IuMEMl8xwTyjuX3lsLbAZyFI9RCyofwA9NqIZ1GeB6Zd196rubQp\n" + |
| "93cmBqGGjZUs3wMrGlm7xdjlX6GQ9UvmvkMub9+lL99A5W50QgCmFeI=\n" + |
| "-----END CERTIFICATE-----\n"; |
| |
| public static final String rootCa = |
| "-----BEGIN CERTIFICATE-----\n" + |
| "MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMx\n" + |
| "ITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g\n" + |
| "RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYw\n" + |
| "MTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMH\n" + |
| "QXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5j\n" + |
| "b20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j\n" + |
| "b20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmlj\n" + |
| "YXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcN\n" + |
| "AQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3H\n" + |
| "KrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQm\n" + |
| "VZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpR\n" + |
| "SgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRT\n" + |
| "cDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ\n" + |
| "6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEu\n" + |
| "MB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDS\n" + |
| "kdRMEXGzYcs9of7dqGrU4zASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEB\n" + |
| "BCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0f\n" + |
| "BD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBv\n" + |
| "c2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUH\n" + |
| "AgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAO\n" + |
| "BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IG\n" + |
| "OgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMU\n" + |
| "A2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o\n" + |
| "0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTX\n" + |
| "RE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuH\n" + |
| "qDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWV\n" + |
| "U+4=\n" + |
| "-----END CERTIFICATE-----\n" + |
| "-----BEGIN CERTIFICATE-----\n" + |
| "MIIE+zCCBGSgAwIBAgICAQ0wDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1Zh\n" + |
| "bGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu\n" + |
| "Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24g\n" + |
| "QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAe\n" + |
| "BgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MDYyMFoX\n" + |
| "DTI0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBE\n" + |
| "YWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0\n" + |
| "aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgC\n" + |
| "ggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv\n" + |
| "2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+q\n" + |
| "N1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiO\n" + |
| "r18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lN\n" + |
| "f4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+YihfukEH\n" + |
| "U1jPEX44dMX4/7VpkI+EdOqXG68CAQOjggHhMIIB3TAdBgNVHQ4EFgQU0sSw0pHU\n" + |
| "TBFxs2HLPaH+3ahq1OMwgdIGA1UdIwSByjCBx6GBwaSBvjCBuzEkMCIGA1UEBxMb\n" + |
| "VmFsaUNlcnQgVmFsaWRhdGlvbiBOZXR3b3JrMRcwFQYDVQQKEw5WYWxpQ2VydCwg\n" + |
| "SW5jLjE1MDMGA1UECxMsVmFsaUNlcnQgQ2xhc3MgMiBQb2xpY3kgVmFsaWRhdGlv\n" + |
| "biBBdXRob3JpdHkxITAfBgNVBAMTGGh0dHA6Ly93d3cudmFsaWNlcnQuY29tLzEg\n" + |
| "MB4GCSqGSIb3DQEJARYRaW5mb0B2YWxpY2VydC5jb22CAQEwDwYDVR0TAQH/BAUw\n" + |
| "AwEB/zAzBggrBgEFBQcBAQQnMCUwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmdv\n" + |
| "ZGFkZHkuY29tMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jZXJ0aWZpY2F0ZXMu\n" + |
| "Z29kYWRkeS5jb20vcmVwb3NpdG9yeS9yb290LmNybDBLBgNVHSAERDBCMEAGBFUd\n" + |
| "IAAwODA2BggrBgEFBQcCARYqaHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNv\n" + |
| "bS9yZXBvc2l0b3J5MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOBgQC1\n" + |
| "QPmnHfbq/qQaQlpE9xXUhUaJwL6e4+PrxeNYiY+Sn1eocSxI0YGyeR+sBjUZsE4O\n" + |
| "WBsUs5iB0QQeyAfJg594RAoYC5jcdnplDQ1tgMQLARzLrUc+cb53S8wGd9D0Vmsf\n" + |
| "SxOaFIqII6hR8INMqzW/Rn453HWkrugp++85j09VZw==\n" + |
| "-----END CERTIFICATE-----\n" + |
| "-----BEGIN CERTIFICATE-----\n" + |
| "MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0\n" + |
| "IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz\n" + |
| "BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y\n" + |
| "aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG\n" + |
| "9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy\n" + |
| "NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y\n" + |
| "azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs\n" + |
| "YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw\n" + |
| "Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl\n" + |
| "cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY\n" + |
| "dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9\n" + |
| "WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS\n" + |
| "v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v\n" + |
| "UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu\n" + |
| "IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC\n" + |
| "W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd\n" + |
| "-----END CERTIFICATE-----\n"; |
| |
| @Inject |
| private KeystoreDao _ksDao; |
| @Inject |
| private KeystoreManager _ksMgr; |
| |
| public class VmBasedAgentHook extends AgentHookBase { |
| |
| public VmBasedAgentHook(VMInstanceDao instanceDao, HostDao hostDao, ConfigurationDao cfgDao, |
| KeystoreManager ksMgr, AgentManager agentMgr, ManagementServer ms) { |
| super(instanceDao, hostDao, cfgDao, ksMgr, agentMgr, ms); |
| } |
| |
| @Override |
| public void onLoadReport(ConsoleProxyLoadReportCommand cmd) { |
| if (cmd.getLoadInfo() == null) { |
| return; |
| } |
| |
| ConsoleProxyStatus status = null; |
| try { |
| GsonBuilder gb = new GsonBuilder(); |
| gb.setVersion(1.3); |
| Gson gson = gb.create(); |
| status = gson.fromJson(cmd.getLoadInfo(), ConsoleProxyStatus.class); |
| } catch (Throwable e) { |
| s_logger.warn("Unable to parse load info from proxy, proxy vm id : " + cmd.getProxyVmId() + ", info : " + cmd.getLoadInfo()); |
| } |
| |
| if (status != null) { |
| int count = 0; |
| if (status.getConnections() != null) { |
| count = status.getConnections().length; |
| } |
| |
| byte[] details = null; |
| if (cmd.getLoadInfo() != null) { |
| details = cmd.getLoadInfo().getBytes(Charset.forName("US-ASCII")); |
| } |
| _consoleProxyDao.update(cmd.getProxyVmId(), count, DateUtil.currentGMTTime(), details); |
| } else { |
| if (s_logger.isTraceEnabled()) { |
| s_logger.trace("Unable to get console proxy load info, id : " + cmd.getProxyVmId()); |
| } |
| |
| _consoleProxyDao.update(cmd.getProxyVmId(), 0, DateUtil.currentGMTTime(), null); |
| } |
| } |
| |
| @Override |
| public void onAgentConnect(HostVO host, StartupCommand cmd) { |
| // no-op |
| } |
| |
| @Override |
| public void onAgentDisconnect(long agentId, com.cloud.host.Status state) { |
| |
| if (state == com.cloud.host.Status.Alert || state == com.cloud.host.Status.Disconnected) { |
| // be it either in alert or in disconnected state, the agent |
| // process |
| // may be gone in the VM, |
| // we will be reacting to stop the corresponding VM and let the |
| // scan |
| // process to |
| HostVO host = _hostDao.findById(agentId); |
| if (host.getType() == Type.ConsoleProxy) { |
| String name = host.getName(); |
| if (s_logger.isInfoEnabled()) { |
| s_logger.info("Console proxy agent disconnected, proxy: " + name); |
| } |
| if (name != null && name.startsWith("v-")) { |
| String[] tokens = name.split("-"); |
| long proxyVmId = 0; |
| try { |
| proxyVmId = Long.parseLong(tokens[1]); |
| } catch (NumberFormatException e) { |
| s_logger.error("Unexpected exception " + e.getMessage(), e); |
| return; |
| } |
| |
| final ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId); |
| if (proxy != null) { |
| |
| // Disable this feature for now, as it conflicts |
| // with |
| // the case of allowing user to reboot console proxy |
| // when rebooting happens, we will receive |
| // disconnect |
| // here and we can't enter into stopping process, |
| // as when the rebooted one comes up, it will kick |
| // off a |
| // newly started one and trigger the process |
| // continue on forever |
| |
| /* |
| * _capacityScanScheduler.execute(new Runnable() { |
| * public void run() { if(s_logger.isInfoEnabled()) |
| * s_logger.info("Stop console proxy " + |
| * proxy.getName() + |
| * " VM because of that the agent running inside it has disconnected" |
| * ); stopProxy(proxy.getId()); } }); |
| */ |
| } else { |
| if (s_logger.isInfoEnabled()) { |
| s_logger.info("Console proxy agent disconnected but corresponding console proxy VM no longer exists in DB, proxy: " |
| + name); |
| } |
| } |
| } else { |
| assert (false) : "Invalid console proxy name: " + name; |
| } |
| } |
| } |
| |
| } |
| |
| @Override |
| protected HostVO findConsoleProxyHost(StartupProxyCommand startupCmd) { |
| long proxyVmId = startupCmd.getProxyVmId(); |
| ConsoleProxyVO consoleProxy = _consoleProxyDao.findById(proxyVmId); |
| if (consoleProxy == null) { |
| s_logger.info("Proxy " + proxyVmId + " is no longer in DB, skip sending startup command"); |
| return null; |
| } |
| |
| assert (consoleProxy != null); |
| return findConsoleProxyHostByName(consoleProxy.getHostName()); |
| } |
| |
| } |
| |
| @Override |
| public ConsoleProxyInfo assignProxy(final long dataCenterId, final long vmId) { |
| ConsoleProxyVO proxy = doAssignProxy(dataCenterId, vmId); |
| if (proxy == null) { |
| return null; |
| } |
| |
| if (proxy.getPublicIpAddress() == null) { |
| s_logger.warn("Assigned console proxy does not have a valid public IP address"); |
| return null; |
| } |
| |
| KeystoreVO ksVo = _ksDao.findByName(ConsoleProxyManager.CERTIFICATE_NAME); |
| assert (ksVo != null); |
| |
| if (_staticPublicIp == null) { |
| return new ConsoleProxyInfo(proxy.isSslEnabled(), proxy.getPublicIpAddress(), _consoleProxyPort, proxy.getPort(), ksVo.getDomainSuffix()); |
| } else { |
| return new ConsoleProxyInfo(proxy.isSslEnabled(), _staticPublicIp, _consoleProxyPort, _staticPort, ksVo.getDomainSuffix()); |
| } |
| } |
| |
| 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; |
| } |
| |
| 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 (_allocProxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { |
| try { |
| if (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); |
| } |
| } 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; |
| } |
| |
| // 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; |
| } |
| |
| 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) { |
| 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) { |
| try { |
| ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId); |
| Account systemAcct = _accountMgr.getSystemAccount(); |
| User systemUser = _accountMgr.getSystemUser(); |
| if (proxy.getState() == VirtualMachine.State.Running) { |
| return proxy; |
| } |
| |
| String restart = _configDao.getValue(Config.ConsoleProxyRestart.key()); |
| if (restart != null && restart.equalsIgnoreCase("false")) { |
| return null; |
| } |
| |
| if (proxy.getState() == VirtualMachine.State.Stopped) { |
| return _itMgr.start(proxy, null, systemUser, systemAcct); |
| } |
| |
| // For VMs that are in Stopping, Starting, Migrating state, let client to wait by returning null |
| // as sooner or later, Starting/Migrating state will be transited to Running and Stopping will be transited |
| // to |
| // Stopped to allow |
| // Starting of it |
| s_logger.warn("Console proxy is not in correct state to be started: " + proxy.getState()); |
| return null; |
| } 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 (ResourceUnavailableException e) { |
| s_logger.warn("Exception while trying to start console proxy", e); |
| return null; |
| } catch (CloudRuntimeException e) { |
| s_logger.warn("Runtime Exception while trying to start console proxy", e); |
| 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<ConsoleProxyVO> runningList = _consoleProxyDao.getProxyListInStates(dataCenterId, State.Running); |
| if (runningList != null && runningList.size() > 0) { |
| Iterator<ConsoleProxyVO> it = runningList.iterator(); |
| while (it.hasNext()) { |
| ConsoleProxyVO proxy = it.next(); |
| if(proxy.getActiveSession() >= _capacityPerProxy){ |
| it.remove(); |
| } |
| } |
| if (s_logger.isTraceEnabled()) { |
| s_logger.trace("Running proxy pool size : " + runningList.size()); |
| for (ConsoleProxyVO proxy : runningList) { |
| s_logger.trace("Running proxy instance : " + proxy.getHostName()); |
| } |
| } |
| |
| List<Pair<Long, Integer>> l = _consoleProxyDao.getProxyLoadMatrix(); |
| Map<Long, Integer> loadInfo = new HashMap<Long, Integer>(); |
| if (l != null) { |
| for (Pair<Long, Integer> 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) { |
| |
| // practically treat all console proxy VM that is not in Running state but can be entering into Running state as |
| // candidates |
| // this is to prevent launching unneccessary console proxy VMs because of temporarily unavailable state |
| List<ConsoleProxyVO> l = _consoleProxyDao.getProxyListInStates(dataCenterId, State.Starting, State.Stopped, State.Migrating, State.Stopping); |
| if (l != null && l.size() > 0) { |
| return l.get(0); |
| } |
| |
| return null; |
| } |
| |
| public ConsoleProxyVO startNew(long dataCenterId) throws ConcurrentOperationException { |
| |
| if (s_logger.isDebugEnabled()) { |
| s_logger.debug("Assign console proxy from a newly started instance for request from data center : " + dataCenterId); |
| } |
| |
| if (!allowToLaunchNew(dataCenterId)) { |
| s_logger.warn("The number of launched console proxy on zone " + dataCenterId + " has reached to limit"); |
| return null; |
| } |
| HypervisorType defaultHype = _resourceMgr.getAvailableHypervisor(dataCenterId); |
| |
| Map<String, Object> context = createProxyInstance(dataCenterId, defaultHype); |
| |
| long proxyVmId = (Long) context.get("proxyVmId"); |
| if (proxyVmId == 0) { |
| if (s_logger.isTraceEnabled()) { |
| s_logger.trace("Creating proxy instance failed, data center id : " + dataCenterId); |
| } |
| return null; |
| } |
| |
| ConsoleProxyVO proxy = _consoleProxyDao.findById(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")); |
| } |
| return null; |
| } |
| |
| protected Map<String, Object> createProxyInstance(long dataCenterId, HypervisorType desiredHyp) throws ConcurrentOperationException { |
| |
| long id = _consoleProxyDao.getNextInSequence(Long.class, "id"); |
| String name = VirtualMachineName.getConsoleProxyName(id, _instance); |
| DataCenterVO dc = _dcDao.findById(dataCenterId); |
| Account systemAcct = _accountMgr.getSystemAccount(); |
| |
| DataCenterDeployment plan = new DataCenterDeployment(dataCenterId); |
| |
| TrafficType defaultTrafficType = TrafficType.Public; |
| if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) { |
| defaultTrafficType = TrafficType.Guest; |
| } |
| |
| List<NetworkVO> defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType); |
| |
| if (defaultNetworks.size() != 1) { |
| throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type " + defaultTrafficType + " when expect to find 1"); |
| } |
| |
| NetworkVO defaultNetwork = defaultNetworks.get(0); |
| |
| List<? extends NetworkOffering> offerings = _networkModel.getSystemAccountNetworkOfferings(NetworkOffering.SystemControlNetwork, NetworkOffering.SystemManagementNetwork); |
| List<Pair<NetworkVO, NicProfile>> networks = new ArrayList<Pair<NetworkVO, NicProfile>>(offerings.size() + 1); |
| NicProfile defaultNic = new NicProfile(); |
| defaultNic.setDefaultNic(true); |
| defaultNic.setDeviceId(2); |
| |
| networks.add(new Pair<NetworkVO, NicProfile>(_networkMgr.setupNetwork(systemAcct, _networkOfferingDao.findById(defaultNetwork.getNetworkOfferingId()), plan, null, null, false).get(0), defaultNic)); |
| |
| for (NetworkOffering offering : offerings) { |
| networks.add(new Pair<NetworkVO, NicProfile>(_networkMgr.setupNetwork(systemAcct, offering, plan, null, null, false).get(0), null)); |
| } |
| |
| VMTemplateVO template = _templateDao.findSystemVMTemplate(dataCenterId, desiredHyp); |
| if (template == null) { |
| s_logger.debug("Can't find a template to start"); |
| throw new CloudRuntimeException("Insufficient capacity exception"); |
| } |
| |
| ConsoleProxyVO proxy = new ConsoleProxyVO(id, _serviceOffering.getId(), name, template.getId(), template.getHypervisorType(), template.getGuestOSId(), dataCenterId, systemAcct.getDomainId(), |
| systemAcct.getId(), 0, _serviceOffering.getOfferHA()); |
| try { |
| proxy = _itMgr.allocate(proxy, template, _serviceOffering, networks, plan, null, systemAcct); |
| } catch (InsufficientCapacityException e) { |
| s_logger.warn("InsufficientCapacity", e); |
| throw new CloudRuntimeException("Insufficient capacity exception", e); |
| } |
| |
| Map<String, Object> context = new HashMap<String, Object>(); |
| context.put("dc", dc); |
| HostPodVO pod = _podDao.findById(proxy.getPodIdToDeployIn()); |
| context.put("pod", pod); |
| context.put("proxyVmId", proxy.getId()); |
| |
| return context; |
| } |
| |
| private ConsoleProxyAllocator getCurrentAllocator() { |
| // for now, only one adapter is supported |
| for(ConsoleProxyAllocator allocator : _consoleProxyAllocators) { |
| return allocator; |
| } |
| |
| return null; |
| } |
| |
| 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 handleAgentDisconnect(long agentId, com.cloud.host.Status state) { |
| if (state == com.cloud.host.Status.Alert || state == com.cloud.host.Status.Disconnected) { |
| // be it either in alert or in disconnected state, the agent process |
| // may be gone in the VM, |
| // 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) { |
| |
| // 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 boolean reserveStandbyCapacity() { |
| ConsoleProxyManagementState state = getManagementState(); |
| if (state == null || state != ConsoleProxyManagementState.Auto) { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| private boolean isConsoleProxyVmRequired(long dcId) { |
| DataCenterVO dc = _dcDao.findById(dcId); |
| _dcDao.loadDetails(dc); |
| String cpvmReq = dc.getDetail(ZoneConfig.EnableConsoleProxyVm.key()); |
| if (cpvmReq != null) { |
| return Boolean.parseBoolean(cpvmReq); |
| } |
| return true; |
| } |
| |
| private boolean allowToLaunchNew(long dcId) { |
| if (!isConsoleProxyVmRequired(dcId)) { |
| if (s_logger.isDebugEnabled()) { |
| s_logger.debug("Console proxy vm not required in zone " + dcId + " not launching"); |
| } |
| return false; |
| } |
| List<ConsoleProxyVO> l = _consoleProxyDao.getProxyListInStates(dcId, VirtualMachine.State.Starting, VirtualMachine.State.Running, VirtualMachine.State.Stopping, VirtualMachine.State.Stopped, |
| VirtualMachine.State.Migrating, VirtualMachine.State.Shutdowned, VirtualMachine.State.Unknown); |
| |
| String value = _configDao.getValue(Config.ConsoleProxyLaunchMax.key()); |
| int launchLimit = NumbersUtil.parseInt(value, 10); |
| return l.size() < launchLimit; |
| } |
| |
| private HypervisorType currentHypervisorType(long dcId) { |
| List<ConsoleProxyVO> l = _consoleProxyDao.getProxyListInStates(dcId, VirtualMachine.State.Starting, VirtualMachine.State.Running, VirtualMachine.State.Stopping, VirtualMachine.State.Stopped, |
| VirtualMachine.State.Migrating, VirtualMachine.State.Shutdowned, VirtualMachine.State.Unknown); |
| |
| return l.size() > 0 ? l.get(0).getHypervisorType() : HypervisorType.Any; |
| } |
| |
| 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); |
| } |
| |
| ConsoleProxyVO proxy = null; |
| if (_allocProxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { |
| try { |
| 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"); |
| } |
| |
| try { |
| proxy = startNew(dataCenterId); |
| } catch (ConcurrentOperationException e) { |
| s_logger.info("Concurrent Operation caught " + e); |
| } |
| } else { |
| if (s_logger.isInfoEnabled()) { |
| s_logger.info("Found a stopped console proxy, bring it up to running pool. proxy vm id : " + proxy.getId()); |
| } |
| } |
| } finally { |
| _allocProxyLock.unlock(); |
| } |
| } else { |
| if (s_logger.isInfoEnabled()) { |
| s_logger.info("Unable to acquire proxy allocation lock, skip for next time"); |
| } |
| } |
| |
| if (proxy != null) { |
| long proxyVmId = proxy.getId(); |
| proxy = startProxy(proxyVmId); |
| |
| if (proxy != null) { |
| if (s_logger.isInfoEnabled()) { |
| s_logger.info("Console proxy " + proxy.getHostName() + " is started"); |
| } |
| } |
| } |
| } |
| |
| public boolean isZoneReady(Map<Long, ZoneHostInfo> zoneHostInfoMap, long dataCenterId) { |
| ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenterId); |
| if (zoneHostInfo != null && isZoneHostReady(zoneHostInfo)) { |
| VMTemplateVO template = _templateDao.findSystemVMTemplate(dataCenterId); |
| HostVO secondaryStorageHost = this.templateMgr.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<Pair<Long, Integer>> l = _consoleProxyDao.getDatacenterStoragePoolHostInfo(dataCenterId, _use_lvm); |
| if (l != null && l.size() > 0 && l.get(0).second().intValue() > 0) { |
| return true; |
| } else { |
| if (s_logger.isDebugEnabled()) { |
| s_logger.debug("Primary storage is not ready, wait until it is ready to launch console proxy"); |
| } |
| } |
| } else { |
| if (s_logger.isDebugEnabled()) { |
| if (template == null) { |
| s_logger.debug("Zone host is ready, but console proxy template is null"); |
| } else if (secondaryStorageHost != null) { |
| s_logger.debug("Zone host is ready, but console proxy template: " + template.getId() + " is not ready on secondary storage: " + secondaryStorageHost.getId()); |
| } else { |
| s_logger.debug("Zone host is ready, but console proxy template: " + template.getId() + " is not ready on secondary storage."); |
| } |
| } |
| } |
| } |
| 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<Long, ZoneHostInfo> getZoneHostInfo() { |
| Date cutTime = DateUtil.currentGMTTime(); |
| List<RunningHostCountInfo> 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 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"); |
| } |
| |
| this._loadScanner.stop(); |
| _allocProxyLock.releaseRef(); |
| _resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName()); |
| return true; |
| } |
| |
| @Override |
| public Long convertToId(String vmName) { |
| if (!VirtualMachineName.isValidConsoleProxyName(vmName, _instance)) { |
| return null; |
| } |
| return VirtualMachineName.getConsoleProxyId(vmName); |
| } |
| |
| @Override |
| public boolean stopProxy(long 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; |
| } |
| |
| try { |
| return _itMgr.stop(proxy, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); |
| } catch (ResourceUnavailableException e) { |
| s_logger.warn("Stopping console proxy " + proxy.getHostName() + " failed : exception " + e.toString()); |
| return false; |
| } |
| } |
| |
| @Override |
| @DB |
| public void setManagementState(ConsoleProxyManagementState state) { |
| Transaction txn = Transaction.currentTxn(); |
| try { |
| txn.start(); |
| |
| ConsoleProxyManagementState lastState = getManagementState(); |
| if (lastState == null) { |
| txn.commit(); |
| return; |
| } |
| |
| if (lastState != state) { |
| _configDao.update(Config.ConsoleProxyManagementLastState.key(), Config.ConsoleProxyManagementLastState.getCategory(), lastState.toString()); |
| _configDao.update(Config.ConsoleProxyManagementState.key(), Config.ConsoleProxyManagementState.getCategory(), state.toString()); |
| } |
| |
| txn.commit(); |
| } catch (Throwable e) { |
| txn.rollback(); |
| } |
| } |
| |
| @Override |
| public ConsoleProxyManagementState getManagementState() { |
| String value = _configDao.getValue(Config.ConsoleProxyManagementState.key()); |
| if (value != null) { |
| ConsoleProxyManagementState state = ConsoleProxyManagementState.valueOf(value); |
| |
| if (state == null) { |
| s_logger.error("Invalid console proxy management state: " + value); |
| } |
| return state; |
| } |
| |
| s_logger.error("Invalid console proxy management state: " + value); |
| return null; |
| } |
| |
| @Override |
| @DB |
| public void resumeLastManagementState() { |
| Transaction txn = Transaction.currentTxn(); |
| try { |
| txn.start(); |
| ConsoleProxyManagementState state = getManagementState(); |
| ConsoleProxyManagementState lastState = getLastManagementState(); |
| if (lastState == null) { |
| txn.commit(); |
| return; |
| } |
| |
| if (lastState != state) { |
| _configDao.update(Config.ConsoleProxyManagementState.key(), Config.ConsoleProxyManagementState.getCategory(), lastState.toString()); |
| } |
| |
| txn.commit(); |
| } catch (Throwable e) { |
| txn.rollback(); |
| } |
| } |
| |
| private ConsoleProxyManagementState getLastManagementState() { |
| String value = _configDao.getValue(Config.ConsoleProxyManagementLastState.key()); |
| if (value != null) { |
| ConsoleProxyManagementState state = ConsoleProxyManagementState.valueOf(value); |
| |
| if (state == null) { |
| s_logger.error("Invalid console proxy management state: " + value); |
| } |
| return state; |
| } |
| |
| s_logger.error("Invalid console proxy management state: " + value); |
| return null; |
| } |
| |
| @Override |
| public boolean rebootProxy(long proxyVmId) { |
| final ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId); |
| |
| if (proxy == null || proxy.getState() == State.Destroyed) { |
| return false; |
| } |
| |
| 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 && answer.getResult()) { |
| if (s_logger.isDebugEnabled()) { |
| s_logger.debug("Successfully reboot console proxy " + proxy.getHostName()); |
| } |
| |
| SubscriptionMgr.getInstance().notifySubscribers(ConsoleProxyManager.ALERT_SUBJECT, this, |
| new ConsoleProxyAlertEventArgs(ConsoleProxyAlertEventArgs.PROXY_REBOOTED, proxy.getDataCenterId(), proxy.getId(), proxy, null)); |
| |
| return true; |
| } else { |
| if (s_logger.isDebugEnabled()) { |
| s_logger.debug("failed to reboot console proxy : " + proxy.getHostName()); |
| } |
| |
| return false; |
| } |
| } else { |
| return startProxy(proxyVmId) != null; |
| } |
| } |
| |
| @Override |
| public boolean destroyProxy(long vmId) { |
| ConsoleProxyVO proxy = _consoleProxyDao.findById(vmId); |
| try { |
| //expunge the vm |
| boolean result = _itMgr.expunge(proxy, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); |
| if (result) { |
| HostVO host = _hostDao.findByTypeNameAndZoneId(proxy.getDataCenterId(), proxy.getHostName(), |
| Host.Type.ConsoleProxy); |
| if (host != null) { |
| s_logger.debug("Removing host entry for proxy id=" + vmId); |
| result = result && _hostDao.remove(host.getId()); |
| } |
| } |
| |
| return result; |
| } catch (ResourceUnavailableException e) { |
| s_logger.warn("Unable to expunge " + proxy, e); |
| return false; |
| } |
| } |
| |
| private String getAllocProxyLockName() { |
| return "consoleproxy.alloc"; |
| } |
| |
| private void prepareDefaultCertificate() { |
| GlobalLock lock = GlobalLock.getInternLock("consoleproxy.cert.setup"); |
| try { |
| if (lock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { |
| KeystoreVO ksVo = _ksDao.findByName(CERTIFICATE_NAME); |
| if (ksVo == null) { |
| _ksDao.save(CERTIFICATE_NAME, certContent, keyContent, "realhostip.com"); |
| KeystoreVO caRoot = new KeystoreVO(); |
| caRoot.setCertificate(rootCa); |
| caRoot.setDomainSuffix("realhostip.com"); |
| caRoot.setName("root"); |
| caRoot.setIndex(0); |
| _ksDao.persist(caRoot); |
| } |
| lock.unlock(); |
| } |
| } finally { |
| lock.releaseRef(); |
| } |
| } |
| |
| @Override |
| public boolean configure(String name, Map<String, Object> params) throws ConfigurationException { |
| if (s_logger.isInfoEnabled()) { |
| s_logger.info("Start configuring console proxy manager : " + name); |
| } |
| |
| Map<String, String> configs = _configDao.getConfiguration("management-server", params); |
| |
| String value = configs.get(Config.ConsoleProxyCmdPort.key()); |
| value = configs.get("consoleproxy.sslEnabled"); |
| if (value != null && value.equalsIgnoreCase("true")) { |
| _sslEnabled = true; |
| } |
| |
| value = configs.get(Config.ConsoleProxyCapacityScanInterval.key()); |
| _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(Config.ConsoleProxyDisableRpFilter.key()); |
| if (value != null && value.equalsIgnoreCase("true")) { |
| _disable_rp_filter = true; |
| } |
| |
| value = configs.get(Config.SystemVMUseLocalStorage.key()); |
| 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); |
| } |
| |
| _instance = configs.get("instance.name"); |
| if (_instance == null) { |
| _instance = "DEFAULT"; |
| } |
| |
| prepareDefaultCertificate(); |
| |
| Map<String, String> 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); |
| |
| _listener = |
| new ConsoleProxyListener(new VmBasedAgentHook(_instanceDao, _hostDao, _configDao, _ksMgr, |
| _agentMgr, _ms)); |
| _agentMgr.registerForHostEvents(_listener, true, true, false); |
| |
| _itMgr.registerGuru(VirtualMachine.Type.ConsoleProxy, this); |
| |
| boolean useLocalStorage = Boolean.parseBoolean(configs.get(Config.SystemVMUseLocalStorage.key())); |
| |
| //check if there is a default service offering configured |
| String cpvmSrvcOffIdStr = configs.get(Config.ConsoleProxyServiceOffering.key()); |
| if (cpvmSrvcOffIdStr != null) { |
| DiskOffering diskOffering = _diskOfferingDao.findByUuid(cpvmSrvcOffIdStr); |
| if (diskOffering == null) |
| diskOffering = _diskOfferingDao.findById(Long.parseLong(cpvmSrvcOffIdStr)); |
| if (diskOffering != null) { |
| _serviceOffering = _offeringDao.findById(diskOffering.getId()); |
| } else { |
| s_logger.warn("Can't find system service offering specified by global config, uuid=" + cpvmSrvcOffIdStr + " for console proxy vm"); |
| } |
| } |
| |
| if(_serviceOffering == null || !_serviceOffering.getSystemUse()){ |
| int ramSize = NumbersUtil.parseInt(_configDao.getValue("console.ram.size"), DEFAULT_PROXY_VM_RAMSIZE); |
| int cpuFreq = NumbersUtil.parseInt(_configDao.getValue("console.cpu.mhz"), DEFAULT_PROXY_VM_CPUMHZ); |
| _serviceOffering = new ServiceOfferingVO("System Offering For Console Proxy", 1, ramSize, cpuFreq, 0, 0, false, null, useLocalStorage, true, null, true, VirtualMachine.Type.ConsoleProxy, true); |
| _serviceOffering.setUniqueName(ServiceOffering.consoleProxyDefaultOffUniqueName); |
| _serviceOffering = _offeringDao.persistSystemServiceOffering(_serviceOffering); |
| |
| // this can sometimes happen, if DB is manually or programmatically manipulated |
| if (_serviceOffering == null) { |
| String msg = "Data integrity problem : System Offering For Console Proxy has been removed?"; |
| s_logger.error(msg); |
| throw new ConfigurationException(msg); |
| } |
| } |
| |
| _loadScanner = new SystemVmLoadScanner<Long>(this); |
| _loadScanner.initScan(STARTUP_DELAY, _capacityScanInterval); |
| _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); |
| |
| _staticPublicIp = _configDao.getValue("consoleproxy.static.publicIp"); |
| if (_staticPublicIp != null) { |
| _staticPort = NumbersUtil.parseInt(_configDao.getValue("consoleproxy.static.port"), 8443); |
| } |
| |
| if (s_logger.isInfoEnabled()) { |
| s_logger.info("Console Proxy Manager is configured."); |
| } |
| return true; |
| } |
| |
| |
| |
| protected ConsoleProxyManagerImpl() { |
| } |
| |
| @Override |
| public boolean finalizeVirtualMachineProfile(VirtualMachineProfile<ConsoleProxyVO> profile, DeployDestination dest, ReservationContext context) { |
| |
| ConsoleProxyVO vm = profile.getVirtualMachine(); |
| Map<String, String> details = _vmDetailsDao.findDetails(vm.getId()); |
| vm.setDetails(details); |
| |
| StringBuilder buf = profile.getBootArgsBuilder(); |
| buf.append(" template=domP type=consoleproxy"); |
| buf.append(" host=").append(_mgmt_host); |
| buf.append(" port=").append(_mgmt_port); |
| buf.append(" name=").append(profile.getVirtualMachine().getHostName()); |
| if (_sslEnabled) { |
| buf.append(" premium=true"); |
| } |
| buf.append(" zone=").append(dest.getDataCenter().getId()); |
| buf.append(" pod=").append(dest.getPod().getId()); |
| buf.append(" guid=Proxy.").append(profile.getId()); |
| buf.append(" proxy_vm=").append(profile.getId()); |
| if (_disable_rp_filter) { |
| buf.append(" disable_rp_filter=true"); |
| } |
| |
| boolean externalDhcp = false; |
| String externalDhcpStr = _configDao.getValue("direct.attach.network.externalIpAllocator.enabled"); |
| if (externalDhcpStr != null && externalDhcpStr.equalsIgnoreCase("true")) { |
| externalDhcp = true; |
| } |
| |
| if (Boolean.valueOf(_configDao.getValue("system.vm.random.password"))) { |
| buf.append(" vmpassword=").append(_configDao.getValue("system.vm.password")); |
| } |
| |
| for (NicProfile nic : profile.getNics()) { |
| int deviceId = nic.getDeviceId(); |
| if (nic.getIp4Address() == null) { |
| buf.append(" eth").append(deviceId).append("ip=").append("0.0.0.0"); |
| buf.append(" eth").append(deviceId).append("mask=").append("0.0.0.0"); |
| } else { |
| buf.append(" eth").append(deviceId).append("ip=").append(nic.getIp4Address()); |
| buf.append(" eth").append(deviceId).append("mask=").append(nic.getNetmask()); |
| } |
| |
| if (nic.isDefaultNic()) { |
| buf.append(" gateway=").append(nic.getGateway()); |
| } |
| |
| if (nic.getTrafficType() == TrafficType.Management) { |
| String mgmt_cidr = _configDao.getValue(Config.ManagementNetwork.key()); |
| if (NetUtils.isValidCIDR(mgmt_cidr)) { |
| buf.append(" mgmtcidr=").append(mgmt_cidr); |
| } |
| buf.append(" localgw=").append(dest.getPod().getGateway()); |
| } |
| } |
| |
| /* External DHCP mode */ |
| if (externalDhcp) { |
| buf.append(" bootproto=dhcp"); |
| } |
| DataCenterVO dc = _dcDao.findById(profile.getVirtualMachine().getDataCenterId()); |
| buf.append(" internaldns1=").append(dc.getInternalDns1()); |
| if (dc.getInternalDns2() != null) { |
| buf.append(" internaldns2=").append(dc.getInternalDns2()); |
| } |
| buf.append(" dns1=").append(dc.getDns1()); |
| if (dc.getDns2() != null) { |
| buf.append(" dns2=").append(dc.getDns2()); |
| } |
| |
| String bootArgs = buf.toString(); |
| if (s_logger.isDebugEnabled()) { |
| s_logger.debug("Boot Args for " + profile + ": " + bootArgs); |
| } |
| |
| return true; |
| } |
| |
| @Override |
| public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile<ConsoleProxyVO> profile, DeployDestination dest, ReservationContext context) { |
| |
| finalizeCommandsOnStart(cmds, profile); |
| |
| ConsoleProxyVO proxy = profile.getVirtualMachine(); |
| DataCenter dc = dest.getDataCenter(); |
| List<NicProfile> nics = profile.getNics(); |
| for (NicProfile nic : nics) { |
| if ((nic.getTrafficType() == TrafficType.Public && dc.getNetworkType() == NetworkType.Advanced) |
| || (nic.getTrafficType() == TrafficType.Guest && (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()))) { |
| proxy.setPublicIpAddress(nic.getIp4Address()); |
| proxy.setPublicNetmask(nic.getNetmask()); |
| proxy.setPublicMacAddress(nic.getMacAddress()); |
| } else if (nic.getTrafficType() == TrafficType.Management) { |
| proxy.setPrivateIpAddress(nic.getIp4Address()); |
| proxy.setPrivateMacAddress(nic.getMacAddress()); |
| } |
| } |
| _consoleProxyDao.update(proxy.getId(), proxy); |
| return true; |
| } |
| |
| @Override |
| public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile<ConsoleProxyVO> profile) { |
| |
| NicProfile managementNic = null; |
| NicProfile controlNic = null; |
| for (NicProfile nic : profile.getNics()) { |
| if (nic.getTrafficType() == TrafficType.Management) { |
| managementNic = nic; |
| } else if (nic.getTrafficType() == TrafficType.Control && nic.getIp4Address() != null) { |
| controlNic = nic; |
| } |
| } |
| |
| if (controlNic == null) { |
| if (managementNic == null) { |
| s_logger.error("Management network doesn't exist for the console proxy vm " + profile.getVirtualMachine()); |
| return false; |
| } |
| controlNic = managementNic; |
| } |
| |
| CheckSshCommand check = new CheckSshCommand(profile.getInstanceName(), controlNic.getIp4Address(), 3922); |
| cmds.addCommand("checkSsh", check); |
| |
| return true; |
| } |
| |
| @Override |
| public boolean finalizeStart(VirtualMachineProfile<ConsoleProxyVO> profile, long hostId, Commands cmds, ReservationContext context) { |
| CheckSshAnswer answer = (CheckSshAnswer) cmds.getAnswer("checkSsh"); |
| if (answer == null || !answer.getResult()) { |
| if (answer != null) { |
| s_logger.warn("Unable to ssh to the VM: " + answer.getDetails()); |
| } else { |
| s_logger.warn("Unable to ssh to the VM: null answer"); |
| } |
| return false; |
| } |
| |
| try { |
| //get system ip and create static nat rule for the vm in case of basic networking with EIP/ELB |
| _rulesMgr.getSystemIpAndEnableStaticNatForVm(profile.getVirtualMachine(), false); |
| IPAddressVO ipaddr = _ipAddressDao.findByAssociatedVmId(profile.getVirtualMachine().getId()); |
| if (ipaddr != null && ipaddr.getSystem()) { |
| ConsoleProxyVO consoleVm = profile.getVirtualMachine(); |
| // override CPVM guest IP with EIP, so that console url's will be prepared with EIP |
| consoleVm.setPublicIpAddress(ipaddr.getAddress().addr()); |
| _consoleProxyDao.update(consoleVm.getId(), consoleVm); |
| } |
| } catch (Exception ex) { |
| s_logger.warn("Failed to get system ip and enable static nat for the vm " + profile.getVirtualMachine() + " due to exception ", ex); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| @Override |
| public void finalizeExpunge(ConsoleProxyVO proxy) { |
| proxy.setPublicIpAddress(null); |
| proxy.setPublicMacAddress(null); |
| proxy.setPublicNetmask(null); |
| proxy.setPrivateMacAddress(null); |
| proxy.setPrivateIpAddress(null); |
| _consoleProxyDao.update(proxy.getId(), proxy); |
| } |
| |
| |
| |
| @Override |
| public ConsoleProxyVO persist(ConsoleProxyVO proxy) { |
| return _consoleProxyDao.persist(proxy); |
| } |
| |
| @Override |
| public ConsoleProxyVO findById(long id) { |
| return _consoleProxyDao.findById(id); |
| } |
| |
| @Override |
| public ConsoleProxyVO findByName(String name) { |
| if (!VirtualMachineName.isValidConsoleProxyName(name)) { |
| return null; |
| } |
| return findById(VirtualMachineName.getConsoleProxyId(name)); |
| } |
| |
| @Override |
| public void finalizeStop(VirtualMachineProfile<ConsoleProxyVO> profile, StopAnswer answer) { |
| //release elastic IP here if assigned |
| IPAddressVO ip = _ipAddressDao.findByAssociatedVmId(profile.getId()); |
| if (ip != null && ip.getSystem()) { |
| UserContext ctx = UserContext.current(); |
| try { |
| _rulesMgr.disableStaticNat(ip.getId(), ctx.getCaller(), ctx.getCallerUserId(), true); |
| } catch (Exception ex) { |
| s_logger.warn("Failed to disable static nat and release system ip " + ip + " as a part of vm " + profile.getVirtualMachine() + " stop due to exception ", ex); |
| } |
| } |
| } |
| |
| @Override |
| public String getScanHandlerName() { |
| return "consoleproxy"; |
| } |
| |
| @Override |
| public void onScanStart() { |
| // to reduce possible number of DB queries for capacity scan, we run following aggregated queries in preparation |
| // stage |
| _zoneHostInfoMap = getZoneHostInfo(); |
| |
| _zoneProxyCountMap = new HashMap<Long, ConsoleProxyLoadInfo>(); |
| List<ConsoleProxyLoadInfo> listProxyCounts = _consoleProxyDao.getDatacenterProxyLoadMatrix(); |
| for (ConsoleProxyLoadInfo info : listProxyCounts) { |
| _zoneProxyCountMap.put(info.getId(), info); |
| } |
| |
| _zoneVmCountMap = new HashMap<Long, ConsoleProxyLoadInfo>(); |
| List<ConsoleProxyLoadInfo> listVmCounts = _consoleProxyDao.getDatacenterSessionLoadMatrix(); |
| for (ConsoleProxyLoadInfo info : listVmCounts) { |
| _zoneVmCountMap.put(info.getId(), info); |
| } |
| } |
| |
| private void scanManagementState() { |
| ConsoleProxyManagementState state = getManagementState(); |
| if (state != null) { |
| switch (state) { |
| case Auto: |
| case Manual: |
| case Suspending: |
| break; |
| |
| case ResetSuspending: |
| handleResetSuspending(); |
| break; |
| |
| default: |
| assert (false); |
| } |
| } |
| } |
| |
| private void handleResetSuspending() { |
| List<ConsoleProxyVO> runningProxies = _consoleProxyDao.getProxyListInStates(State.Running); |
| for (ConsoleProxyVO proxy : runningProxies) { |
| s_logger.info("Stop console proxy " + proxy.getId() + " because of we are currently in ResetSuspending management mode"); |
| this.stopProxy(proxy.getId()); |
| } |
| |
| // check if it is time to resume |
| List<ConsoleProxyVO> proxiesInTransition = _consoleProxyDao.getProxyListInStates(State.Running, State.Starting, State.Stopping); |
| if (proxiesInTransition.size() == 0) { |
| s_logger.info("All previous console proxy VMs in transition mode ceased the mode, we will now resume to last management state"); |
| this.resumeLastManagementState(); |
| } |
| } |
| |
| @Override |
| public boolean canScan() { |
| // take the chance to do management-state management |
| scanManagementState(); |
| |
| if (!reserveStandbyCapacity()) { |
| if (s_logger.isDebugEnabled()) { |
| s_logger.debug("Reserving standby capacity is disable, skip capacity scan"); |
| } |
| return false; |
| } |
| |
| List<StoragePoolVO> upPools = _storagePoolDao.listByStatus(StoragePoolStatus.Up); |
| if (upPools == null || upPools.size() == 0) { |
| s_logger.debug("Skip capacity scan due to there is no Primary Storage UPintenance mode"); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| @Override |
| public Long[] getScannablePools() { |
| List<DataCenterVO> zones = _dcDao.listEnabledZones(); |
| |
| Long[] dcIdList = new Long[zones.size()]; |
| int i = 0; |
| for (DataCenterVO dc : zones) { |
| dcIdList[i++] = dc.getId(); |
| } |
| |
| return dcIdList; |
| } |
| |
| @Override |
| public boolean isPoolReadyForScan(Long pool) { |
| // pool is at zone basis |
| long dataCenterId = pool.longValue(); |
| |
| if (!isZoneReady(_zoneHostInfoMap, dataCenterId)) { |
| if (s_logger.isDebugEnabled()) { |
| s_logger.debug("Zone " + dataCenterId + " is not ready to launch console proxy yet"); |
| } |
| return false; |
| } |
| |
| List<ConsoleProxyVO> l = _consoleProxyDao.getProxyListInStates(VirtualMachine.State.Starting, VirtualMachine.State.Stopping); |
| if (l.size() > 0) { |
| if (s_logger.isDebugEnabled()) { |
| s_logger.debug("Zone " + dataCenterId + " has " + l.size() + " console proxy VM(s) in transition state"); |
| } |
| |
| return false; |
| } |
| |
| if (s_logger.isDebugEnabled()) { |
| s_logger.debug("Zone " + dataCenterId + " is ready to launch console proxy"); |
| } |
| return true; |
| } |
| |
| @Override |
| public Pair<AfterScanAction, Object> scanPool(Long pool) { |
| long dataCenterId = pool.longValue(); |
| |
| ConsoleProxyLoadInfo proxyInfo = this._zoneProxyCountMap.get(dataCenterId); |
| if (proxyInfo == null) { |
| return new Pair<AfterScanAction, Object>(AfterScanAction.nop, null); |
| } |
| |
| ConsoleProxyLoadInfo vmInfo = this._zoneVmCountMap.get(dataCenterId); |
| if (vmInfo == null) { |
| vmInfo = new ConsoleProxyLoadInfo(); |
| } |
| |
| if (!checkCapacity(proxyInfo, vmInfo)) { |
| if (s_logger.isDebugEnabled()) { |
| s_logger.debug("Expand console proxy standby capacity for zone " + proxyInfo.getName()); |
| } |
| |
| return new Pair<AfterScanAction, Object>(AfterScanAction.expand, null); |
| } |
| |
| return new Pair<AfterScanAction, Object>(AfterScanAction.nop, null); |
| } |
| |
| @Override |
| public void expandPool(Long pool, Object actionArgs) { |
| long dataCenterId = pool.longValue(); |
| allocCapacity(dataCenterId); |
| } |
| |
| @Override |
| public void shrinkPool(Long pool, Object actionArgs) { |
| } |
| |
| @Override |
| public void onScanEnd() { |
| } |
| |
| @Override |
| public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { |
| if (!(cmd[0] instanceof StartupProxyCommand)) { |
| return null; |
| } |
| |
| host.setType(com.cloud.host.Host.Type.ConsoleProxy); |
| return host; |
| } |
| |
| @Override |
| public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details, |
| List<String> hostTags) { |
| // TODO Auto-generated method stub |
| return null; |
| } |
| |
| @Override |
| public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { |
| // TODO Auto-generated method stub |
| return null; |
| } |
| |
| protected HostVO findConsoleProxyHostByName(String name) { |
| SearchCriteriaService<HostVO, HostVO> sc = SearchCriteria2.create(HostVO.class); |
| sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.ConsoleProxy); |
| sc.addAnd(sc.getEntity().getName(), Op.EQ, name); |
| return sc.find(); |
| } |
| |
| @Override |
| public boolean plugNic(Network network, NicTO nic, VirtualMachineTO vm, |
| ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException, |
| InsufficientCapacityException { |
| //not supported |
| throw new UnsupportedOperationException("Plug nic is not supported for vm of type " + vm.getType()); |
| } |
| |
| |
| @Override |
| public boolean unplugNic(Network network, NicTO nic, VirtualMachineTO vm, |
| ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException { |
| //not supported |
| throw new UnsupportedOperationException("Unplug nic is not supported for vm of type " + vm.getType()); |
| } |
| |
| @Override |
| public void prepareStop(VirtualMachineProfile<ConsoleProxyVO> profile) { |
| } |
| |
| } |