Statistics
| Branch: | Tag: | Revision:

root / lib / jstore.py @ 526f866b

History | View | Annotate | Download (5.6 kB)

1 8b537bb0 Michael Hanselmann
#
2 8b537bb0 Michael Hanselmann
#
3 8b537bb0 Michael Hanselmann
4 8b537bb0 Michael Hanselmann
# Copyright (C) 2006, 2007 Google Inc.
5 8b537bb0 Michael Hanselmann
#
6 8b537bb0 Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 8b537bb0 Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 8b537bb0 Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 8b537bb0 Michael Hanselmann
# (at your option) any later version.
10 8b537bb0 Michael Hanselmann
#
11 8b537bb0 Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 8b537bb0 Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 8b537bb0 Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 8b537bb0 Michael Hanselmann
# General Public License for more details.
15 8b537bb0 Michael Hanselmann
#
16 8b537bb0 Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 8b537bb0 Michael Hanselmann
# along with this program; if not, write to the Free Software
18 8b537bb0 Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 8b537bb0 Michael Hanselmann
# 02110-1301, USA.
20 8b537bb0 Michael Hanselmann
21 8b537bb0 Michael Hanselmann
22 8b537bb0 Michael Hanselmann
"""Module implementing the job queue handling."""
23 8b537bb0 Michael Hanselmann
24 8b537bb0 Michael Hanselmann
import errno
25 ff699aa9 Michael Hanselmann
import os
26 8b537bb0 Michael Hanselmann
27 8b537bb0 Michael Hanselmann
from ganeti import constants
28 8b537bb0 Michael Hanselmann
from ganeti import errors
29 82b22e19 René Nussbaumer
from ganeti import runtime
30 8b537bb0 Michael Hanselmann
from ganeti import utils
31 8b537bb0 Michael Hanselmann
32 8b537bb0 Michael Hanselmann
33 1410a389 Michael Hanselmann
JOBS_PER_ARCHIVE_DIRECTORY = 10000
34 1410a389 Michael Hanselmann
35 1410a389 Michael Hanselmann
36 8b537bb0 Michael Hanselmann
def _ReadNumericFile(file_name):
37 8b537bb0 Michael Hanselmann
  """Reads a file containing a number.
38 8b537bb0 Michael Hanselmann

39 8b537bb0 Michael Hanselmann
  @rtype: None or int
40 8b537bb0 Michael Hanselmann
  @return: None if file is not found, otherwise number
41 8b537bb0 Michael Hanselmann

42 8b537bb0 Michael Hanselmann
  """
43 8b537bb0 Michael Hanselmann
  try:
44 6358dbc2 Guido Trotter
    return int(utils.ReadFile(file_name))
45 6358dbc2 Guido Trotter
  except EnvironmentError, err:
46 8b537bb0 Michael Hanselmann
    if err.errno in (errno.ENOENT, ):
47 8b537bb0 Michael Hanselmann
      return None
48 8b537bb0 Michael Hanselmann
    raise
49 8b537bb0 Michael Hanselmann
50 8b537bb0 Michael Hanselmann
51 8b537bb0 Michael Hanselmann
def ReadSerial():
52 8b537bb0 Michael Hanselmann
  """Read the serial file.
53 8b537bb0 Michael Hanselmann

54 8b537bb0 Michael Hanselmann
  The queue should be locked while this function is called.
55 8b537bb0 Michael Hanselmann

56 8b537bb0 Michael Hanselmann
  """
57 8b537bb0 Michael Hanselmann
  return _ReadNumericFile(constants.JOB_QUEUE_SERIAL_FILE)
58 8b537bb0 Michael Hanselmann
59 8b537bb0 Michael Hanselmann
60 8b537bb0 Michael Hanselmann
def ReadVersion():
61 8b537bb0 Michael Hanselmann
  """Read the queue version.
62 8b537bb0 Michael Hanselmann

63 8b537bb0 Michael Hanselmann
  The queue should be locked while this function is called.
64 8b537bb0 Michael Hanselmann

65 8b537bb0 Michael Hanselmann
  """
66 8b537bb0 Michael Hanselmann
  return _ReadNumericFile(constants.JOB_QUEUE_VERSION_FILE)
67 8b537bb0 Michael Hanselmann
68 8b537bb0 Michael Hanselmann
69 5d6fb8eb Michael Hanselmann
def InitAndVerifyQueue(must_lock):
70 8b537bb0 Michael Hanselmann
  """Open and lock job queue.
71 8b537bb0 Michael Hanselmann

72 8b537bb0 Michael Hanselmann
  If necessary, the queue is automatically initialized.
73 8b537bb0 Michael Hanselmann

74 5d6fb8eb Michael Hanselmann
  @type must_lock: bool
75 5d6fb8eb Michael Hanselmann
  @param must_lock: Whether an exclusive lock must be held.
76 8b537bb0 Michael Hanselmann
  @rtype: utils.FileLock
77 8b537bb0 Michael Hanselmann
  @return: Lock object for the queue. This can be used to change the
78 8b537bb0 Michael Hanselmann
           locking mode.
79 8b537bb0 Michael Hanselmann

80 8b537bb0 Michael Hanselmann
  """
81 82b22e19 René Nussbaumer
  getents = runtime.GetEnts()
82 8b537bb0 Michael Hanselmann
83 8b537bb0 Michael Hanselmann
  # Lock queue
84 b4478d34 Michael Hanselmann
  queue_lock = utils.FileLock.Open(constants.JOB_QUEUE_LOCK_FILE)
85 8b537bb0 Michael Hanselmann
  try:
86 5d6fb8eb Michael Hanselmann
    # The queue needs to be locked in exclusive mode to write to the serial and
87 5d6fb8eb Michael Hanselmann
    # version files.
88 5d6fb8eb Michael Hanselmann
    if must_lock:
89 5d6fb8eb Michael Hanselmann
      queue_lock.Exclusive(blocking=True)
90 5d6fb8eb Michael Hanselmann
      holding_lock = True
91 8b537bb0 Michael Hanselmann
    else:
92 5d6fb8eb Michael Hanselmann
      try:
93 5d6fb8eb Michael Hanselmann
        queue_lock.Exclusive(blocking=False)
94 5d6fb8eb Michael Hanselmann
        holding_lock = True
95 5d6fb8eb Michael Hanselmann
      except errors.LockError:
96 5d6fb8eb Michael Hanselmann
        # Ignore errors and assume the process keeping the lock checked
97 5d6fb8eb Michael Hanselmann
        # everything.
98 5d6fb8eb Michael Hanselmann
        holding_lock = False
99 5d6fb8eb Michael Hanselmann
100 5d6fb8eb Michael Hanselmann
    if holding_lock:
101 5d6fb8eb Michael Hanselmann
      # Verify version
102 8b537bb0 Michael Hanselmann
      version = ReadVersion()
103 5d6fb8eb Michael Hanselmann
      if version is None:
104 5d6fb8eb Michael Hanselmann
        # Write new version file
105 5d6fb8eb Michael Hanselmann
        utils.WriteFile(constants.JOB_QUEUE_VERSION_FILE,
106 82b22e19 René Nussbaumer
                        uid=getents.masterd_uid, gid=getents.masterd_gid,
107 5d6fb8eb Michael Hanselmann
                        data="%s\n" % constants.JOB_QUEUE_VERSION)
108 8b537bb0 Michael Hanselmann
109 5d6fb8eb Michael Hanselmann
        # Read again
110 5d6fb8eb Michael Hanselmann
        version = ReadVersion()
111 8b537bb0 Michael Hanselmann
112 5d6fb8eb Michael Hanselmann
      if version != constants.JOB_QUEUE_VERSION:
113 5d6fb8eb Michael Hanselmann
        raise errors.JobQueueError("Found job queue version %s, expected %s",
114 5d6fb8eb Michael Hanselmann
                                   version, constants.JOB_QUEUE_VERSION)
115 8b537bb0 Michael Hanselmann
116 8b537bb0 Michael Hanselmann
      serial = ReadSerial()
117 5d6fb8eb Michael Hanselmann
      if serial is None:
118 5d6fb8eb Michael Hanselmann
        # Write new serial file
119 5d6fb8eb Michael Hanselmann
        utils.WriteFile(constants.JOB_QUEUE_SERIAL_FILE,
120 82b22e19 René Nussbaumer
                        uid=getents.masterd_uid, gid=getents.masterd_gid,
121 5d6fb8eb Michael Hanselmann
                        data="%s\n" % 0)
122 5d6fb8eb Michael Hanselmann
123 5d6fb8eb Michael Hanselmann
        # Read again
124 5d6fb8eb Michael Hanselmann
        serial = ReadSerial()
125 8b537bb0 Michael Hanselmann
126 5d6fb8eb Michael Hanselmann
      if serial is None:
127 5d6fb8eb Michael Hanselmann
        # There must be a serious problem
128 fe267188 Iustin Pop
        raise errors.JobQueueError("Can't read/parse the job queue"
129 fe267188 Iustin Pop
                                   " serial file")
130 8b537bb0 Michael Hanselmann
131 f56377a3 Michael Hanselmann
      if not must_lock:
132 fe267188 Iustin Pop
        # There's no need for more error handling. Closing the lock
133 fe267188 Iustin Pop
        # file below in case of an error will unlock it anyway.
134 f56377a3 Michael Hanselmann
        queue_lock.Unlock()
135 f56377a3 Michael Hanselmann
136 8b537bb0 Michael Hanselmann
  except:
137 8b537bb0 Michael Hanselmann
    queue_lock.Close()
138 8b537bb0 Michael Hanselmann
    raise
139 8b537bb0 Michael Hanselmann
140 8b537bb0 Michael Hanselmann
  return queue_lock
141 ff699aa9 Michael Hanselmann
142 ff699aa9 Michael Hanselmann
143 ff699aa9 Michael Hanselmann
def CheckDrainFlag():
144 ff699aa9 Michael Hanselmann
  """Check if the queue is marked to be drained.
145 ff699aa9 Michael Hanselmann

146 ff699aa9 Michael Hanselmann
  This currently uses the queue drain file, which makes it a per-node flag.
147 ff699aa9 Michael Hanselmann
  In the future this can be moved to the config file.
148 ff699aa9 Michael Hanselmann

149 ff699aa9 Michael Hanselmann
  @rtype: boolean
150 ff699aa9 Michael Hanselmann
  @return: True if the job queue is marked drained
151 ff699aa9 Michael Hanselmann

152 ff699aa9 Michael Hanselmann
  """
153 ff699aa9 Michael Hanselmann
  return os.path.exists(constants.JOB_QUEUE_DRAIN_FILE)
154 ff699aa9 Michael Hanselmann
155 ff699aa9 Michael Hanselmann
156 ff699aa9 Michael Hanselmann
def SetDrainFlag(drain_flag):
157 ff699aa9 Michael Hanselmann
  """Sets the drain flag for the queue.
158 ff699aa9 Michael Hanselmann

159 ff699aa9 Michael Hanselmann
  @type drain_flag: boolean
160 ff699aa9 Michael Hanselmann
  @param drain_flag: Whether to set or unset the drain flag
161 ff699aa9 Michael Hanselmann
  @attention: This function should only called the current holder of the queue
162 ff699aa9 Michael Hanselmann
    lock
163 ff699aa9 Michael Hanselmann

164 ff699aa9 Michael Hanselmann
  """
165 ff699aa9 Michael Hanselmann
  getents = runtime.GetEnts()
166 ff699aa9 Michael Hanselmann
167 ff699aa9 Michael Hanselmann
  if drain_flag:
168 ff699aa9 Michael Hanselmann
    utils.WriteFile(constants.JOB_QUEUE_DRAIN_FILE, data="",
169 ff699aa9 Michael Hanselmann
                    uid=getents.masterd_uid, gid=getents.masterd_gid)
170 ff699aa9 Michael Hanselmann
  else:
171 ff699aa9 Michael Hanselmann
    utils.RemoveFile(constants.JOB_QUEUE_DRAIN_FILE)
172 ff699aa9 Michael Hanselmann
173 ff699aa9 Michael Hanselmann
  assert (not drain_flag) ^ CheckDrainFlag()
174 1410a389 Michael Hanselmann
175 1410a389 Michael Hanselmann
176 1410a389 Michael Hanselmann
def FormatJobID(job_id):
177 1410a389 Michael Hanselmann
  """Convert a job ID to string format.
178 1410a389 Michael Hanselmann

179 1410a389 Michael Hanselmann
  Currently this just does C{str(job_id)} after performing some
180 1410a389 Michael Hanselmann
  checks, but if we want to change the job id format this will
181 1410a389 Michael Hanselmann
  abstract this change.
182 1410a389 Michael Hanselmann

183 1410a389 Michael Hanselmann
  @type job_id: int or long
184 1410a389 Michael Hanselmann
  @param job_id: the numeric job id
185 1410a389 Michael Hanselmann
  @rtype: str
186 1410a389 Michael Hanselmann
  @return: the formatted job id
187 1410a389 Michael Hanselmann

188 1410a389 Michael Hanselmann
  """
189 1410a389 Michael Hanselmann
  if not isinstance(job_id, (int, long)):
190 1410a389 Michael Hanselmann
    raise errors.ProgrammerError("Job ID '%s' not numeric" % job_id)
191 1410a389 Michael Hanselmann
  if job_id < 0:
192 1410a389 Michael Hanselmann
    raise errors.ProgrammerError("Job ID %s is negative" % job_id)
193 1410a389 Michael Hanselmann
194 1410a389 Michael Hanselmann
  return str(job_id)
195 1410a389 Michael Hanselmann
196 1410a389 Michael Hanselmann
197 1410a389 Michael Hanselmann
def GetArchiveDirectory(job_id):
198 1410a389 Michael Hanselmann
  """Returns the archive directory for a job.
199 1410a389 Michael Hanselmann

200 1410a389 Michael Hanselmann
  @type job_id: str
201 1410a389 Michael Hanselmann
  @param job_id: Job identifier
202 1410a389 Michael Hanselmann
  @rtype: str
203 1410a389 Michael Hanselmann
  @return: Directory name
204 1410a389 Michael Hanselmann

205 1410a389 Michael Hanselmann
  """
206 526f866b Michael Hanselmann
  return str(ParseJobId(job_id) / JOBS_PER_ARCHIVE_DIRECTORY)
207 526f866b Michael Hanselmann
208 526f866b Michael Hanselmann
209 526f866b Michael Hanselmann
def ParseJobId(job_id):
210 526f866b Michael Hanselmann
  """Parses a job ID and converts it to integer.
211 526f866b Michael Hanselmann

212 526f866b Michael Hanselmann
  """
213 526f866b Michael Hanselmann
  try:
214 526f866b Michael Hanselmann
    return int(job_id)
215 526f866b Michael Hanselmann
  except (ValueError, TypeError):
216 526f866b Michael Hanselmann
    raise errors.ParameterError("Invalid job ID '%s'" % job_id)