add use of virsh domifaddr to get VM external DHCP IP (#10376)

* add use of virsh domifaddr to get VM external DHCP IP

* updates to modularize LibvirtGetVmIpAddressCommandWrapper per comments; added test cases to cover 90%+ scenarios

* updates to modularize LibvirtGetVmIpAddressCommandWrapper per comments; added test cases to cover 90%+ scenarios

* updates to modularize LibvirtGetVmIpAddressCommandWrapper per comments; added test cases to cover 90%+ scenarios
This commit is contained in:
Rene Glover 2025-02-27 22:43:53 -06:00 committed by GitHub
parent f992ebb52a
commit f0179855f5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 440 additions and 51 deletions

View File

@ -29,6 +29,7 @@ import com.cloud.agent.api.GetVmIpAddressCommand;
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
import com.cloud.resource.CommandWrapper;
import com.cloud.resource.ResourceWrapper;
import com.cloud.utils.Pair;
import com.cloud.utils.net.NetUtils;
import com.cloud.utils.script.Script;
@ -37,6 +38,26 @@ public final class LibvirtGetVmIpAddressCommandWrapper extends CommandWrapper<Ge
private static final Logger s_logger = Logger.getLogger(LibvirtGetVmIpAddressCommandWrapper.class);
static String virsh_path = null;
static String virt_win_reg_path = null;
static String grep_path = null;
static String awk_path = null;
static String sed_path = null;
static String virt_ls_path = null;
static String virt_cat_path = null;
static String tail_path = null;
static void init() {
virt_ls_path = Script.getExecutableAbsolutePath("virt-ls");
virt_cat_path = Script.getExecutableAbsolutePath("virt-cat");
virt_win_reg_path = Script.getExecutableAbsolutePath("virt-win-reg");
tail_path = Script.getExecutableAbsolutePath("tail");
grep_path = Script.getExecutableAbsolutePath("grep");
awk_path = Script.getExecutableAbsolutePath("awk");
sed_path = Script.getExecutableAbsolutePath("sed");
virsh_path = Script.getExecutableAbsolutePath("virsh");
}
@Override
public Answer execute(final GetVmIpAddressCommand command, final LibvirtComputingResource libvirtComputingResource) {
String ip = null;
@ -45,65 +66,113 @@ public final class LibvirtGetVmIpAddressCommandWrapper extends CommandWrapper<Ge
if (!NetUtils.verifyDomainNameLabel(vmName, true)) {
return new Answer(command, result, ip);
}
String sanitizedVmName = sanitizeBashCommandArgument(vmName);
String networkCidr = command.getVmNetworkCidr();
List<String[]> commands = new ArrayList<>();
final String virt_ls_path = Script.getExecutableAbsolutePath("virt-ls");
final String virt_cat_path = Script.getExecutableAbsolutePath("virt-cat");
final String virt_win_reg_path = Script.getExecutableAbsolutePath("virt-win-reg");
final String tail_path = Script.getExecutableAbsolutePath("tail");
final String grep_path = Script.getExecutableAbsolutePath("grep");
final String awk_path = Script.getExecutableAbsolutePath("awk");
final String sed_path = Script.getExecutableAbsolutePath("sed");
if(!command.isWindows()) {
//List all dhcp lease files inside guestVm
commands.add(new String[]{virt_ls_path, sanitizedVmName, "/var/lib/dhclient/"});
commands.add(new String[]{grep_path, ".*\\*.leases"});
String leasesList = Script.executePipedCommands(commands, 0).second();
if(leasesList != null) {
String[] leasesFiles = leasesList.split("\n");
for(String leaseFile : leasesFiles){
//Read from each dhclient lease file inside guest Vm using virt-cat libguestfs utility
commands = new ArrayList<>();
commands.add(new String[]{virt_cat_path, sanitizedVmName, "/var/lib/dhclient/" + leaseFile});
commands.add(new String[]{tail_path, "-16"});
commands.add(new String[]{grep_path, "fixed-address"});
commands.add(new String[]{awk_path, "{print $2}"});
commands.add(new String[]{sed_path, "-e", "s/;//"});
String ipAddr = Script.executePipedCommands(commands, 0).second();
// Check if the IP belongs to the network
if((ipAddr != null) && NetUtils.isIpWithInCidrRange(ipAddr, networkCidr)) {
ip = ipAddr;
break;
}
s_logger.debug("GetVmIp: "+ vmName + " Ip: "+ipAddr+" does not belong to network "+networkCidr);
}
}
} else {
// 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
commands = new ArrayList<>();
commands.add(new String[]{virt_win_reg_path, "--unsafe-printable-strings", sanitizedVmName, "HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces"});
commands.add(new String[]{grep_path, "DhcpIPAddress"});
commands.add(new String[]{awk_path, "-F", ":", "{print $2}"});
commands.add(new String[]{sed_path, "-e", "s/^\"//", "-e", "s/\"$//"});
String ipList = Script.executePipedCommands(commands, 0).second();
if(ipList != null) {
s_logger.debug("GetVmIp: "+ vmName + "Ips: "+ipList);
String[] ips = ipList.split("\n");
for (String ipAddr : ips){
// Check if the IP belongs to the network
if((ipAddr != null) && NetUtils.isIpWithInCidrRange(ipAddr, networkCidr)){
ip = ipAddr;
break;
}
s_logger.debug("GetVmIp: "+ vmName + " Ip: "+ipAddr+" does not belong to network "+networkCidr);
}
ip = ipFromDomIf(sanitizedVmName, networkCidr);
if (ip == null) {
if(!command.isWindows()) {
ip = ipFromDhcpLeaseFile(sanitizedVmName, networkCidr);
} else {
ip = ipFromWindowsRegistry(sanitizedVmName, networkCidr);
}
}
if(ip != null){
result = true;
s_logger.debug("GetVmIp: "+ vmName + " Found Ip: "+ip);
} else {
s_logger.warn("GetVmIp: "+ vmName + " IP not found.");
}
return new Answer(command, result, ip);
}
private String ipFromDomIf(String sanitizedVmName, String networkCidr) {
String ip = null;
List<String[]> commands = new ArrayList<>();
commands.add(new String[]{virsh_path, "domifaddr", sanitizedVmName, "--source", "agent"});
Pair<Integer,String> response = executePipedCommands(commands, 0);
if (response != null) {
String output = response.second();
String[] lines = output.split("\n");
for (String line : lines) {
if (line.contains("ipv4")) {
String[] parts = line.split(" ");
String[] ipParts = parts[parts.length-1].split("/");
if (ipParts.length > 1) {
if (NetUtils.isIpWithInCidrRange(ipParts[0], networkCidr)) {
ip = ipParts[0];
break;
}
}
}
}
} else {
s_logger.error("ipFromDomIf: Command execution failed for VM: " + sanitizedVmName);
}
return ip;
}
private String ipFromDhcpLeaseFile(String sanitizedVmName, String networkCidr) {
String ip = null;
List<String[]> commands = new ArrayList<>();
commands.add(new String[]{virt_ls_path, sanitizedVmName, "/var/lib/dhclient/"});
commands.add(new String[]{grep_path, ".*\\*.leases"});
Pair<Integer,String> response = executePipedCommands(commands, 0);
if(response != null && response.second() != null) {
String leasesList = response.second();
String[] leasesFiles = leasesList.split("\n");
for(String leaseFile : leasesFiles){
commands = new ArrayList<>();
commands.add(new String[]{virt_cat_path, sanitizedVmName, "/var/lib/dhclient/" + leaseFile});
commands.add(new String[]{tail_path, "-16"});
commands.add(new String[]{grep_path, "fixed-address"});
commands.add(new String[]{awk_path, "{print $2}"});
commands.add(new String[]{sed_path, "-e", "s/;//"});
String ipAddr = executePipedCommands(commands, 0).second();
if((ipAddr != null) && NetUtils.isIpWithInCidrRange(ipAddr, networkCidr)) {
ip = ipAddr;
break;
}
s_logger.debug("GetVmIp: "+ sanitizedVmName + " Ip: "+ipAddr+" does not belong to network "+networkCidr);
}
} else {
s_logger.error("ipFromDhcpLeaseFile: Command execution failed for VM: " + sanitizedVmName);
}
return ip;
}
private String ipFromWindowsRegistry(String sanitizedVmName, String networkCidr) {
String ip = null;
List<String[]> commands = new ArrayList<>();
commands.add(new String[]{virt_win_reg_path, "--unsafe-printable-strings", sanitizedVmName, "HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces"});
commands.add(new String[]{grep_path, "DhcpIPAddress"});
commands.add(new String[]{awk_path, "-F", ":", "{print $2}"});
commands.add(new String[]{sed_path, "-e", "s/^\"//", "-e", "s/\"$//"});
Pair<Integer,String> pair = executePipedCommands(commands, 0);
if(pair != null && pair.second() != null) {
String ipList = pair.second();
ipList = ipList.replaceAll("\"", "");
s_logger.debug("GetVmIp: "+ sanitizedVmName + "Ips: "+ipList);
String[] ips = ipList.split("\n");
for (String ipAddr : ips){
if((ipAddr != null) && NetUtils.isIpWithInCidrRange(ipAddr, networkCidr)){
ip = ipAddr;
break;
}
s_logger.debug("GetVmIp: "+ sanitizedVmName + " Ip: "+ipAddr+" does not belong to network "+networkCidr);
}
} else {
s_logger.error("ipFromWindowsRegistry: Command execution failed for VM: " + sanitizedVmName);
}
return ip;
}
static Pair<Integer, String> executePipedCommands(List<String[]> commands, long timeout) {
return Script.executePipedCommands(commands, timeout);
}
}

View File

@ -0,0 +1,320 @@
//
// 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.hypervisor.kvm.resource.wrapper;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockedStatic;
import org.mockito.MockitoAnnotations;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.GetVmIpAddressCommand;
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
import com.cloud.utils.Pair;
import com.cloud.utils.script.Script;
public class LibvirtGetVmIpAddressCommandWrapperTest {
private static String VIRSH_DOMIF_OUTPUT = " Name MAC address Protocol Address\n" + //
"-------------------------------------------------------------------------------\n" + //
" lo 00:00:00:00:00:70 ipv4 127.0.0.1/8\n" + //
" eth0 02:0c:02:f9:00:80 ipv4 192.168.0.10/24\n" + //
" net1 b2:41:19:69:a4:90 N/A N/A\n" + //
" net2 52:a2:36:cf:d1:50 ipv4 10.244.6.93/32\n" + //
" net3 a6:1d:d3:52:d3:40 N/A N/A\n" + //
" net4 2e:9b:60:dc:49:30 N/A N/A\n" + //
" lxc5b7327203b6f 92:b2:77:0b:a9:20 N/A N/A\n";
@Before
public void setUp() {
MockitoAnnotations.openMocks(this);
}
@Test
public void testExecuteWithValidVmName() {
LibvirtComputingResource libvirtComputingResource = mock(LibvirtComputingResource.class);
GetVmIpAddressCommand getVmIpAddressCommand = mock(GetVmIpAddressCommand.class);
LibvirtGetVmIpAddressCommandWrapper commandWrapper = new LibvirtGetVmIpAddressCommandWrapper();
MockedStatic<Script> scriptMock = mockStatic(Script.class);
when(getVmIpAddressCommand.getVmName()).thenReturn("validVmName");
when(getVmIpAddressCommand.getVmNetworkCidr()).thenReturn("192.168.0.0/24");
when(getVmIpAddressCommand.isWindows()).thenReturn(false);
when(Script.executePipedCommands(anyList(), anyLong())).thenReturn(new Pair<>(0, VIRSH_DOMIF_OUTPUT));
Answer answer = commandWrapper.execute(getVmIpAddressCommand, libvirtComputingResource);
try {
assertTrue(answer.getResult());
assertEquals("192.168.0.10", answer.getDetails());
} finally {
scriptMock.close();
}
}
@Test
public void testExecuteWithInvalidVmName() {
LibvirtComputingResource libvirtComputingResource = mock(LibvirtComputingResource.class);
GetVmIpAddressCommand getVmIpAddressCommand = mock(GetVmIpAddressCommand.class);
LibvirtGetVmIpAddressCommandWrapper commandWrapper = new LibvirtGetVmIpAddressCommandWrapper();
MockedStatic<Script> scriptMock = mockStatic(Script.class);
when(getVmIpAddressCommand.getVmName()).thenReturn("invalidVmName!");
when(getVmIpAddressCommand.getVmNetworkCidr()).thenReturn("192.168.0.0/24");
when(getVmIpAddressCommand.isWindows()).thenReturn(false);
when(Script.executePipedCommands(anyList(), anyLong())).thenReturn(new Pair<>(0, VIRSH_DOMIF_OUTPUT));
Answer answer = commandWrapper.execute(getVmIpAddressCommand, libvirtComputingResource);
try {
assertFalse(answer.getResult());
assertNull(answer.getDetails());
} finally {
scriptMock.close();
}
}
@Test
public void testExecuteWithWindowsVm() {
LibvirtComputingResource libvirtComputingResource = mock(LibvirtComputingResource.class);
GetVmIpAddressCommand getVmIpAddressCommand = mock(GetVmIpAddressCommand.class);
LibvirtGetVmIpAddressCommandWrapper commandWrapper = new LibvirtGetVmIpAddressCommandWrapper();
MockedStatic<Script> scriptMock = null;
try {
scriptMock = mockStatic(Script.class);
when(getVmIpAddressCommand.getVmName()).thenReturn("validVmName");
when(getVmIpAddressCommand.getVmNetworkCidr()).thenReturn("192.168.0.0/24");
when(getVmIpAddressCommand.isWindows()).thenReturn(true);
when(Script.executePipedCommands(anyList(), anyLong())).thenReturn(new Pair<>(0, "192.168.0.10"));
Answer answer = commandWrapper.execute(getVmIpAddressCommand, libvirtComputingResource);
assertTrue(answer.getResult());
assertEquals("192.168.0.10", answer.getDetails());
} finally {
if (scriptMock != null)
scriptMock.close();
}
}
@Test
public void testExecuteWithNoIpFound() {
LibvirtComputingResource libvirtComputingResource = mock(LibvirtComputingResource.class);
GetVmIpAddressCommand getVmIpAddressCommand = mock(GetVmIpAddressCommand.class);
LibvirtGetVmIpAddressCommandWrapper commandWrapper = new LibvirtGetVmIpAddressCommandWrapper();
MockedStatic<Script> scriptMock = null;
try {
scriptMock = mockStatic(Script.class);
when(getVmIpAddressCommand.getVmName()).thenReturn("validVmName");
when(getVmIpAddressCommand.getVmNetworkCidr()).thenReturn("192.168.0.0/24");
when(getVmIpAddressCommand.isWindows()).thenReturn(false);
when(Script.executePipedCommands(anyList(), anyLong())).thenReturn(new Pair<>(0, ""));
Answer answer = commandWrapper.execute(getVmIpAddressCommand, libvirtComputingResource);
assertFalse(answer.getResult());
assertNull(answer.getDetails());
} finally {
if (scriptMock != null)
scriptMock.close();
}
}
@Test
public void testExecuteWithValidVmNameAndNoIpFound() {
LibvirtComputingResource libvirtComputingResource = mock(LibvirtComputingResource.class);
GetVmIpAddressCommand getVmIpAddressCommand = mock(GetVmIpAddressCommand.class);
LibvirtGetVmIpAddressCommandWrapper commandWrapper = new LibvirtGetVmIpAddressCommandWrapper();
MockedStatic<Script> scriptMock = null;
try {
scriptMock = mockStatic(Script.class);
when(getVmIpAddressCommand.getVmName()).thenReturn("validVmName");
when(getVmIpAddressCommand.getVmNetworkCidr()).thenReturn("192.168.0.0/24");
when(getVmIpAddressCommand.isWindows()).thenReturn(false);
when(Script.executePipedCommands(anyList(), anyLong())).thenReturn(new Pair<>(0, ""));
Answer answer = commandWrapper.execute(getVmIpAddressCommand, libvirtComputingResource);
assertFalse(answer.getResult());
assertNull(answer.getDetails());
} finally {
if (scriptMock != null)
scriptMock.close();
}
}
@Test
public void testExecuteWithValidVmNameAndIpFromDhcpLeaseFile() {
LibvirtComputingResource libvirtComputingResource = mock(LibvirtComputingResource.class);
GetVmIpAddressCommand getVmIpAddressCommand = mock(GetVmIpAddressCommand.class);
LibvirtGetVmIpAddressCommandWrapper commandWrapper = new LibvirtGetVmIpAddressCommandWrapper();
MockedStatic<Script> scriptMock = null;
try {
scriptMock = mockStatic(Script.class);
when(getVmIpAddressCommand.getVmName()).thenReturn("validVmName");
when(getVmIpAddressCommand.getVmNetworkCidr()).thenReturn("192.168.0.0/24");
when(getVmIpAddressCommand.isWindows()).thenReturn(false);
when(Script.executePipedCommands(anyList(), anyLong())).thenReturn(new Pair<>(0, "192.168.0.10"));
Answer answer = commandWrapper.execute(getVmIpAddressCommand, libvirtComputingResource);
assertTrue(answer.getResult());
assertEquals("192.168.0.10", answer.getDetails());
} finally {
if (scriptMock != null)
scriptMock.close();
}
}
@Test
public void testExecuteWithValidVmNameAndIpFromWindowsRegistry() {
LibvirtComputingResource libvirtComputingResource = mock(LibvirtComputingResource.class);
GetVmIpAddressCommand getVmIpAddressCommand = mock(GetVmIpAddressCommand.class);
LibvirtGetVmIpAddressCommandWrapper commandWrapper = new LibvirtGetVmIpAddressCommandWrapper();
MockedStatic<Script> scriptMock = null;
try {
scriptMock = mockStatic(Script.class);
when(getVmIpAddressCommand.getVmName()).thenReturn("validVmName");
when(getVmIpAddressCommand.getVmNetworkCidr()).thenReturn("192.168.0.0/24");
when(getVmIpAddressCommand.isWindows()).thenReturn(true);
when(Script.executePipedCommands(anyList(), anyLong())).thenReturn(new Pair<>(0, "\"192.168.0.10\""));
Answer answer = commandWrapper.execute(getVmIpAddressCommand, libvirtComputingResource);
assertTrue(answer.getResult());
assertEquals("192.168.0.10", answer.getDetails());
} finally {
if (scriptMock != null)
scriptMock.close();
}
}
@Test
public void testIpFromDomIfCommandExecutionFailure() {
LibvirtComputingResource libvirtComputingResource = mock(LibvirtComputingResource.class);
GetVmIpAddressCommand getVmIpAddressCommand = mock(GetVmIpAddressCommand.class);
LibvirtGetVmIpAddressCommandWrapper commandWrapper = new LibvirtGetVmIpAddressCommandWrapper();
MockedStatic<Script> scriptMock = null;
try {
scriptMock = mockStatic(Script.class);
when(getVmIpAddressCommand.getVmName()).thenReturn("testVm");
when(getVmIpAddressCommand.getVmNetworkCidr()).thenReturn("192.168.1.0/24");
when(Script.executePipedCommands(anyList(), anyLong())).thenReturn(null);
Answer answer = commandWrapper.execute(getVmIpAddressCommand, libvirtComputingResource);
assertFalse(answer.getResult());
assertNull(answer.getDetails());
} finally {
if (scriptMock != null)
scriptMock.close();
}
}
@Test
public void testIpFromDhcpLeaseFileCommandExecutionFailure() {
LibvirtComputingResource libvirtComputingResource = mock(LibvirtComputingResource.class);
GetVmIpAddressCommand getVmIpAddressCommand = mock(GetVmIpAddressCommand.class);
LibvirtGetVmIpAddressCommandWrapper commandWrapper = new LibvirtGetVmIpAddressCommandWrapper();
MockedStatic<Script> scriptMock = null;
try {
scriptMock = mockStatic(Script.class);
when(getVmIpAddressCommand.getVmName()).thenReturn("testVm");
when(getVmIpAddressCommand.getVmNetworkCidr()).thenReturn("192.168.1.0/24");
when(Script.executePipedCommands(anyList(), anyLong())).thenReturn(null);
Answer answer = commandWrapper.execute(getVmIpAddressCommand, libvirtComputingResource);
assertFalse(answer.getResult());
assertNull(answer.getDetails());
} finally {
if (scriptMock != null)
scriptMock.close();
}
}
@Test
public void testIpFromWindowsRegistryCommandExecutionFailure() {
LibvirtComputingResource libvirtComputingResource = mock(LibvirtComputingResource.class);
GetVmIpAddressCommand getVmIpAddressCommand = mock(GetVmIpAddressCommand.class);
LibvirtGetVmIpAddressCommandWrapper commandWrapper = new LibvirtGetVmIpAddressCommandWrapper();
MockedStatic<Script> scriptMock = null;
try {
scriptMock = mockStatic(Script.class);
when(getVmIpAddressCommand.getVmName()).thenReturn("testVm");
when(getVmIpAddressCommand.getVmNetworkCidr()).thenReturn("192.168.1.0/24");
when(getVmIpAddressCommand.isWindows()).thenReturn(true);
when(Script.executePipedCommands(anyList(), anyLong())).thenReturn(null);
Answer answer = commandWrapper.execute(getVmIpAddressCommand, libvirtComputingResource);
assertFalse(answer.getResult());
assertNull(answer.getDetails());
} finally {
if (scriptMock != null)
scriptMock.close();
}
}
@Test
public void testInit() {
MockedStatic<Script> scriptMock = null;
try {
scriptMock = mockStatic(Script.class);
scriptMock.when(() -> Script.getExecutableAbsolutePath("virt-ls")).thenReturn("/usr/bin/virt-ls");
scriptMock.when(() -> Script.getExecutableAbsolutePath("virt-cat")).thenReturn("/usr/bin/virt-cat");
scriptMock.when(() -> Script.getExecutableAbsolutePath("virt-win-reg")).thenReturn("/usr/bin/virt-win-reg");
scriptMock.when(() -> Script.getExecutableAbsolutePath("tail")).thenReturn("/usr/bin/tail");
scriptMock.when(() -> Script.getExecutableAbsolutePath("grep")).thenReturn("/usr/bin/grep");
scriptMock.when(() -> Script.getExecutableAbsolutePath("awk")).thenReturn("/usr/bin/awk");
scriptMock.when(() -> Script.getExecutableAbsolutePath("sed")).thenReturn("/usr/bin/sed");
scriptMock.when(() -> Script.getExecutableAbsolutePath("virsh")).thenReturn("/usr/bin/virsh");
LibvirtGetVmIpAddressCommandWrapper.init();
assertEquals("/usr/bin/virt-ls", LibvirtGetVmIpAddressCommandWrapper.virt_ls_path);
assertEquals("/usr/bin/virt-cat", LibvirtGetVmIpAddressCommandWrapper.virt_cat_path);
assertEquals("/usr/bin/virt-win-reg", LibvirtGetVmIpAddressCommandWrapper.virt_win_reg_path);
assertEquals("/usr/bin/tail", LibvirtGetVmIpAddressCommandWrapper.tail_path);
assertEquals("/usr/bin/grep", LibvirtGetVmIpAddressCommandWrapper.grep_path);
assertEquals("/usr/bin/awk", LibvirtGetVmIpAddressCommandWrapper.awk_path);
assertEquals("/usr/bin/sed", LibvirtGetVmIpAddressCommandWrapper.sed_path);
assertEquals("/usr/bin/virsh", LibvirtGetVmIpAddressCommandWrapper.virsh_path);
} finally {
if (scriptMock != null)
scriptMock.close();
}
}
}