This subtest tries to attach scsi_debug disk with different cgroup
devices.list setting.

 * subtests the devices.{allow, deny, list} cgroup functionality
 * new function get_maj_min(dev) which returns (major, minor) numbers
   of dev
 * rm_drive: support for rm_device without drive (only remove the host
   file)
 * improved logging

Signed-off-by: Lukas Doktor <ldok...@redhat.com>
---
 client/tests/kvm/tests/cgroup.py |  234 +++++++++++++++++++++++++++++++++-----
 1 files changed, 203 insertions(+), 31 deletions(-)

diff --git a/client/tests/kvm/tests/cgroup.py b/client/tests/kvm/tests/cgroup.py
index 6c64532..c83f91a 100644
--- a/client/tests/kvm/tests/cgroup.py
+++ b/client/tests/kvm/tests/cgroup.py
@@ -50,7 +50,7 @@ def run_cgroup(test, params, env):
         return abs(float(actual-reference) / reference)
 
 
-    def get_dd_cmd(direction, dev='vd?', count=None, bs=None):
+    def get_dd_cmd(direction, dev=None, count=None, bs=None):
         """
         Generates dd_cmd string
         @param direction: {read,write,bi} dd direction
@@ -59,6 +59,11 @@ def run_cgroup(test, params, env):
         @param bs: bs parameter of dd
         @return: dd command string
         """
+        if dev is None:
+            if get_device_driver() == "virtio":
+                dev = 'vd?'
+            else:
+                dev = '[sh]d?'
         if direction == "read":
             params = "if=$FILE of=/dev/null iflag=direct"
         elif direction == "write":
@@ -82,6 +87,21 @@ def run_cgroup(test, params, env):
         return params.get('drive_format', 'virtio')
 
 
+    def get_maj_min(dev):
+        """
+        Returns the major and minor numbers of the dev device
+        @return: Tupple(major, minor) numbers of the dev device
+        """
+        try:
+            ret = utils.system_output("ls -l %s" % dev)
+            ret = re.match(r'[bc][rwx-]{9} \d+ \w+ \w+ (\d+), (\d+)',
+                           ret).groups()
+        except Exception, details:
+            raise error.TestFail("Couldn't get %s maj and min numbers: %s" %
+                                  (dev, details))
+        return ret
+
+
     def add_file_drive(vm, driver=get_device_driver(), host_file=None):
         """
         Hot-add a drive based on file to a vm
@@ -173,14 +193,17 @@ def run_cgroup(test, params, env):
         """
         err = False
         # TODO: Implement also via QMP
-        vm.monitor.cmd("pci_del %s" % device)
-        time.sleep(3)
-        qtree = vm.monitor.info('qtree', debug=False)
-        if qtree.count('addr %s.0' % device) != 0:
-            err = True
-            vm.destroy()
-
-        if isinstance(host_file, str):    # scsi device
+        if device:
+            vm.monitor.cmd("pci_del %s" % device)
+            time.sleep(3)
+            qtree = vm.monitor.info('qtree', debug=False)
+            if qtree.count('addr %s.0' % device) != 0:
+                err = True
+                vm.destroy()
+
+        if host_file is None:   # Do not remove
+            pass
+        elif isinstance(host_file, str):    # scsi device
             utils.system("echo -1> 
/sys/bus/pseudo/drivers/scsi_debug/add_host")
         else:     # file
             host_file.close()
@@ -334,7 +357,7 @@ def run_cgroup(test, params, env):
             _TestBlkioBandwidth.__init__(self, vms, modules)
             # Read from the last vd* in a loop until test removes the
             # /tmp/cgroup_lock file (and kills us)
-            self.dd_cmd = get_dd_cmd("read", bs="100K")
+            self.dd_cmd = get_dd_cmd("read", dev='vd?', bs="100K")
 
 
     class TestBlkioBandwidthWeigthWrite(_TestBlkioBandwidth):
@@ -350,7 +373,7 @@ def run_cgroup(test, params, env):
             # Write on the last vd* in a loop until test removes the
             # /tmp/cgroup_lock file (and kills us)
             _TestBlkioBandwidth.__init__(self, vms, modules)
-            self.dd_cmd = get_dd_cmd("write", bs="100K")
+            self.dd_cmd = get_dd_cmd("write", dev='vd?', bs="100K")
 
 
     class _TestBlkioThrottle:
@@ -376,10 +399,6 @@ def run_cgroup(test, params, env):
             self.devices = None # Temporary virt devices (PCI drive 1 per vm)
             self.dd_cmd = None  # DD command used to test the throughput
             self.speeds = None  # cgroup throughput
-            if get_device_driver() == "virtio":
-                self.dev = "vd?"
-            else:
-                self.dev = "[sh]d?"
 
         def cleanup(self):
             """
@@ -417,13 +436,8 @@ def run_cgroup(test, params, env):
                                                             driver="virtio")
             else:
                 (self.files, self.devices) = add_scsi_drive(self.vm)
-            try:
-                dev = utils.system_output("ls -l %s" % self.files).split()[4:6]
-                dev[0] = dev[0][:-1]    # Remove tailing ','
-            except:
-                time.sleep(5)
-                raise error.TestFail("Couldn't get %s maj and min numbers"
-                                     % self.files)
+            time.sleep(3)
+            dev = get_maj_min(self.files)
 
             cgroup = self.cgroup
             cgroup.initialize(self.modules)
@@ -548,7 +562,7 @@ def run_cgroup(test, params, env):
             @param modules: initialized cgroup module class
             """
             _TestBlkioThrottle.__init__(self, vms, modules)
-            self.dd_cmd = get_dd_cmd("read", dev=self.dev, count=1)
+            self.dd_cmd = get_dd_cmd("read", count=1)
             self.speeds = [1024]
 
 
@@ -561,7 +575,7 @@ def run_cgroup(test, params, env):
             @param modules: initialized cgroup module class
             """
             _TestBlkioThrottle.__init__(self, vms, modules)
-            self.dd_cmd = get_dd_cmd("write", dev=self.dev, count=1)
+            self.dd_cmd = get_dd_cmd("write", count=1)
             self.speeds = [1024]
 
 
@@ -577,7 +591,7 @@ def run_cgroup(test, params, env):
             @param modules: initialized cgroup module class
             """
             _TestBlkioThrottle.__init__(self, vms, modules)
-            self.dd_cmd = get_dd_cmd("read", dev=self.dev, count=1)
+            self.dd_cmd = get_dd_cmd("read", count=1)
             self.speeds = [0, 1024, 0, 2048, 0, 4096]
 
 
@@ -593,10 +607,166 @@ def run_cgroup(test, params, env):
             @param modules: initialized cgroup module class
             """
             _TestBlkioThrottle.__init__(self, vms, modules)
-            self.dd_cmd = get_dd_cmd("write", dev=self.dev, count=1)
+            self.dd_cmd = get_dd_cmd("write", count=1)
             self.speeds = [0, 1024, 0, 2048, 0, 4096]
 
 
+    class TestDevicesAccess:
+        """
+        It tries to attach scsi_debug disk with different cgroup devices.list
+        setting.
+         * self.permitions are defined as a list of dictionaries:
+           {'property': control property, 'value': permition value,
+            'check_value': check value (from devices.list property),
+            'read_results': excepced read results T/F,
+            'write_results': expected write results T/F}
+        """
+        def __init__(self, vms, modules):
+            """
+            Initialization
+            @param vms: list of vms
+            @param modules: initialized cgroup module class
+            """
+            self.vm = vms[0]      # Virt machines
+            self.modules = modules          # cgroup module handler
+            self.cgroup = Cgroup('devices', '')   # cgroup blkio handler
+            self.files = None   # Temporary files (files of virt disks)
+            self.devices = None # Temporary virt devices
+            self.permitions = None  # Test dictionary, see init for details
+
+
+        def cleanup(self):
+            """ Cleanup """
+            err = ""
+            try:
+                rm_drive(self.vm, self.files, self.devices)
+            except Exception, failure_detail:
+                err += "\nCan't remove PCI drive: %s" % failure_detail
+            try:
+                del(self.cgroup)
+            except Exception, failure_detail:
+                err += "\nCan't remove Cgroup: %s" % failure_detail
+
+            if err:
+                logging.error("Some cleanup operations failed: %s", err)
+                raise error.TestError("Some cleanup operations failed: %s"
+                                      % err)
+
+
+        def init(self):
+            """
+            Initialization
+             * creates a new scsi_debug device
+             * prepares one cgroup and assign vm to it
+            """
+            # Only create the host /dev/sd? device
+            (self.files, self.devices) = add_scsi_drive(self.vm)
+            rm_drive(self.vm, host_file=None, device=self.devices)
+            self.devices = None # We don't want to mess cleanup
+
+            time.sleep(3)
+            dev = "%s:%s" % get_maj_min(self.files)
+
+            self.cgroup.initialize(self.modules)
+            self.cgroup.mk_cgroup()
+            self.cgroup.set_cgroup(self.vm.get_shell_pid(),
+                                   self.cgroup.cgroups[0])
+            for pid in utils.get_children_pids(self.vm.get_shell_pid()):
+                self.cgroup.set_cgroup(int(pid), self.cgroup.cgroups[0])
+
+            # Test dictionary
+            # Beware of persistence of some setting to another round!!!
+            self.permitions = [
+                               {'property'      : 'deny',
+                                'value'         : 'a',
+                                'check_value'   : '',
+                                'result'        : False},
+                               {'property'      : 'allow',
+                                'value'         : 'b %s rm' % dev,
+                                'check_value'   : True,
+                                'result'        : False},
+                               {'property'      : 'allow',
+                                'value'         : 'b %s w' % dev,
+                                'check_value'   : 'b %s rwm' % dev,
+                                'result'        : True},
+                               {'property'      : 'deny',
+                                'value'         : 'b %s r' % dev,
+                                'check_value'   : 'b %s wm' % dev,
+                                'result'        : False},
+                               {'property'      : 'deny',
+                                'value'         : 'b %s wm' % dev,
+                                'check_value'   : '',
+                                'result'        : False},
+                               {'property'      : 'allow',
+                                'value'         : 'a',
+                                'check_value'   : 'a *:* rwm',
+                                'result'        : True},
+                              ]
+
+
+
+        def run(self):
+            """
+            Actual test:
+             * For each self.permitions sets the cgroup devices permition
+               and tries attach the disk. Checks the results with prescription.
+            """
+            def set_permitions(cgroup, permitions):
+                """
+                Wrapper for setting permitions to first cgroup
+                @param self.permitions: is defined as a list of dictionaries:
+                   {'property': control property, 'value': permition value,
+                    'check_value': check value (from devices.list property),
+                    'read_results': excepced read results T/F,
+                    'write_results': expected write results T/F}
+                """
+                cgroup.set_property('devices.'+permitions['property'],
+                                    permitions['value'],
+                                    cgroup.cgroups[0],
+                                    check=permitions['check_value'],
+                                    checkprop='devices.list')
+
+
+            session = self.vm.wait_for_login(timeout=30)
+
+            cgroup = self.cgroup
+            results = ""
+            for i in range(len(self.permitions)):
+                perm = self.permitions[i]
+                set_permitions(cgroup, perm)
+                logging.debug("Setting permitions: {%s: %s}, value: %s",
+                              perm['property'], perm['value'],
+                              cgroup.get_property('devices.list',
+                                                  cgroup.cgroups[0]))
+
+                try:
+                    (_, self.devices) = add_scsi_drive(self.vm,
+                                                        host_file=self.files)
+                except Exception, details:
+                    if perm['result']:
+                        logging.error("Perm: {%s: %s}: drive was not attached:"
+                                      " %s", perm['property'], perm['value'],
+                                      details)
+                        results += ("{%s: %s => NotAttached}, " %
+                                     (perm['property'], perm['value']))
+                else:
+                    if not perm['result']:
+                        logging.error("Perm: {%s: %s}: drive was attached",
+                                      perm['property'], perm['value'])
+                        results += ("{%s: %s => Attached}, " %
+                                     (perm['property'], perm['value']))
+                    rm_drive(self.vm, host_file=None, device=self.devices)
+                    self.devices = None
+
+            session.close()
+            if results:
+                raise error.TestFail("Some restrictions were broken: {%s}" %
+                                      results[:-2])
+
+            time.sleep(10)
+
+            return ("All restrictions enforced successfully.")
+
     # Setup
     # TODO: Add all new tests here
     tests = {"blkio_bandwidth_weigth_read"  : TestBlkioBandwidthWeigthRead,
@@ -605,9 +775,10 @@ def run_cgroup(test, params, env):
              "blkio_throttle_write"         : TestBlkioThrottleWrite,
              "blkio_throttle_multiple_read" : TestBlkioThrottleMultipleRead,
              "blkio_throttle_multiple_write" : TestBlkioThrottleMultipleWrite,
+             "devices_access"               : TestDevicesAccess,
             }
     modules = CgroupModules()
-    if (modules.init(['blkio']) <= 0):
+    if (modules.init(['blkio', 'devices']) <= 0):
         raise error.TestFail('Can\'t mount any cgroup modules')
     # Add all vms
     vms = []
@@ -674,14 +845,15 @@ def run_cgroup(test, params, env):
                     results += ("\n [F] %s: {%s} FAILED: %s" %
                                  (cg_test, err[:-2], out))
                 elif err:
-                    results += ("\n [E] %s: Test passed but {%s} FAILED: %s" %
+                    results += ("\n [W] %s: Test passed but {%s} FAILED: %s" %
                                  (cg_test, err[:-2], out))
                 else:
                     results += ("\n [P] %s: PASSED: %s" % (cg_test, out))
 
-    out = ("SUM: All tests finished (%d PASS / %d FAIL = %d TOTAL)%s" %
-           (results.count("PASSED"), results.count("FAILED"),
-            (results.count("PASSED")+results.count("FAILED")), results))
+    out = ("SUM: All tests finished (%d PASS / %d WARN / %d FAIL = %d 
TOTAL)%s"%
+           (results.count("\n [P]"), results.count("\n [W]"),
+            results.count("\n [F]"), (results.count("\n [P]") +
+            results.count("\n [F]") + results.count("\n [W]")), results))
     logging.info(out)
     if results.count("FAILED"):
         raise error.TestFail("Some subtests failed\n%s" % out)
-- 
1.7.6.2

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to