diff --git a/qa/ganeti-qa.py b/qa/ganeti-qa.py
index 4c2a2fcffe1b9dfba8dc443606c61171ce035a7f..d66d8c3223abdf33bd1971de0d2afb61036ccbfb 100755
--- a/qa/ganeti-qa.py
+++ b/qa/ganeti-qa.py
@@ -160,6 +160,9 @@ def RunCommonInstanceTests(instance):
   if qa_config.TestEnabled('node-volumes'):
     RunTest(qa_node.TestNodeVolumes)
 
+  if qa_config.TestEnabled("node-storage"):
+    RunTest(qa_node.TestNodeStorage)
+
   if qa_rapi.Enabled():
     RunTest(qa_rapi.TestInstance, instance)
 
diff --git a/qa/qa-sample.json b/qa/qa-sample.json
index d2a18be2c7cd3e527200e9fe533e59eb3a1fa343..f051ec9b21611ffc4765c3230163c1330b785e48 100644
--- a/qa/qa-sample.json
+++ b/qa/qa-sample.json
@@ -51,6 +51,7 @@
     "node-info": true,
     "node-volumes": true,
     "node-readd": true,
+    "node-storage": true,
 
     "# This test needs at least three nodes": null,
     "node-evacuate": false,
@@ -73,16 +74,16 @@
     "instance-automatic-restart": false,
     "instance-consecutive-failures": false,
 
-    "# This test might fail with certain hypervisor types, depending on whether": null,
-    "# they support the `gnt-instance console' command.": null,
+    "# This test might fail with certain hypervisor types, depending": null,
+    "# on whether they support the `gnt-instance console' command.": null,
     "instance-console": false,
 
     "# Disabled by default because it takes rather long": null,
     "instance-replace-disks": false,
 
-    "# Make sure not to include the disk(s) required for Dom0 to be included in": null,
-    "# the volume group used for instances. Otherwise the whole system may stop": null,
-    "# working until restarted.": null,
+    "# Make sure not to include the disk(s) required for Dom0 to be": null,
+    "# included in the volume group used for instances. Otherwise": null,
+    "# whole system may stop working until restarted.": null,
     "instance-disk-failure": false
   },
 
diff --git a/qa/qa_node.py b/qa/qa_node.py
index 15777cb277b533da1814961ed0b354800ad57a9d..8d17a4cb3013aaf0d47c332bd8f710eb2866e05b 100644
--- a/qa/qa_node.py
+++ b/qa/qa_node.py
@@ -20,12 +20,13 @@
 
 
 from ganeti import utils
+from ganeti import constants
 
 import qa_config
 import qa_error
 import qa_utils
 
-from qa_utils import AssertEqual, StartSSH
+from qa_utils import AssertEqual, AssertNotEqual, StartSSH
 
 
 def _NodeAdd(node, readd=False):
@@ -96,6 +97,72 @@ def TestNodeVolumes():
                        utils.ShellQuoteArgs(cmd)).wait(), 0)
 
 
+def TestNodeStorage():
+  """gnt-node storage"""
+  master = qa_config.GetMasterNode()
+
+  for storage_type in constants.VALID_STORAGE_TYPES:
+    # Test simple list
+    cmd = ["gnt-node", "list-storage", "--storage-type", storage_type]
+    AssertEqual(StartSSH(master["primary"],
+                         utils.ShellQuoteArgs(cmd)).wait(), 0)
+
+    # Test all storage fields
+    cmd = ["gnt-node", "list-storage", "--storage-type", storage_type,
+           "--output=%s" % ",".join(list(constants.VALID_STORAGE_FIELDS) +
+                                    [constants.SF_NODE, constants.SF_TYPE])]
+    AssertEqual(StartSSH(master["primary"],
+                         utils.ShellQuoteArgs(cmd)).wait(), 0)
+
+    # Get list of valid storage devices
+    cmd = ["gnt-node", "list-storage", "--storage-type", storage_type,
+           "--output=node,name,allocatable", "--separator=|",
+           "--no-headers"]
+    output = qa_utils.GetCommandOutput(master["primary"],
+                                       utils.ShellQuoteArgs(cmd))
+
+    # Test with up to two devices
+    testdevcount = 2
+
+    for line in output.splitlines()[:testdevcount]:
+      (node_name, st_name, st_allocatable) = line.split("|")
+
+      # Dummy modification without any changes
+      cmd = ["gnt-node", "modify-storage", node_name, storage_type, st_name]
+      AssertEqual(StartSSH(master["primary"],
+                           utils.ShellQuoteArgs(cmd)).wait(), 0)
+
+      # Make sure we end up with the same value as before
+      if st_allocatable.lower() == "y":
+        test_allocatable = ["no", "yes"]
+      else:
+        test_allocatable = ["yes", "no"]
+
+      if (constants.SF_ALLOCATABLE in
+          constants.MODIFIABLE_STORAGE_FIELDS.get(storage_type, [])):
+        assert_fn = AssertEqual
+      else:
+        assert_fn = AssertNotEqual
+
+      for i in test_allocatable:
+        cmd = ["gnt-node", "modify-storage", "--allocatable", i,
+               node_name, storage_type, st_name]
+        assert_fn(StartSSH(master["primary"],
+                  utils.ShellQuoteArgs(cmd)).wait(), 0)
+
+      # Test repair functionality
+      cmd = ["gnt-node", "repair-storage", node_name, storage_type, st_name]
+
+      if (constants.SO_FIX_CONSISTENCY in
+          constants.VALID_STORAGE_OPERATIONS.get(storage_type, [])):
+        assert_fn = AssertEqual
+      else:
+        assert_fn = AssertNotEqual
+
+      assert_fn(StartSSH(master["primary"],
+                         utils.ShellQuoteArgs(cmd)).wait(), 0)
+
+
 def TestNodeFailover(node, node2):
   """gnt-node failover"""
   master = qa_config.GetMasterNode()