mirror of https://github.com/apache/cloudstack.git
CLOUDSTACK-8324: Added vm ip fetch logic
This commit is contained in:
parent
70934e8c1a
commit
733ac2b728
|
|
@ -523,6 +523,7 @@ public class EventTypes {
|
|||
public static final String EVENT_NIC_SECONDARY_IP_ASSIGN = "NIC.SECONDARY.IP.ASSIGN";
|
||||
public static final String EVENT_NIC_SECONDARY_IP_UNASSIGN = "NIC.SECONDARY.IP.UNASSIGN";
|
||||
public static final String EVENT_NIC_SECONDARY_IP_CONFIGURE = "NIC.SECONDARY.IP.CONFIGURE";
|
||||
public static final String EVENT_NETWORK_EXTERNAL_DHCP_VM_IPFETCH = "EXTERNAL.DHCP.VM.IP.FETCH";
|
||||
|
||||
//Usage related events
|
||||
public static final String EVENT_USAGE_REMOVE_USAGE_RECORDS = "USAGE.REMOVE.USAGE.RECORDS";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// 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.agent.api;
|
||||
|
||||
public class GetVmIpAddressCommand extends Command {
|
||||
|
||||
String vmName;
|
||||
String vmNetworkCidr;
|
||||
boolean windows = false;
|
||||
|
||||
public GetVmIpAddressCommand(String vmName, String vmNetworkCidr, boolean windows) {
|
||||
this.vmName = vmName;
|
||||
this.windows = windows;
|
||||
this.vmNetworkCidr = vmNetworkCidr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getVmName(){
|
||||
return vmName;
|
||||
}
|
||||
|
||||
public boolean isWindows(){
|
||||
return windows;
|
||||
}
|
||||
|
||||
public String getVmNetworkCidr() {
|
||||
return vmNetworkCidr;
|
||||
}
|
||||
}
|
||||
|
|
@ -56,6 +56,11 @@ public class VmDataCommand extends NetworkElementCommand {
|
|||
this.executeInSequence = executeInSequence;
|
||||
}
|
||||
|
||||
public VmDataCommand(String vmName) {
|
||||
this.vmName = vmName;
|
||||
this.vmData = new ArrayList<String[]>();
|
||||
}
|
||||
|
||||
public String getVmIpAddress() {
|
||||
return vmIpAddress;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ public interface NetworkDao extends GenericDao<NetworkVO, Long>, StateDao<State,
|
|||
|
||||
List<NetworkVO> listByOwner(long ownerId);
|
||||
|
||||
List<NetworkVO> listByGuestType(GuestType type);
|
||||
|
||||
List<NetworkVO> listBy(long accountId, long offeringId, long dataCenterId);
|
||||
|
||||
List<NetworkVO> listBy(long accountId, long dataCenterId, String cidr, boolean skipVpc);
|
||||
|
|
|
|||
|
|
@ -270,6 +270,14 @@ public class NetworkDaoImpl extends GenericDaoBase<NetworkVO, Long> implements N
|
|||
return listBy(sc, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NetworkVO> listByGuestType(Network.GuestType type) {
|
||||
SearchCriteria<NetworkVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("guestType", type);
|
||||
return listBy(sc, null);
|
||||
}
|
||||
|
||||
|
||||
public List<NetworkVO> findBy(final TrafficType trafficType, final Mode mode, final BroadcastDomainType broadcastType, final long networkOfferingId, final long dataCenterId) {
|
||||
final SearchCriteria<NetworkVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("trafficType", trafficType);
|
||||
|
|
|
|||
|
|
@ -27,8 +27,10 @@ import java.util.Map;
|
|||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.ejb.Local;
|
||||
|
|
@ -97,6 +99,7 @@ import com.cloud.agent.api.GetVmDiskStatsCommand;
|
|||
import com.cloud.agent.api.GetVmStatsAnswer;
|
||||
import com.cloud.agent.api.GetVmStatsCommand;
|
||||
import com.cloud.agent.api.PvlanSetupCommand;
|
||||
import com.cloud.agent.api.GetVmIpAddressCommand;
|
||||
import com.cloud.agent.api.StartAnswer;
|
||||
import com.cloud.agent.api.VmDiskStatsEntry;
|
||||
import com.cloud.agent.api.VmStatsEntry;
|
||||
|
|
@ -129,9 +132,12 @@ import com.cloud.deploy.DeploymentPlanningManager;
|
|||
import com.cloud.deploy.PlannerHostReservationVO;
|
||||
import com.cloud.deploy.dao.PlannerHostReservationDao;
|
||||
import com.cloud.domain.DomainVO;
|
||||
import com.cloud.domain.Domain;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import com.cloud.event.ActionEvent;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.event.ActionEventUtils;
|
||||
import com.cloud.event.ActionEventUtils;
|
||||
import com.cloud.event.UsageEventUtils;
|
||||
import com.cloud.event.UsageEventVO;
|
||||
import com.cloud.event.dao.UsageEventDao;
|
||||
|
|
@ -475,11 +481,14 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
protected int _expungeDelay;
|
||||
protected boolean _dailyOrHourly = false;
|
||||
private int capacityReleaseInterval;
|
||||
ExecutorService _vmIpFetchThreadExecutor;
|
||||
|
||||
|
||||
protected String _instance;
|
||||
protected String _zone;
|
||||
protected boolean _instanceNameFlag;
|
||||
protected int _scaleRetry;
|
||||
protected Map<Long, VmAndCountDetails> vmIdCountMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Inject
|
||||
ConfigurationDao _configDao;
|
||||
|
|
@ -496,6 +505,16 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
@Inject
|
||||
ManagementService _mgr;
|
||||
|
||||
static final ConfigKey<Integer> VmIpFetchWaitInterval = new ConfigKey<Integer>("Advanced", Integer.class, "externaldhcp.vmip.retrieval.interval", "180",
|
||||
"Wait Interval (in seconds) for shared network vm dhcp ip addr fetch for next iteration ", true);
|
||||
|
||||
static final ConfigKey<Integer> VmIpFetchTrialMax = new ConfigKey<Integer>("Advanced", Integer.class, "externaldhcp.vmip.max.retry", "10",
|
||||
"The max number of retrieval times for shared entwork vm dhcp ip fetch, in case of failures", true);
|
||||
|
||||
static final ConfigKey<Integer> VmIpFetchThreadPoolMax = new ConfigKey<Integer>("Advanced", Integer.class, "externaldhcp.vmipFetch.threadPool.max", "10",
|
||||
"number of threads for fetching vms ip address", true);
|
||||
|
||||
|
||||
@Override
|
||||
public UserVmVO getVirtualMachine(long vmId) {
|
||||
return _vmDao.findById(vmId);
|
||||
|
|
@ -524,6 +543,122 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
_resourceLimitMgr.decrementResourceCount(accountId, ResourceType.memory, displayVm, memory);
|
||||
}
|
||||
|
||||
public class VmAndCountDetails {
|
||||
long vmId;
|
||||
int retrievalCount = VmIpFetchTrialMax.value();
|
||||
|
||||
|
||||
public VmAndCountDetails() {
|
||||
}
|
||||
|
||||
public VmAndCountDetails (long vmId, int retrievalCount) {
|
||||
this.vmId = vmId;
|
||||
this.retrievalCount = retrievalCount;
|
||||
}
|
||||
|
||||
public VmAndCountDetails (long vmId) {
|
||||
this.vmId = vmId;
|
||||
}
|
||||
|
||||
public int getRetrievalCount() {
|
||||
return retrievalCount;
|
||||
}
|
||||
|
||||
public void setRetrievalCount(int retrievalCount) {
|
||||
this.retrievalCount = retrievalCount;
|
||||
}
|
||||
|
||||
public long getVmId() {
|
||||
return vmId;
|
||||
}
|
||||
|
||||
public void setVmId(long vmId) {
|
||||
this.vmId = vmId;
|
||||
}
|
||||
|
||||
public void decrementCount() {
|
||||
this.retrievalCount--;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected class VmIpAddrFetchThread extends ManagedContextRunnable {
|
||||
|
||||
|
||||
long nicId;
|
||||
long vmId;
|
||||
String vmName;
|
||||
boolean isWindows;
|
||||
Long hostId;
|
||||
String networkCidr;
|
||||
|
||||
public VmIpAddrFetchThread() {
|
||||
}
|
||||
|
||||
public VmIpAddrFetchThread(long vmId, long nicId, String instanceName, boolean windows, Long hostId, String networkCidr) {
|
||||
this.vmId = vmId;
|
||||
this.nicId = nicId;
|
||||
this.vmName = instanceName;
|
||||
this.isWindows = windows;
|
||||
this.hostId = hostId;
|
||||
this.networkCidr = networkCidr;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void runInContext() {
|
||||
GetVmIpAddressCommand cmd = new GetVmIpAddressCommand(vmName, networkCidr, isWindows);
|
||||
boolean decrementCount = true;
|
||||
|
||||
try {
|
||||
s_logger.debug("Trying for vm "+ vmId +" nic Id "+nicId +" ip retrieval ...");
|
||||
Answer answer = _agentMgr.send(hostId, cmd);
|
||||
NicVO nic = _nicDao.findById(nicId);
|
||||
if (answer.getResult()) {
|
||||
String vmIp = answer.getDetails();
|
||||
|
||||
if (NetUtils.isValidIp(vmIp)) {
|
||||
// set this vm ip addr in vm nic.
|
||||
if (nic != null) {
|
||||
nic.setIp4Address(vmIp);
|
||||
_nicDao.update(nicId, nic);
|
||||
s_logger.debug("Vm "+ vmId +" IP "+vmIp +" got retrieved successfully");
|
||||
vmIdCountMap.remove(nicId);
|
||||
decrementCount = false;
|
||||
ActionEventUtils.onActionEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM,
|
||||
Domain.ROOT_DOMAIN, EventTypes.EVENT_NETWORK_EXTERNAL_DHCP_VM_IPFETCH,
|
||||
"VM " + vmId + " nic id " + nicId + " ip address " + vmIp + " got fetched successfully");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//previously vm has ip and nic table has ip address. After vm restart or stop/start
|
||||
//if vm doesnot get the ip then set the ip in nic table to null
|
||||
if (nic.getIp4Address() != null) {
|
||||
nic.setIp4Address(null);
|
||||
_nicDao.update(nicId, nic);
|
||||
}
|
||||
if (answer.getDetails() != null) {
|
||||
s_logger.debug("Failed to get vm ip for Vm "+ vmId + answer.getDetails());
|
||||
}
|
||||
}
|
||||
} catch (OperationTimedoutException e) {
|
||||
s_logger.warn("Timed Out", e);
|
||||
} catch (AgentUnavailableException e) {
|
||||
s_logger.warn("Agent Unavailable ", e);
|
||||
} finally {
|
||||
if (decrementCount) {
|
||||
VmAndCountDetails vmAndCount = vmIdCountMap.get(nicId);
|
||||
vmAndCount.decrementCount();
|
||||
s_logger.debug("Ip is not retrieved for VM " + vmId +" nic "+nicId + " ... decremented count to "+vmAndCount.getRetrievalCount());
|
||||
vmIdCountMap.put(nicId, vmAndCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
@ActionEvent(eventType = EventTypes.EVENT_VM_RESETPASSWORD, eventDescription = "resetting Vm password", async = true)
|
||||
public UserVm resetVMPassword(ResetVMPasswordCmd cmd, String password) throws ResourceUnavailableException, InsufficientCapacityException {
|
||||
|
|
@ -1716,9 +1851,37 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
@Override
|
||||
public boolean start() {
|
||||
_executor.scheduleWithFixedDelay(new ExpungeTask(), _expungeInterval, _expungeInterval, TimeUnit.SECONDS);
|
||||
_executor.scheduleWithFixedDelay(new VmIpFetchTask(), VmIpFetchWaitInterval.value(), VmIpFetchWaitInterval.value(), TimeUnit.SECONDS);
|
||||
loadVmDetailsInMapForExternalDhcpIp();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void loadVmDetailsInMapForExternalDhcpIp() {
|
||||
|
||||
List<NetworkVO> networks = _networkDao.listByGuestType(Network.GuestType.Shared);
|
||||
|
||||
for (NetworkVO network: networks) {
|
||||
if(_networkModel.isSharedNetworkWithoutServices(network.getId())) {
|
||||
List<NicVO> nics = _nicDao.listByNetworkId(network.getId());
|
||||
|
||||
for (NicVO nic : nics) {
|
||||
|
||||
if (nic.getIp4Address() == null) {
|
||||
long nicId = nic.getId();
|
||||
long vmId = nic.getInstanceId();
|
||||
VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId);
|
||||
|
||||
// only load running vms. For stopped vms get loaded on starting
|
||||
if (vmInstance.getState() == State.Running) {
|
||||
VmAndCountDetails vmAndCount = new VmAndCountDetails(vmId, VmIpFetchTrialMax.value());
|
||||
vmIdCountMap.put(nicId, vmAndCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
_executor.shutdown();
|
||||
|
|
@ -1872,6 +2035,66 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected class VmIpFetchTask extends ManagedContextRunnable {
|
||||
|
||||
public VmIpFetchTask() {
|
||||
GlobalLock scanLock = GlobalLock.getInternLock("vmIpFetch");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void runInContext() {
|
||||
GlobalLock scanLock = GlobalLock.getInternLock("vmIpFetch");
|
||||
|
||||
try {
|
||||
if (scanLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION)) {
|
||||
try {
|
||||
|
||||
for (Entry<Long, VmAndCountDetails> entry: vmIdCountMap.entrySet()) {
|
||||
long nicId = entry.getKey();
|
||||
VmAndCountDetails vmIdAndCount = entry.getValue();
|
||||
long vmId = vmIdAndCount.getVmId();
|
||||
|
||||
if (vmIdAndCount.getRetrievalCount() <= 0) {
|
||||
vmIdCountMap.remove(nicId);
|
||||
s_logger.debug("Vm " + vmId +" nic "+nicId + " count is zero .. removing vm nic from map ");
|
||||
|
||||
ActionEventUtils.onActionEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM,
|
||||
Domain.ROOT_DOMAIN, EventTypes.EVENT_NETWORK_EXTERNAL_DHCP_VM_IPFETCH,
|
||||
"VM " + vmId + " nic id "+ nicId + " ip addr fetch failed ");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
UserVm userVm = _vmDao.findById(vmId);
|
||||
VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId);
|
||||
NicVO nicVo = _nicDao.findById(nicId);
|
||||
NetworkVO network = _networkDao.findById(nicVo.getNetworkId());
|
||||
|
||||
VirtualMachineProfile vmProfile = new VirtualMachineProfileImpl(userVm);
|
||||
VirtualMachine vm = vmProfile.getVirtualMachine();
|
||||
boolean isWindows = _guestOSCategoryDao.findById(_guestOSDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
|
||||
|
||||
_vmIpFetchThreadExecutor.execute(new VmIpAddrFetchThread(vmId, nicId, vmInstance.getInstanceName(),
|
||||
isWindows, vm.getHostId(), network.getCidr()));
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.error("Caught the Exception in VmIpFetchTask", e);
|
||||
} finally {
|
||||
scanLock.unlock();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
scanLock.releaseRef();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected class ExpungeTask extends ManagedContextRunnable {
|
||||
public ExpungeTask() {
|
||||
}
|
||||
|
|
@ -5045,7 +5268,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
@Override
|
||||
public ConfigKey<?>[] getConfigKeys() {
|
||||
return new ConfigKey<?>[] {EnableDynamicallyScaleVm};
|
||||
return new ConfigKey<?>[] {EnableDynamicallyScaleVm, VmIpFetchWaitInterval, VmIpFetchTrialMax, VmIpFetchThreadPoolMax};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -45,6 +45,11 @@ public class MockNetworkDaoImpl extends GenericDaoBase<NetworkVO, Long> implemen
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NetworkVO> listByGuestType(GuestType type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.cloud.network.dao.NetworkDao#listBy(long, long, long)
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue