mirror of https://github.com/apache/cloudstack.git
el8 fixes backport (#155)
* Extract the IO_URING configuration into the agent.properties (#6253) When using advanced virtualization the IO Driver is not supported. The admin will decide if want to enable/disable this configuration from agent.properties file. The default value is true * kvm: truncate vnc password to 8 chars (#6244) This PR truncates the vnc password of kvm vms to 8 chars to support latest versions of libvirt. * merge fix Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com> * [KVM] Enable IOURING only when it is available on the host (#6399) * [KVM] Disable IOURING by default on agents * Refactor * Remove agent property for iouring * Restore property * Refactor suse check and enable on ubuntu by default * Refactor irrespective of guest OS * Improvement * Logs and new path * Refactor condition to enable iouring * Improve condition * Refactor property check * Improvement * Doc comment * Extend comment * Move method * Add log * [KVM] Fix VM migration error due to VNC password on libvirt limiting versions (#6404) * [KVM] Fix VM migration error due to VNC password on libvirt limiting versions * Fix passwd value * Simplify implementation Co-authored-by: slavkap <51903378+slavkap@users.noreply.github.com> Co-authored-by: Wei Zhou <weizhou@apache.org> Co-authored-by: Nicolas Vazquez <nicovazquez90@gmail.com>
This commit is contained in:
parent
c39cf4cbde
commit
de1414138b
|
|
@ -288,3 +288,6 @@ iscsi.session.cleanup.enabled=false
|
|||
|
||||
# Manually set the host CPU MHz, in cases where CPU scaling support detected value is wrong
|
||||
# host.cpu.manual.speed.mhz=0
|
||||
|
||||
# Enable/disable IO driver for Qemu (in case it is not set CloudStack can also detect if its supported by qemu)
|
||||
# enable.io.uring=true
|
||||
|
|
|
|||
|
|
@ -313,6 +313,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
|
||||
public final static String HOST_CACHE_PATH_PARAMETER = "host.cache.location";
|
||||
public final static String CONFIG_DIR = "config";
|
||||
private boolean enableIoUring;
|
||||
private final static String ENABLE_IO_URING_PROPERTY = "enable.io.uring";
|
||||
|
||||
public static final String BASH_SCRIPT_PATH = "/bin/bash";
|
||||
|
||||
|
|
@ -1138,6 +1140,12 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
s_logger.trace("Ignoring libvirt error.", e);
|
||||
}
|
||||
|
||||
// Enable/disable IO driver for Qemu (in case it is not set CloudStack can also detect if its supported by qemu)
|
||||
// Do not remove - switching it to AgentProperties.Property may require accepting null values for the properties default value
|
||||
String enableIoUringConfig = (String) params.get(ENABLE_IO_URING_PROPERTY);
|
||||
enableIoUring = isIoUringEnabled(enableIoUringConfig);
|
||||
s_logger.info("IO uring driver for Qemu: " + (enableIoUring ? "enabled" : "disabled"));
|
||||
|
||||
final String cpuArchOverride = (String)params.get("guest.cpu.arch");
|
||||
if (!Strings.isNullOrEmpty(cpuArchOverride)) {
|
||||
_guestCpuArch = cpuArchOverride;
|
||||
|
|
@ -2972,6 +2980,33 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
return storagePool.getPhysicalDisk(data.getPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if IO_URING is supported by qemu
|
||||
*/
|
||||
protected boolean isIoUringSupportedByQemu() {
|
||||
s_logger.debug("Checking if iouring is supported");
|
||||
String command = getIoUringCheckCommand();
|
||||
if (org.apache.commons.lang3.StringUtils.isBlank(command)) {
|
||||
s_logger.debug("Could not check iouring support, disabling it");
|
||||
return false;
|
||||
}
|
||||
int exitValue = executeBashScriptAndRetrieveExitValue(command);
|
||||
return exitValue == 0;
|
||||
}
|
||||
|
||||
protected String getIoUringCheckCommand() {
|
||||
String[] qemuPaths = { "/usr/bin/qemu-system-x86_64", "/usr/libexec/qemu-kvm", "/usr/bin/qemu-kvm" };
|
||||
for (String qemuPath : qemuPaths) {
|
||||
File file = new File(qemuPath);
|
||||
if (file.exists()) {
|
||||
String cmd = String.format("ldd %s | grep -Eqe '[[:space:]]liburing\\.so'", qemuPath);
|
||||
s_logger.debug("Using the check command: " + cmd);
|
||||
return cmd;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Disk IO Driver, if supported by the Libvirt/Qemu version.
|
||||
* IO Driver works for:
|
||||
|
|
@ -2979,11 +3014,34 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
* (ii) Libvirt >= 6.3.0
|
||||
*/
|
||||
protected void setDiskIoDriver(DiskDef disk) {
|
||||
if (getHypervisorLibvirtVersion() >= HYPERVISOR_LIBVIRT_VERSION_SUPPORTS_IO_URING && getHypervisorQemuVersion() >= HYPERVISOR_QEMU_VERSION_SUPPORTS_IO_URING) {
|
||||
if (enableIoUring) {
|
||||
disk.setIoDriver(DiskDef.IoDriver.IOURING);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* IO_URING supported if the property 'enable.io.uring' is set to true OR it is supported by qemu
|
||||
*/
|
||||
private boolean isIoUringEnabled(String enableIoUringConfig) {
|
||||
boolean meetRequirements = getHypervisorLibvirtVersion() >= HYPERVISOR_LIBVIRT_VERSION_SUPPORTS_IO_URING
|
||||
&& getHypervisorQemuVersion() >= HYPERVISOR_QEMU_VERSION_SUPPORTS_IO_URING;
|
||||
if (!meetRequirements) {
|
||||
return false;
|
||||
}
|
||||
return enableIoUringConfig != null ?
|
||||
Boolean.parseBoolean(enableIoUringConfig):
|
||||
(isBaseOsUbuntu() || isIoUringSupportedByQemu());
|
||||
}
|
||||
|
||||
private boolean isBaseOsUbuntu() {
|
||||
Map<String, String> versionString = getVersionStrings();
|
||||
String hostKey = "Host.OS";
|
||||
if (MapUtils.isEmpty(versionString) || !versionString.containsKey(hostKey) || versionString.get(hostKey) == null) {
|
||||
return false;
|
||||
}
|
||||
return versionString.get(hostKey).equalsIgnoreCase("ubuntu");
|
||||
}
|
||||
|
||||
private KVMPhysicalDisk getPhysicalDiskFromNfsStore(String dataStoreUrl, DataTO data) {
|
||||
final String volPath = dataStoreUrl + File.separator + data.getPath();
|
||||
final int index = volPath.lastIndexOf("/");
|
||||
|
|
@ -3847,10 +3905,20 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
}
|
||||
|
||||
private String executeBashScript(final String script) {
|
||||
return createScript(script).execute();
|
||||
}
|
||||
|
||||
private Script createScript(final String script) {
|
||||
final Script command = new Script("/bin/bash", _timeout, s_logger);
|
||||
command.add("-c");
|
||||
command.add(script);
|
||||
return command.execute();
|
||||
return command;
|
||||
}
|
||||
|
||||
private int executeBashScriptAndRetrieveExitValue(final String script) {
|
||||
Script command = createScript(script);
|
||||
command.execute();
|
||||
return command.getExitValue();
|
||||
}
|
||||
|
||||
public List<VmNetworkStatsEntry> getVmNetworkStat(Connect conn, String vmName) throws LibvirtException {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
public class LibvirtVMDef {
|
||||
|
|
@ -1764,7 +1764,7 @@ public class LibvirtVMDef {
|
|||
graphicBuilder.append(" listen=''");
|
||||
}
|
||||
if (_passwd != null) {
|
||||
graphicBuilder.append(" passwd='" + _passwd + "'");
|
||||
graphicBuilder.append(" passwd='" + StringUtils.truncate(_passwd, 8) + "'");
|
||||
} else if (_keyMap != null) {
|
||||
graphicBuilder.append(" _keymap='" + _keyMap + "'");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,7 +149,11 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCo
|
|||
|
||||
final String target = command.getDestinationIp();
|
||||
xmlDesc = dm.getXMLDesc(xmlFlag);
|
||||
xmlDesc = replaceIpForVNCInDescFile(xmlDesc, target);
|
||||
|
||||
// Limit the VNC password in case the length is greater than 8 characters
|
||||
// Since libvirt version 8 VNC passwords are limited to 8 characters
|
||||
String vncPassword = org.apache.commons.lang3.StringUtils.truncate(to.getVncPassword(), 8);
|
||||
xmlDesc = replaceIpForVNCInDescFileAndNormalizePassword(xmlDesc, target, vncPassword);
|
||||
|
||||
String oldIsoVolumePath = getOldVolumePath(disks, vmName);
|
||||
String newIsoVolumePath = getNewVolumePathIfDatastoreHasChanged(libvirtComputingResource, conn, to);
|
||||
|
|
@ -450,9 +454,10 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCo
|
|||
* </graphics>
|
||||
* @param xmlDesc the qemu xml description
|
||||
* @param target the ip address to migrate to
|
||||
* @param vncPassword if set, the VNC password truncated to 8 characters
|
||||
* @return the new xmlDesc
|
||||
*/
|
||||
String replaceIpForVNCInDescFile(String xmlDesc, final String target) {
|
||||
String replaceIpForVNCInDescFileAndNormalizePassword(String xmlDesc, final String target, String vncPassword) {
|
||||
final int begin = xmlDesc.indexOf(GRAPHICS_ELEM_START);
|
||||
if (begin >= 0) {
|
||||
final int end = xmlDesc.lastIndexOf(GRAPHICS_ELEM_END) + GRAPHICS_ELEM_END.length();
|
||||
|
|
@ -460,6 +465,9 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCo
|
|||
String graphElem = xmlDesc.substring(begin, end);
|
||||
graphElem = graphElem.replaceAll("listen='[a-zA-Z0-9\\.]*'", "listen='" + target + "'");
|
||||
graphElem = graphElem.replaceAll("address='[a-zA-Z0-9\\.]*'", "address='" + target + "'");
|
||||
if (org.apache.commons.lang3.StringUtils.isNotBlank(vncPassword)) {
|
||||
graphElem = graphElem.replaceAll("passwd='([^\\s]+)'", "passwd='" + vncPassword + "'");
|
||||
}
|
||||
xmlDesc = xmlDesc.replaceAll(GRAPHICS_ELEM_START + CONTENTS_WILDCARD + GRAPHICS_ELEM_END, graphElem);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ import org.apache.cloudstack.utils.linux.CPUStat;
|
|||
import org.apache.cloudstack.utils.linux.MemStat;
|
||||
import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat;
|
||||
import org.apache.commons.lang.SystemUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
|
|
@ -773,7 +774,7 @@ public class LibvirtComputingResourceTest {
|
|||
assertXpath(domainDoc, prefix + "/graphics/@type", "vnc");
|
||||
assertXpath(domainDoc, prefix + "/graphics/@listen", to.getVncAddr());
|
||||
assertXpath(domainDoc, prefix + "/graphics/@autoport", "yes");
|
||||
assertXpath(domainDoc, prefix + "/graphics/@passwd", to.getVncPassword());
|
||||
assertXpath(domainDoc, prefix + "/graphics/@passwd", StringUtils.truncate(to.getVncPassword(), 8));
|
||||
}
|
||||
|
||||
private void verifySerialDevices(Document domainDoc, String prefix) {
|
||||
|
|
|
|||
|
|
@ -571,16 +571,16 @@ public class LibvirtMigrateCommandWrapperTest {
|
|||
@Test
|
||||
public void testReplaceIpForVNCInDescFile() {
|
||||
final String targetIp = "192.168.22.21";
|
||||
final String result = libvirtMigrateCmdWrapper.replaceIpForVNCInDescFile(fullfile, targetIp);
|
||||
final String result = libvirtMigrateCmdWrapper.replaceIpForVNCInDescFileAndNormalizePassword(fullfile, targetIp, null);
|
||||
assertTrue("transformation does not live up to expectation:\n" + result, targetfile.equals(result));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceIpForVNCInDesc() {
|
||||
public void testReplaceIpAndPasswordForVNCInDesc() {
|
||||
final String xmlDesc =
|
||||
"<domain type='kvm' id='3'>" +
|
||||
" <devices>" +
|
||||
" <graphics type='vnc' port='5900' autoport='yes' listen='10.10.10.1'>" +
|
||||
" <graphics type='vnc' port='5900' autoport='yes' listen='10.10.10.1' passwd='123456789012345'>" +
|
||||
" <listen type='address' address='10.10.10.1'/>" +
|
||||
" </graphics>" +
|
||||
" </devices>" +
|
||||
|
|
@ -588,22 +588,23 @@ public class LibvirtMigrateCommandWrapperTest {
|
|||
final String expectedXmlDesc =
|
||||
"<domain type='kvm' id='3'>" +
|
||||
" <devices>" +
|
||||
" <graphics type='vnc' port='5900' autoport='yes' listen='10.10.10.10'>" +
|
||||
" <graphics type='vnc' port='5900' autoport='yes' listen='10.10.10.10' passwd='12345678'>" +
|
||||
" <listen type='address' address='10.10.10.10'/>" +
|
||||
" </graphics>" +
|
||||
" </devices>" +
|
||||
"</domain>";
|
||||
final String targetIp = "10.10.10.10";
|
||||
final String result = libvirtMigrateCmdWrapper.replaceIpForVNCInDescFile(xmlDesc, targetIp);
|
||||
final String password = "12345678";
|
||||
final String result = libvirtMigrateCmdWrapper.replaceIpForVNCInDescFileAndNormalizePassword(xmlDesc, targetIp, password);
|
||||
assertTrue("transformation does not live up to expectation:\n" + result, expectedXmlDesc.equals(result));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceFqdnForVNCInDesc() {
|
||||
public void testReplaceFqdnAndPasswordForVNCInDesc() {
|
||||
final String xmlDesc =
|
||||
"<domain type='kvm' id='3'>" +
|
||||
" <devices>" +
|
||||
" <graphics type='vnc' port='5900' autoport='yes' listen='localhost.local'>" +
|
||||
" <graphics type='vnc' port='5900' autoport='yes' listen='localhost.local' passwd='123456789012345'>" +
|
||||
" <listen type='address' address='localhost.local'/>" +
|
||||
" </graphics>" +
|
||||
" </devices>" +
|
||||
|
|
@ -611,13 +612,14 @@ public class LibvirtMigrateCommandWrapperTest {
|
|||
final String expectedXmlDesc =
|
||||
"<domain type='kvm' id='3'>" +
|
||||
" <devices>" +
|
||||
" <graphics type='vnc' port='5900' autoport='yes' listen='localhost.localdomain'>" +
|
||||
" <graphics type='vnc' port='5900' autoport='yes' listen='localhost.localdomain' passwd='12345678'>" +
|
||||
" <listen type='address' address='localhost.localdomain'/>" +
|
||||
" </graphics>" +
|
||||
" </devices>" +
|
||||
"</domain>";
|
||||
final String targetIp = "localhost.localdomain";
|
||||
final String result = libvirtMigrateCmdWrapper.replaceIpForVNCInDescFile(xmlDesc, targetIp);
|
||||
final String password = "12345678";
|
||||
final String result = libvirtMigrateCmdWrapper.replaceIpForVNCInDescFileAndNormalizePassword(xmlDesc, targetIp, password);
|
||||
assertTrue("transformation does not live up to expectation:\n" + result, expectedXmlDesc.equals(result));
|
||||
}
|
||||
|
||||
|
|
@ -789,5 +791,4 @@ public class LibvirtMigrateCommandWrapperTest {
|
|||
Assert.assertTrue(replaced.contains("csdpdk-7"));
|
||||
Assert.assertFalse(replaced.contains("csdpdk-1"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue