CLOUDSTACK-8324: Added vm ip fetch logic

This commit is contained in:
Jayapal 2015-05-20 10:24:44 +05:30
parent 70934e8c1a
commit 733ac2b728
7 changed files with 295 additions and 1 deletions

View File

@ -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";

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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)
*/