Skip to content

Commit e3ae08b

Browse files
committed
CLOUDSTACK-9709: Updated the vm ip fetch task to use the correct the thread
1 parent 61ce75e commit e3ae08b

File tree

4 files changed

+209
-6
lines changed

4 files changed

+209
-6
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//
2+
// Licensed to the Apache Software Foundation (ASF) under one
3+
// or more contributor license agreements. See the NOTICE file
4+
// distributed with this work for additional information
5+
// regarding copyright ownership. The ASF licenses this file
6+
// to you under the Apache License, Version 2.0 (the
7+
// "License"); you may not use this file except in compliance
8+
// with the License. You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing,
13+
// software distributed under the License is distributed on an
14+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
// KIND, either express or implied. See the License for the
16+
// specific language governing permissions and limitations
17+
// under the License.
18+
//
19+
20+
package com.cloud.hypervisor.kvm.resource.wrapper;
21+
22+
import com.cloud.agent.api.Answer;
23+
import com.cloud.agent.api.GetVmIpAddressCommand;
24+
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
25+
import com.cloud.resource.CommandWrapper;
26+
import com.cloud.resource.ResourceWrapper;
27+
import com.cloud.utils.net.NetUtils;
28+
import com.cloud.utils.script.Script;
29+
import org.apache.log4j.Logger;
30+
31+
@ResourceWrapper(handles = GetVmIpAddressCommand.class)
32+
public final class LibvirtGetVmIpAddressCommandWrapper extends CommandWrapper<GetVmIpAddressCommand, Answer, LibvirtComputingResource> {
33+
34+
private static final Logger s_logger = Logger.getLogger(LibvirtGetVmIpAddressCommandWrapper.class);
35+
36+
@Override
37+
public Answer execute(final GetVmIpAddressCommand command, final LibvirtComputingResource libvirtComputingResource) {
38+
String ip = null;
39+
boolean result = false;
40+
String networkCidr = command.getVmNetworkCidr();
41+
if(!command.isWindows()) {
42+
//List all dhcp lease files inside guestVm
43+
String leasesList = Script.runSimpleBashScript(new StringBuilder().append("virt-ls ").append(command.getVmName())
44+
.append(" /var/lib/dhclient/ | grep .*\\*.leases").toString());
45+
if(leasesList != null) {
46+
String[] leasesFiles = leasesList.split("\n");
47+
for(String leaseFile : leasesFiles){
48+
//Read from each dhclient lease file inside guest Vm using virt-cat libguestfs ulitiy
49+
String ipAddr = Script.runSimpleBashScript(new StringBuilder().append("virt-cat ").append(command.getVmName())
50+
.append(" /var/lib/dhclient/" + leaseFile + " | tail -16 | grep 'fixed-address' | awk '{print $2}' | sed -e 's/;//'").toString());
51+
// Check if the IP belongs to the network
52+
if((ipAddr != null) && NetUtils.isIpWithtInCidrRange(ipAddr, networkCidr)){
53+
ip = ipAddr;
54+
break;
55+
}
56+
s_logger.debug("GetVmIp: "+command.getVmName()+ " Ip: "+ipAddr+" does not belong to network "+networkCidr);
57+
}
58+
}
59+
} else {
60+
// For windows, read from guest Vm registry using virt-win-reg libguestfs ulitiy. Registry Path: HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Tcpip\Parameters\Interfaces\<service>\DhcpIPAddress
61+
String ipList = Script.runSimpleBashScript(new StringBuilder().append("virt-win-reg --unsafe-printable-strings ").append(command.getVmName())
62+
.append(" 'HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces' | grep DhcpIPAddress | awk -F : '{print $2}' | sed -e 's/^\"//' -e 's/\"$//'").toString());
63+
if(ipList != null) {
64+
s_logger.debug("GetVmIp: "+command.getVmName()+ "Ips: "+ipList);
65+
String[] ips = ipList.split("\n");
66+
for (String ipAddr : ips){
67+
// Check if the IP belongs to the network
68+
if((ipAddr != null) && NetUtils.isIpWithtInCidrRange(ipAddr, networkCidr)){
69+
ip = ipAddr;
70+
break;
71+
}
72+
s_logger.debug("GetVmIp: "+command.getVmName()+ " Ip: "+ipAddr+" does not belong to network "+networkCidr);
73+
}
74+
}
75+
}
76+
if(ip != null){
77+
result = true;
78+
s_logger.debug("GetVmIp: "+command.getVmName()+ " Found Ip: "+ip);
79+
}
80+
return new Answer(command, result, ip);
81+
}
82+
}

plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,9 @@
290290
import com.cloud.vm.VirtualMachine.PowerState;
291291
import com.cloud.vm.VirtualMachineName;
292292
import com.cloud.vm.VmDetailConstants;
293+
import com.vmware.vim25.GuestInfo;
294+
import com.vmware.vim25.VirtualMachineToolsStatus;
295+
import com.cloud.agent.api.GetVmIpAddressCommand;
293296

294297
public class VmwareResource implements StoragePoolResource, ServerResource, VmwareHostService, VirtualRouterDeployer {
295298
private static final Logger s_logger = Logger.getLogger(VmwareResource.class);
@@ -490,6 +493,8 @@ public Answer executeRequest(Command cmd) {
490493
return execute((ScaleVmCommand)cmd);
491494
} else if (clz == PvlanSetupCommand.class) {
492495
return execute((PvlanSetupCommand)cmd);
496+
} else if (clz == GetVmIpAddressCommand.class) {
497+
return execute((GetVmIpAddressCommand)cmd);
493498
} else if (clz == UnregisterNicCommand.class) {
494499
answer = execute((UnregisterNicCommand)cmd);
495500
} else {
@@ -3221,11 +3226,17 @@ protected Answer execute(RebootCommand cmd) {
32213226
s_logger.info("Executing resource RebootCommand: " + _gson.toJson(cmd));
32223227
}
32233228

3229+
boolean toolsInstallerMounted = false;
3230+
VirtualMachineMO vmMo = null;
32243231
VmwareContext context = getServiceContext();
32253232
VmwareHypervisorHost hyperHost = getHyperHost(context);
32263233
try {
3227-
VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(cmd.getVmName());
3234+
vmMo = hyperHost.findVmOnHyperHost(cmd.getVmName());
32283235
if (vmMo != null) {
3236+
if (vmMo.isToolsInstallerMounted()) {
3237+
toolsInstallerMounted = true;
3238+
s_logger.trace("Detected mounted vmware tools installer for :[" + cmd.getVmName() + "]");
3239+
}
32293240
try {
32303241
vmMo.rebootGuest();
32313242
return new RebootAnswer(cmd, "reboot succeeded", true);
@@ -3257,6 +3268,15 @@ protected Answer execute(RebootCommand cmd) {
32573268
String msg = "RebootCommand failed due to " + VmwareHelper.getExceptionMessage(e);
32583269
s_logger.error(msg);
32593270
return new RebootAnswer(cmd, msg, false);
3271+
} finally {
3272+
if (toolsInstallerMounted) {
3273+
try {
3274+
vmMo.mountToolsInstaller();
3275+
s_logger.debug("Successfully re-mounted vmware tools installer for :[" + cmd.getVmName() + "]");
3276+
} catch (Exception e) {
3277+
s_logger.warn("Unabled to re-mount vmware tools installer for :[" + cmd.getVmName() + "]");
3278+
}
3279+
}
32603280
}
32613281
}
32623282

@@ -4366,6 +4386,59 @@ protected Answer execute(ModifySshKeysCommand cmd) {
43664386
}
43674387

43684388

4389+
protected Answer execute(GetVmIpAddressCommand cmd) {
4390+
if (s_logger.isTraceEnabled()) {
4391+
s_logger.trace("Executing resource command GetVmIpAddressCommand: " + _gson.toJson(cmd));
4392+
}
4393+
4394+
String details = "Unable to find IP Address of VM. ";
4395+
String vmName = cmd.getVmName();
4396+
boolean result = false;
4397+
String ip = null;
4398+
Answer answer = null;
4399+
4400+
VmwareContext context = getServiceContext();
4401+
VmwareHypervisorHost hyperHost = getHyperHost(context);
4402+
4403+
if (vmName == null || vmName.isEmpty()) {
4404+
details += "Name of instance provided is NULL or empty.";
4405+
return new Answer(cmd, result, details);
4406+
}
4407+
4408+
try {
4409+
VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
4410+
if (vmMo != null) {
4411+
GuestInfo guestInfo = vmMo.getGuestInfo();
4412+
VirtualMachineToolsStatus toolsStatus = guestInfo.getToolsStatus();
4413+
if (toolsStatus == VirtualMachineToolsStatus.TOOLS_NOT_INSTALLED) {
4414+
details += "Vmware tools not installed.";
4415+
} else {
4416+
ip = guestInfo.getIpAddress();
4417+
if (ip != null) {
4418+
result = true;
4419+
}
4420+
details = ip;
4421+
}
4422+
} else {
4423+
details += "VM " + vmName + " no longer exists on vSphere host: " + hyperHost.getHyperHostName();
4424+
s_logger.info(details);
4425+
}
4426+
} catch (Throwable e) {
4427+
if (e instanceof RemoteException) {
4428+
s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
4429+
invalidateServiceContext();
4430+
}
4431+
details += "Encountered exception : " + VmwareHelper.getExceptionMessage(e);
4432+
s_logger.error(details);
4433+
}
4434+
4435+
answer = new Answer(cmd, result, details);
4436+
if (s_logger.isTraceEnabled()) {
4437+
s_logger.trace("Returning GetVmIpAddressAnswer: " + _gson.toJson(answer));
4438+
}
4439+
return answer;
4440+
}
4441+
43694442
@Override
43704443
public PrimaryStorageDownloadAnswer execute(PrimaryStorageDownloadCommand cmd) {
43714444
if (s_logger.isInfoEnabled()) {

server/src/com/cloud/vm/UserVmManagerImpl.java

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
477477
protected IpAddressManager _ipAddrMgr;
478478

479479
protected ScheduledExecutorService _executor = null;
480+
protected ScheduledExecutorService _vmIpFetchExecutor = null;
480481
protected int _expungeInterval;
481482
protected int _expungeDelay;
482483
protected boolean _dailyOrHourly = false;
@@ -514,6 +515,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
514515
static final ConfigKey<Integer> VmIpFetchThreadPoolMax = new ConfigKey<Integer>("Advanced", Integer.class, "externaldhcp.vmipFetch.threadPool.max", "10",
515516
"number of threads for fetching vms ip address", true);
516517

518+
static final ConfigKey<Integer> VmIpFetchTaskWorkers = new ConfigKey<Integer>("Advanced", Integer.class, "externaldhcp.vmipfetchtask.workers", "10",
519+
"number of worker threads for vm ip fetch task ", true);
520+
517521

518522
@Override
519523
public UserVmVO getVirtualMachine(long vmId) {
@@ -1947,6 +1951,11 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
19471951

19481952
_executor = Executors.newScheduledThreadPool(wrks, new NamedThreadFactory("UserVm-Scavenger"));
19491953

1954+
String vmIpWorkers = configs.get(VmIpFetchTaskWorkers.value());
1955+
int vmipwrks = NumbersUtil.parseInt(vmIpWorkers, 10);
1956+
1957+
_vmIpFetchExecutor = Executors.newScheduledThreadPool(vmipwrks, new NamedThreadFactory("UserVm-ipfetch"));
1958+
19501959
String aggregationRange = configs.get("usage.stats.job.aggregation.range");
19511960
int _usageAggregationRange = NumbersUtil.parseInt(aggregationRange, 1440);
19521961
int HOURLY_TIME = 60;
@@ -1966,7 +1975,9 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
19661975
String value = _configDao.getValue(Config.SetVmInternalNameUsingDisplayName.key());
19671976
_instanceNameFlag = (value == null) ? false : Boolean.parseBoolean(value);
19681977

1969-
_scaleRetry = NumbersUtil.parseInt(configs.get(Config.ScaleRetry.key()), 2);
1978+
_scaleRetry = NumbersUtil.parseInt(configs.get(Config.ScaleRetry.key()), 2);
1979+
1980+
_vmIpFetchThreadExecutor = Executors.newFixedThreadPool(VmIpFetchThreadPoolMax.value(), new NamedThreadFactory("vmIpFetchThread"));
19701981

19711982
s_logger.info("User VM Manager is configured.");
19721983

@@ -1981,7 +1992,7 @@ public String getName() {
19811992
@Override
19821993
public boolean start() {
19831994
_executor.scheduleWithFixedDelay(new ExpungeTask(), _expungeInterval, _expungeInterval, TimeUnit.SECONDS);
1984-
_executor.scheduleWithFixedDelay(new VmIpFetchTask(), VmIpFetchWaitInterval.value(), VmIpFetchWaitInterval.value(), TimeUnit.SECONDS);
1995+
_vmIpFetchExecutor.scheduleWithFixedDelay(new VmIpFetchTask(), VmIpFetchWaitInterval.value(), VmIpFetchWaitInterval.value(), TimeUnit.SECONDS);
19851996
loadVmDetailsInMapForExternalDhcpIp();
19861997
return true;
19871998
}
@@ -2015,6 +2026,7 @@ private void loadVmDetailsInMapForExternalDhcpIp() {
20152026
@Override
20162027
public boolean stop() {
20172028
_executor.shutdown();
2029+
_vmIpFetchExecutor.shutdown();
20182030
return true;
20192031
}
20202032

@@ -2599,7 +2611,21 @@ public UserVm rebootVirtualMachine(RebootVMCmd cmd) throws InsufficientCapacityE
25992611
throw new InvalidParameterValueException("Unable to find service offering: " + serviceOfferingId + " corresponding to the vm");
26002612
}
26012613

2602-
return rebootVirtualMachine(CallContext.current().getCallingUserId(), vmId);
2614+
UserVm userVm = rebootVirtualMachine(CallContext.current().getCallingUserId(), vmId);
2615+
if (userVm != null ) {
2616+
// update the vmIdCountMap if the vm is in advanced shared network with out services
2617+
final List<NicVO> nics = _nicDao.listByVmId(vmId);
2618+
for (NicVO nic : nics) {
2619+
Network network = _networkModel.getNetwork(nic.getNetworkId());
2620+
if (_networkModel.isSharedNetworkWithoutServices(network.getId())) {
2621+
s_logger.debug("Adding vm " +vmId +" nic id "+ nic.getId() +" into vmIdCountMap as part of vm " +
2622+
"reboot for vm ip fetch ");
2623+
vmIdCountMap.put(nic.getId(), new VmAndCountDetails(nic.getInstanceId(), VmIpFetchTrialMax.value()));
2624+
}
2625+
}
2626+
return userVm;
2627+
}
2628+
return null;
26032629
}
26042630

26052631
@Override
@@ -3808,7 +3834,7 @@ public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile prof
38083834
}
38093835

38103836
@Override
3811-
public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) {
3837+
public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) {
38123838
UserVmVO vm = _vmDao.findById(profile.getId());
38133839

38143840
Answer[] answersToCmds = cmds.getAnswers();
@@ -3896,6 +3922,21 @@ public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Command
38963922
}
38973923
}
38983924

3925+
final VirtualMachineProfile vmProfile = profile;
3926+
Transaction.execute(new TransactionCallbackNoReturn() {
3927+
@Override
3928+
public void doInTransactionWithoutResult(TransactionStatus status) {
3929+
final UserVmVO vm = _vmDao.findById(vmProfile.getId());
3930+
final List<NicVO> nics = _nicDao.listByVmId(vm.getId());
3931+
for (NicVO nic : nics) {
3932+
Network network = _networkModel.getNetwork(nic.getNetworkId());
3933+
if (_networkModel.isSharedNetworkWithoutServices(network.getId())) {
3934+
vmIdCountMap.put(nic.getId(), new VmAndCountDetails(nic.getInstanceId(), VmIpFetchTrialMax.value()));
3935+
}
3936+
}
3937+
}
3938+
});
3939+
38993940
return true;
39003941
}
39013942

@@ -5835,7 +5876,7 @@ public String getConfigComponentName() {
58355876

58365877
@Override
58375878
public ConfigKey<?>[] getConfigKeys() {
5838-
return new ConfigKey<?>[] {EnableDynamicallyScaleVm, AllowUserExpungeRecoverVm, VmIpFetchWaitInterval, VmIpFetchTrialMax, VmIpFetchThreadPoolMax};
5879+
return new ConfigKey<?>[] {EnableDynamicallyScaleVm, AllowUserExpungeRecoverVm, VmIpFetchWaitInterval, VmIpFetchTrialMax, VmIpFetchThreadPoolMax, VmIpFetchTaskWorkers};
58395880
}
58405881

58415882
@Override

vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,13 @@ public VirtualMachineConfigInfo getConfigInfo() throws Exception {
751751
return (VirtualMachineConfigInfo)_context.getVimClient().getDynamicProperty(_mor, "config");
752752
}
753753

754+
public boolean isToolsInstallerMounted() throws Exception {
755+
return _context.getVimClient().getDynamicProperty(_mor, "runtime.toolsInstallerMounted");
756+
}
757+
public GuestInfo getGuestInfo() throws Exception {
758+
return (GuestInfo)_context.getVimClient().getDynamicProperty(_mor, "guest");
759+
}
760+
754761
public VirtualMachineConfigSummary getConfigSummary() throws Exception {
755762
return (VirtualMachineConfigSummary)_context.getVimClient().getDynamicProperty(_mor, "summary.config");
756763
}

0 commit comments

Comments
 (0)