diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 9a4ae16cadb..55b49c2ca31 100755 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -454,6 +454,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv protected boolean _noKvmClock; protected String _videoHw; protected int _videoRam; + protected Pair hostOsVersion; private final Map _pifs = new HashMap(); private final Map _vmStats = new ConcurrentHashMap(); @@ -965,6 +966,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv String[] kernelVersions = unameKernelVersion.split("[\\.\\-]"); _kernelVersion = Integer.parseInt(kernelVersions[0]) * 1000 * 1000 + Integer.parseInt(kernelVersions[1]) * 1000 + Integer.parseInt(kernelVersions[2]); + getOsVersion(); return true; } @@ -3606,6 +3608,24 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return uuid; } + private void getOsVersion() { + String version = Script.runSimpleBashScript("cat /etc/redhat-release | awk '{print $7}'"); + if (version != null) { + String[] versions = version.split("."); + if (versions.length == 2) { + String major = versions[0]; + String minor = versions[1]; + try { + Integer m = Integer.parseInt(major); + Integer min = Integer.parseInt(minor); + hostOsVersion = new Pair<>(m, min); + } catch(NumberFormatException e) { + + } + } + } + } + protected LibvirtVMDef createVMFromSpec(VirtualMachineTO vmTO) { LibvirtVMDef vm = new LibvirtVMDef(); vm.setDomainName(vmTO.getName()); @@ -3684,6 +3704,12 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv features.addFeatures("pae"); features.addFeatures("apic"); features.addFeatures("acpi"); + //for rhel 6.5 and above, hyperv enlightment feature is added + if (vmTO.getOs().contains("Windows Server 2008") && hostOsVersion != null && ((hostOsVersion.first() == 6 && hostOsVersion.second() >= 5) || (hostOsVersion.first() >= 7))) { + LibvirtVMDef.HyperVEnlightenmentFeatureDef hyv = new LibvirtVMDef.HyperVEnlightenmentFeatureDef(); + hyv.setRelaxed(true); + features.addHyperVFeature(hyv); + } vm.addComp(features); TermPolicy term = new TermPolicy(); diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java index bc952042215..2ce24421a97 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java @@ -173,13 +173,42 @@ public class LibvirtVMDef { } } + public static class HyperVEnlightenmentFeatureDef { + private final Map features = new HashMap(); + public void setRelaxed(boolean on) { + String state = on ? "On":"Off"; + features.put("relaxed", state); + } + @Override + public String toString() { + if (features.isEmpty()) { + return ""; + } + StringBuilder feaBuilder = new StringBuilder(); + feaBuilder.append("\n"); + for (Map.Entry e : features.entrySet()) { + feaBuilder.append("<"); + feaBuilder.append(e.getKey()); + feaBuilder.append(" state='" + e.getValue() + "'"); + feaBuilder.append("/>\n"); + } + feaBuilder.append("\n"); + return feaBuilder.toString(); + } + } + public static class FeaturesDef { private final List _features = new ArrayList(); + private HyperVEnlightenmentFeatureDef hyperVEnlightenmentFeatureDef = null; public void addFeatures(String feature) { _features.add(feature); } + public void addHyperVFeature(HyperVEnlightenmentFeatureDef hyperVEnlightenmentFeatureDef) { + this.hyperVEnlightenmentFeatureDef = hyperVEnlightenmentFeatureDef; + } + @Override public String toString() { StringBuilder feaBuilder = new StringBuilder(); @@ -187,6 +216,12 @@ public class LibvirtVMDef { for (String feature : _features) { feaBuilder.append("<" + feature + "/>\n"); } + if (hyperVEnlightenmentFeatureDef != null) { + String hpervF = hyperVEnlightenmentFeatureDef.toString(); + if (hpervF != "") { + feaBuilder.append(hpervF); + } + } feaBuilder.append("\n"); return feaBuilder.toString(); } diff --git a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java index aa7570c3638..ddbe256aeb6 100644 --- a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java +++ b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java @@ -21,6 +21,7 @@ package com.cloud.hypervisor.kvm.resource; import junit.framework.TestCase; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DiskDef; +import com.cloud.utils.Pair; public class LibvirtVMDefTest extends TestCase { @@ -90,4 +91,25 @@ public class LibvirtVMDefTest extends TestCase { assertEquals(xmlDef, expectedXml); } + public void testHypervEnlightDef() { + LibvirtVMDef.FeaturesDef featuresDef = new LibvirtVMDef.FeaturesDef(); + LibvirtVMDef.HyperVEnlightenmentFeatureDef hyperVEnlightenmentFeatureDef = new LibvirtVMDef.HyperVEnlightenmentFeatureDef(); + hyperVEnlightenmentFeatureDef.setRelaxed(true); + featuresDef.addHyperVFeature(hyperVEnlightenmentFeatureDef); + String defs = featuresDef.toString(); + assertTrue(defs.contains("relaxed")); + + featuresDef = new LibvirtVMDef.FeaturesDef(); + featuresDef.addFeatures("pae"); + defs = featuresDef.toString(); + assertFalse(defs.contains("relaxed")); + + assertTrue("Windows Server 2008 R2".contains("Windows Server 2008")); + + Pair hostOsVersion = new Pair(6,5); + assertTrue((hostOsVersion.first() == 6 && hostOsVersion.second() >= 5) || (hostOsVersion.first() >= 7)); + hostOsVersion = new Pair(7,1); + assertTrue((hostOsVersion.first() == 6 && hostOsVersion.second() >= 5) || (hostOsVersion.first() >= 7)); + } + }