New RPC to get size and spindles of disks
[ganeti-local] / lib / jstore.py
index e735c71..324f91e 100644 (file)
@@ -1,7 +1,7 @@
 #
 #
 
-# Copyright (C) 2006, 2007 Google Inc.
+# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -28,6 +28,7 @@ from ganeti import constants
 from ganeti import errors
 from ganeti import runtime
 from ganeti import utils
+from ganeti import pathutils
 
 
 JOBS_PER_ARCHIVE_DIRECTORY = 10000
@@ -41,12 +42,19 @@ def _ReadNumericFile(file_name):
 
   """
   try:
-    return int(utils.ReadFile(file_name))
+    contents = utils.ReadFile(file_name)
   except EnvironmentError, err:
     if err.errno in (errno.ENOENT, ):
       return None
     raise
 
+  try:
+    return int(contents)
+  except (ValueError, TypeError), err:
+    # Couldn't convert to int
+    raise errors.JobQueueError("Content of file '%s' is not numeric: %s" %
+                               (file_name, err))
+
 
 def ReadSerial():
   """Read the serial file.
@@ -54,7 +62,7 @@ def ReadSerial():
   The queue should be locked while this function is called.
 
   """
-  return _ReadNumericFile(constants.JOB_QUEUE_SERIAL_FILE)
+  return _ReadNumericFile(pathutils.JOB_QUEUE_SERIAL_FILE)
 
 
 def ReadVersion():
@@ -63,7 +71,7 @@ def ReadVersion():
   The queue should be locked while this function is called.
 
   """
-  return _ReadNumericFile(constants.JOB_QUEUE_VERSION_FILE)
+  return _ReadNumericFile(pathutils.JOB_QUEUE_VERSION_FILE)
 
 
 def InitAndVerifyQueue(must_lock):
@@ -81,7 +89,7 @@ def InitAndVerifyQueue(must_lock):
   getents = runtime.GetEnts()
 
   # Lock queue
-  queue_lock = utils.FileLock.Open(constants.JOB_QUEUE_LOCK_FILE)
+  queue_lock = utils.FileLock.Open(pathutils.JOB_QUEUE_LOCK_FILE)
   try:
     # The queue needs to be locked in exclusive mode to write to the serial and
     # version files.
@@ -102,8 +110,9 @@ def InitAndVerifyQueue(must_lock):
       version = ReadVersion()
       if version is None:
         # Write new version file
-        utils.WriteFile(constants.JOB_QUEUE_VERSION_FILE,
-                        uid=getents.masterd_uid, gid=getents.masterd_gid,
+        utils.WriteFile(pathutils.JOB_QUEUE_VERSION_FILE,
+                        uid=getents.masterd_uid, gid=getents.daemons_gid,
+                        mode=constants.JOB_QUEUE_FILES_PERMS,
                         data="%s\n" % constants.JOB_QUEUE_VERSION)
 
         # Read again
@@ -116,8 +125,9 @@ def InitAndVerifyQueue(must_lock):
       serial = ReadSerial()
       if serial is None:
         # Write new serial file
-        utils.WriteFile(constants.JOB_QUEUE_SERIAL_FILE,
-                        uid=getents.masterd_uid, gid=getents.masterd_gid,
+        utils.WriteFile(pathutils.JOB_QUEUE_SERIAL_FILE,
+                        uid=getents.masterd_uid, gid=getents.daemons_gid,
+                        mode=constants.JOB_QUEUE_FILES_PERMS,
                         data="%s\n" % 0)
 
         # Read again
@@ -150,7 +160,7 @@ def CheckDrainFlag():
   @return: True if the job queue is marked drained
 
   """
-  return os.path.exists(constants.JOB_QUEUE_DRAIN_FILE)
+  return os.path.exists(pathutils.JOB_QUEUE_DRAIN_FILE)
 
 
 def SetDrainFlag(drain_flag):
@@ -165,24 +175,24 @@ def SetDrainFlag(drain_flag):
   getents = runtime.GetEnts()
 
   if drain_flag:
-    utils.WriteFile(constants.JOB_QUEUE_DRAIN_FILE, data="",
-                    uid=getents.masterd_uid, gid=getents.masterd_gid)
+    utils.WriteFile(pathutils.JOB_QUEUE_DRAIN_FILE, data="",
+                    uid=getents.masterd_uid, gid=getents.daemons_gid,
+                    mode=constants.JOB_QUEUE_FILES_PERMS)
   else:
-    utils.RemoveFile(constants.JOB_QUEUE_DRAIN_FILE)
+    utils.RemoveFile(pathutils.JOB_QUEUE_DRAIN_FILE)
 
   assert (not drain_flag) ^ CheckDrainFlag()
 
 
 def FormatJobID(job_id):
-  """Convert a job ID to string format.
+  """Convert a job ID to int format.
 
-  Currently this just does C{str(job_id)} after performing some
-  checks, but if we want to change the job id format this will
-  abstract this change.
+  Currently this just is a no-op that performs some checks, but if we
+  want to change the job id format this will abstract this change.
 
   @type job_id: int or long
   @param job_id: the numeric job id
-  @rtype: str
+  @rtype: int
   @return: the formatted job id
 
   """
@@ -191,7 +201,7 @@ def FormatJobID(job_id):
   if job_id < 0:
     raise errors.ProgrammerError("Job ID %s is negative" % job_id)
 
-  return str(job_id)
+  return job_id
 
 
 def GetArchiveDirectory(job_id):
@@ -203,4 +213,14 @@ def GetArchiveDirectory(job_id):
   @return: Directory name
 
   """
-  return str(int(job_id) / JOBS_PER_ARCHIVE_DIRECTORY)
+  return str(ParseJobId(job_id) / JOBS_PER_ARCHIVE_DIRECTORY)
+
+
+def ParseJobId(job_id):
+  """Parses a job ID and converts it to integer.
+
+  """
+  try:
+    return int(job_id)
+  except (ValueError, TypeError):
+    raise errors.ParameterError("Invalid job ID '%s'" % job_id)