Repository: cloudstack
Updated Branches:
  refs/heads/master 8d1f1a69a -> c9e14c9f0


CLOUDSTACK-9395: Add Virtio RNG device to Instances when configured

By adding a Random Number Generator device to Instances we can prevent
entropy starvation inside guest.

The default source is /dev/random on the host, but this can be configured
to another source when present, for example a hardware RNG.

When enabled it will add the following to the Instance's XML definition:

  <rng model='virtio'>
    <rate period='1000' bytes='2048' />
    <backend model='random'>/dev/random</backend>
  </rng>

If the Instance has the proper support, which most modern distributions have,
it will have a /dev/hwrng device which it can use for gathering entropy.

More information: https://libvirt.org/formatdomain.html#elementsRng


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/0beb41b6
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/0beb41b6
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/0beb41b6

Branch: refs/heads/master
Commit: 0beb41b6e7d5177a64ac12d86d31c0766dc58d03
Parents: 6e7fdc4
Author: Wido den Hollander <w...@widodh.nl>
Authored: Mon May 30 16:56:19 2016 +0200
Committer: Wido den Hollander <w...@widodh.nl>
Committed: Tue Oct 4 12:44:55 2016 +0200

----------------------------------------------------------------------
 agent/conf/agent.properties                     |  19 ++++
 .../kvm/resource/LibvirtComputingResource.java  |  34 +++++++
 .../kvm/resource/LibvirtDomainXMLParser.java    |  27 +++++
 .../hypervisor/kvm/resource/LibvirtVMDef.java   | 101 +++++++++++++++++++
 .../resource/LibvirtDomainXMLParserTest.java    |  13 ++-
 .../kvm/resource/LibvirtVMDefTest.java          |  14 +++
 6 files changed, 207 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0beb41b6/agent/conf/agent.properties
----------------------------------------------------------------------
diff --git a/agent/conf/agent.properties b/agent/conf/agent.properties
index daad05f..1a3412e 100644
--- a/agent/conf/agent.properties
+++ b/agent/conf/agent.properties
@@ -152,3 +152,22 @@ hypervisor.type=kvm
 # kvmclock.disable=false
 # Some newer linux kernels are incapable of reliably migrating vms with 
kvmclock
 # This is a workaround for the bug, admin can set this to true per-host
+#
+# vm.rng.enable=false
+# This enabled the VirtIO Random Number Generator device for guests.
+#
+# vm.rng.model=random
+# The model of VirtIO Random Number Generator (RNG) to present to the Guest.
+# Currently only 'random' is supported.
+#
+# vm.rng.path=/dev/random
+# Local Random Number Device Generator to use for VirtIO RNG for Guests.
+# This is usually /dev/random, but per platform this might be different
+#
+# vm.rng.rate.bytes=2048
+# The amount of bytes the Guest may request/obtain from the RNG in the period
+# specified below.
+#
+# vm.rng.rate.period=1000
+# The number of milliseconds in which the guest is allowed to obtain the bytes
+# specified above.

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0beb41b6/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
----------------------------------------------------------------------
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 2b9aa71..53fb9c9 100644
--- 
a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
+++ 
b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
@@ -44,6 +44,7 @@ import java.util.regex.Pattern;
 import javax.ejb.Local;
 import javax.naming.ConfigurationException;
 
+import com.google.common.base.Strings;
 import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
 import org.apache.cloudstack.storage.to.VolumeObjectTO;
 import org.apache.cloudstack.utils.hypervisor.HypervisorUtils;
@@ -115,6 +116,8 @@ import 
com.cloud.hypervisor.kvm.resource.LibvirtVMDef.SerialDef;
 import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.TermPolicy;
 import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.VideoDef;
 import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.VirtioSerialDef;
+import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.RngDef;
+import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.RngDef.RngBackendModel;
 import com.cloud.hypervisor.kvm.resource.wrapper.LibvirtRequestWrapper;
 import com.cloud.hypervisor.kvm.resource.wrapper.LibvirtUtilitiesHelper;
 import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk;
@@ -244,6 +247,11 @@ public class LibvirtComputingResource extends 
ServerResourceBase implements Serv
     protected long _diskActivityCheckFileSizeMin = 10485760; // 10MB
     protected int _diskActivityCheckTimeoutSeconds = 120; // 120s
     protected long _diskActivityInactiveThresholdMilliseconds = 30000; // 30s
+    protected boolean _rngEnable = false;
+    protected RngBackendModel _rngBackendModel = RngBackendModel.RANDOM;
+    protected String _rngPath = "/dev/random";
+    protected int _rngRatePeriod = 1000;
+    protected int _rngRateBytes = 2048;
 
     private final Map <String, String> _pifs = new HashMap<String, String>();
     private final Map<String, VmStats> _vmStats = new 
ConcurrentHashMap<String, VmStats>();
@@ -803,6 +811,27 @@ public class LibvirtComputingResource extends 
ServerResourceBase implements Serv
             _noKvmClock = true;
         }
 
+        value = (String) params.get("vm.rng.enable");
+        if (Boolean.parseBoolean(value)) {
+            _rngEnable = true;
+
+            value = (String) params.get("vm.rng.model");
+            if (!Strings.isNullOrEmpty(value)) {
+                _rngBackendModel = 
RngBackendModel.valueOf(value.toUpperCase());
+            }
+
+            value = (String) params.get("vm.rng.path");
+            if (!Strings.isNullOrEmpty(value)) {
+                _rngPath = value;
+            }
+
+            value = (String) params.get("vm.rng.rate.bytes");
+            _rngRateBytes = NumbersUtil.parseInt(value, new 
Integer(_rngRateBytes));
+
+            value = (String) params.get("vm.rng.rate.period");
+            _rngRatePeriod = NumbersUtil.parseInt(value, new 
Integer(_rngRatePeriod));
+        }
+
         LibvirtConnection.initialize(_hypervisorURI);
         Connect conn = null;
         try {
@@ -1983,6 +2012,11 @@ public class LibvirtComputingResource extends 
ServerResourceBase implements Serv
             devices.addDevice(vserial);
         }
 
+        if (_rngEnable) {
+            final RngDef rngDevice = new RngDef(_rngPath, _rngBackendModel, 
_rngRateBytes, _rngRatePeriod);
+            devices.addDevice(rngDevice);
+        }
+
         final VideoDef videoCard = new VideoDef(_videoHw, _videoRam);
         devices.addDevice(videoCard);
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0beb41b6/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParser.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParser.java
 
b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParser.java
index 0b6b9d9..b77c1c8 100644
--- 
a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParser.java
+++ 
b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParser.java
@@ -25,6 +25,7 @@ import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
+import com.google.common.base.Strings;
 import org.apache.log4j.Logger;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -36,11 +37,14 @@ import org.xml.sax.SAXException;
 import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DiskDef;
 import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef;
 import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef.NicModel;
+import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.RngDef;
+import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.RngDef.RngBackendModel;
 
 public class LibvirtDomainXMLParser {
     private static final Logger s_logger = 
Logger.getLogger(LibvirtDomainXMLParser.class);
     private final List<InterfaceDef> interfaces = new 
ArrayList<InterfaceDef>();
     private final List<DiskDef> diskDefs = new ArrayList<DiskDef>();
+    private final List<RngDef> rngDefs = new ArrayList<RngDef>();
     private Integer vncPort;
     private String desc;
 
@@ -189,6 +193,25 @@ public class LibvirtDomainXMLParser {
                 }
             }
 
+            NodeList rngs = devices.getElementsByTagName("rng");
+            for (int i = 0; i < rngs.getLength(); i++) {
+                RngDef def = null;
+                Element rng = (Element)rngs.item(i);
+                String backendModel = getAttrValue("backend", "model", rng);
+                String path = getTagValue("backend", rng);
+                String bytes = getAttrValue("rate", "bytes", rng);
+                String period = getAttrValue("rate", "period", rng);
+
+                if (Strings.isNullOrEmpty(backendModel)) {
+                    def = new RngDef(path, Integer.parseInt(bytes), 
Integer.parseInt(period));
+                } else {
+                    def = new RngDef(path, 
RngBackendModel.valueOf(backendModel.toUpperCase()),
+                                     Integer.parseInt(bytes), 
Integer.parseInt(period));
+                }
+
+                rngDefs.add(def);
+            }
+
             return true;
         } catch (ParserConfigurationException e) {
             s_logger.debug(e.toString());
@@ -234,6 +257,10 @@ public class LibvirtDomainXMLParser {
         return diskDefs;
     }
 
+    public List<RngDef> getRngs() {
+        return rngDefs;
+    }
+
     public String getDescription() {
         return desc;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0beb41b6/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
----------------------------------------------------------------------
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 6ce7d6c..157d711 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
@@ -1366,6 +1366,107 @@ public class LibvirtVMDef {
         }
     }
 
+    public static class RngDef {
+        enum RngModel {
+            VIRTIO("virtio");
+            String model;
+
+            RngModel(String model) {
+                this.model = model;
+            }
+
+            @Override
+            public String toString() {
+                return model;
+            }
+        }
+
+        enum RngBackendModel {
+            RANDOM("random"), EGD("egd");
+            String model;
+
+            RngBackendModel(String model) {
+                this.model = model;
+            }
+
+            @Override
+            public String toString() {
+                return model;
+            }
+        }
+
+        private String path = "/dev/random";
+        private RngModel rngModel = RngModel.VIRTIO;
+        private RngBackendModel rngBackendModel = RngBackendModel.RANDOM;
+        private int rngRateBytes = 2048;
+        private int rngRatePeriod = 1000;
+
+        public RngDef(String path) {
+            this.path = path;
+        }
+
+        public RngDef(String path, int rngRateBytes, int rngRatePeriod) {
+            this.path = path;
+            this.rngRateBytes = rngRateBytes;
+            this.rngRatePeriod = rngRatePeriod;
+        }
+
+        public RngDef(RngModel rngModel) {
+            this.rngModel = rngModel;
+        }
+
+        public RngDef(RngBackendModel rngBackendModel) {
+            this.rngBackendModel = rngBackendModel;
+        }
+
+        public RngDef(String path, RngBackendModel rngBackendModel) {
+            this.path = path;
+            this.rngBackendModel = rngBackendModel;
+        }
+
+        public RngDef(String path, RngBackendModel rngBackendModel, int 
rngRateBytes, int rngRatePeriod) {
+            this.path = path;
+            this.rngBackendModel = rngBackendModel;
+            this.rngRateBytes = rngRateBytes;
+            this.rngRatePeriod = rngRatePeriod;
+        }
+
+        public RngDef(String path, RngModel rngModel) {
+            this.path = path;
+            this.rngModel = rngModel;
+        }
+
+        public String getPath() {
+           return path;
+        }
+
+        public RngBackendModel getRngBackendModel() {
+            return rngBackendModel;
+        }
+
+        public RngModel getRngModel() {
+            return rngModel;
+        }
+
+        public int getRngRateBytes() {
+            return rngRateBytes;
+        }
+
+        public int getRngRatePeriod() {
+            return rngRatePeriod;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder rngBuilder = new StringBuilder();
+            rngBuilder.append("<rng model='" + rngModel + "'>\n");
+            rngBuilder.append("<rate period='" + rngRatePeriod + "' bytes='" + 
rngRateBytes + "' />\n");
+            rngBuilder.append("<backend model='" + rngBackendModel + "'>" + 
path + "</backend>");
+            rngBuilder.append("</rng>\n");
+            return rngBuilder.toString();
+        }
+    }
+
     public void setHvsType(String hvs) {
         _hvsType = hvs;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0beb41b6/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParserTest.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParserTest.java
 
b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParserTest.java
index eb28d8b..a71232c 100644
--- 
a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParserTest.java
+++ 
b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtDomainXMLParserTest.java
@@ -23,6 +23,7 @@ import junit.framework.TestCase;
 import java.util.List;
 import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DiskDef;
 import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef;
+import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.RngDef;
 
 public class LibvirtDomainXMLParserTest extends TestCase {
 
@@ -164,6 +165,10 @@ public class LibvirtDomainXMLParserTest extends TestCase {
                      "<alias name='balloon0'/>" +
                      "<address type='pci' domain='0x0000' bus='0x00' 
slot='0x09' function='0x0'/>" +
                      "</memballoon>" +
+                     "<rng model='virtio'>" +
+                     "<rate period='5000' bytes='4096' />" +
+                     "<backend model='random'>/dev/random</backend>" +
+                     "</rng>" +
                      "</devices>" +
                      "<seclabel type='none'/>" +
                      "</domain>";
@@ -190,5 +195,11 @@ public class LibvirtDomainXMLParserTest extends TestCase {
             assertEquals(ifModel, ifs.get(i).getModel());
             assertEquals(ifType, ifs.get(i).getNetType());
         }
+
+        List<RngDef> rngs = parser.getRngs();
+        assertEquals("/dev/random", rngs.get(0).getPath());
+        assertEquals(RngDef.RngBackendModel.RANDOM, 
rngs.get(0).getRngBackendModel());
+        assertEquals(4096, rngs.get(0).getRngRateBytes());
+        assertEquals(5000, rngs.get(0).getRngRatePeriod());
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0beb41b6/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtVMDefTest.java
----------------------------------------------------------------------
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 a926129..f0d1b5b 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
@@ -118,4 +118,18 @@ public class LibvirtVMDefTest extends TestCase {
         assertTrue((hostOsVersion.first() == 6 && hostOsVersion.second() >= 5) 
|| (hostOsVersion.first() >= 7));
     }
 
+    public void testChannelDef() {
+        LibvirtVMDef.RngDef.RngBackendModel backendModel = 
LibvirtVMDef.RngDef.RngBackendModel.RANDOM;
+        String path = "/dev/random";
+        int period = 2000;
+        int bytes = 2048;
+
+        LibvirtVMDef.RngDef def = new LibvirtVMDef.RngDef(path, backendModel, 
bytes, period);
+        assertEquals(def.getPath(), path);
+        assertEquals(def.getRngBackendModel(), backendModel);
+        assertEquals(def.getRngModel(), LibvirtVMDef.RngDef.RngModel.VIRTIO);
+        assertEquals(def.getRngRateBytes(), bytes);
+        assertEquals(def.getRngRatePeriod(), period);
+    }
+
 }

Reply via email to