diff --git a/lib/constants.py b/lib/constants.py
index a9d61d45bc3f9a6db2f1b6bf16f74517a854d7bf..114cf91ba45fb86e10b3a258f9ab3a71e28e6a58 100644
--- a/lib/constants.py
+++ b/lib/constants.py
@@ -826,6 +826,12 @@ JOBS_FINALIZED = frozenset([
   JOB_STATUS_SUCCESS,
   JOB_STATUS_ERROR,
   ])
+JOB_STATUS_ALL = frozenset([
+  JOB_STATUS_QUEUED,
+  JOB_STATUS_WAITLOCK,
+  JOB_STATUS_CANCELING,
+  JOB_STATUS_RUNNING,
+  ]) | JOBS_FINALIZED
 
 # OpCode status
 # not yet finalized
diff --git a/test/ganeti.jqueue_unittest.py b/test/ganeti.jqueue_unittest.py
index c83157509a1e053f0937a982d902b22602a15d7e..ce065411cdf0c0fa2852cb3c5100ba30fb415408 100755
--- a/test/ganeti.jqueue_unittest.py
+++ b/test/ganeti.jqueue_unittest.py
@@ -346,6 +346,81 @@ class TestQueuedJob(unittest.TestCase):
     job.ops[0].priority -= 19
     self.assertEqual(job.CalcPriority(), constants.OP_PRIO_DEFAULT - 20)
 
+  def testCalcStatus(self):
+    def _Queued(ops):
+      # The default status is "queued"
+      self.assert_(compat.all(op.status == constants.OP_STATUS_QUEUED
+                              for op in ops))
+
+    def _Waitlock1(ops):
+      ops[0].status = constants.OP_STATUS_WAITLOCK
+
+    def _Waitlock2(ops):
+      ops[0].status = constants.OP_STATUS_SUCCESS
+      ops[1].status = constants.OP_STATUS_SUCCESS
+      ops[2].status = constants.OP_STATUS_WAITLOCK
+
+    def _Running(ops):
+      ops[0].status = constants.OP_STATUS_SUCCESS
+      ops[1].status = constants.OP_STATUS_RUNNING
+      for op in ops[2:]:
+        op.status = constants.OP_STATUS_QUEUED
+
+    def _Canceling1(ops):
+      ops[0].status = constants.OP_STATUS_SUCCESS
+      ops[1].status = constants.OP_STATUS_SUCCESS
+      for op in ops[2:]:
+        op.status = constants.OP_STATUS_CANCELING
+
+    def _Canceling2(ops):
+      for op in ops:
+        op.status = constants.OP_STATUS_CANCELING
+
+    def _Canceled(ops):
+      for op in ops:
+        op.status = constants.OP_STATUS_CANCELED
+
+    def _Error1(ops):
+      for idx, op in enumerate(ops):
+        if idx > 3:
+          op.status = constants.OP_STATUS_ERROR
+        else:
+          op.status = constants.OP_STATUS_SUCCESS
+
+    def _Error2(ops):
+      for op in ops:
+        op.status = constants.OP_STATUS_ERROR
+
+    def _Success(ops):
+      for op in ops:
+        op.status = constants.OP_STATUS_SUCCESS
+
+    tests = {
+      constants.JOB_STATUS_QUEUED: [_Queued],
+      constants.JOB_STATUS_WAITLOCK: [_Waitlock1, _Waitlock2],
+      constants.JOB_STATUS_RUNNING: [_Running],
+      constants.JOB_STATUS_CANCELING: [_Canceling1, _Canceling2],
+      constants.JOB_STATUS_CANCELED: [_Canceled],
+      constants.JOB_STATUS_ERROR: [_Error1, _Error2],
+      constants.JOB_STATUS_SUCCESS: [_Success],
+      }
+
+    def _NewJob():
+      job = jqueue._QueuedJob(None, 1,
+                              [opcodes.OpTestDelay() for _ in range(10)])
+      self.assertEqual(job.CalcStatus(), constants.JOB_STATUS_QUEUED)
+      self.assert_(compat.all(op.status == constants.OP_STATUS_QUEUED
+                              for op in job.ops))
+      return job
+
+    for status in constants.JOB_STATUS_ALL:
+      sttests = tests[status]
+      assert sttests
+      for fn in sttests:
+        job = _NewJob()
+        fn(job.ops)
+        self.assertEqual(job.CalcStatus(), status)
+
 
 class _FakeQueueForProc:
   def __init__(self):