Get rid of constants.RAPI_ENABLE
[ganeti-local] / lib / jstore.py
1 #
2 #
3
4 # Copyright (C) 2006, 2007 Google Inc.
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 # 02110-1301, USA.
20
21
22 """Module implementing the job queue handling."""
23
24 import os
25 import errno
26
27 from ganeti import constants
28 from ganeti import errors
29 from ganeti import utils
30
31
32 def _ReadNumericFile(file_name):
33   """Reads a file containing a number.
34
35   @rtype: None or int
36   @return: None if file is not found, otherwise number
37
38   """
39   try:
40     fd = open(file_name, "r")
41   except IOError, err:
42     if err.errno in (errno.ENOENT, ):
43       return None
44     raise
45
46   try:
47     return int(fd.read(128))
48   finally:
49     fd.close()
50
51
52 def ReadSerial():
53   """Read the serial file.
54
55   The queue should be locked while this function is called.
56
57   """
58   return _ReadNumericFile(constants.JOB_QUEUE_SERIAL_FILE)
59
60
61 def ReadVersion():
62   """Read the queue version.
63
64   The queue should be locked while this function is called.
65
66   """
67   return _ReadNumericFile(constants.JOB_QUEUE_VERSION_FILE)
68
69
70 def InitAndVerifyQueue(must_lock):
71   """Open and lock job queue.
72
73   If necessary, the queue is automatically initialized.
74
75   @type must_lock: bool
76   @param must_lock: Whether an exclusive lock must be held.
77   @rtype: utils.FileLock
78   @return: Lock object for the queue. This can be used to change the
79            locking mode.
80
81   """
82   # Make sure our directories exists
83   for path in (constants.QUEUE_DIR, constants.JOB_QUEUE_ARCHIVE_DIR):
84     try:
85       os.mkdir(path, 0700)
86     except OSError, err:
87       if err.errno not in (errno.EEXIST, ):
88         raise
89
90   # Lock queue
91   queue_lock = utils.FileLock(constants.JOB_QUEUE_LOCK_FILE)
92   try:
93     # The queue needs to be locked in exclusive mode to write to the serial and
94     # version files.
95     if must_lock:
96       queue_lock.Exclusive(blocking=True)
97       holding_lock = True
98     else:
99       try:
100         queue_lock.Exclusive(blocking=False)
101         holding_lock = True
102       except errors.LockError:
103         # Ignore errors and assume the process keeping the lock checked
104         # everything.
105         holding_lock = False
106
107     if holding_lock:
108       # Verify version
109       version = ReadVersion()
110       if version is None:
111         # Write new version file
112         utils.WriteFile(constants.JOB_QUEUE_VERSION_FILE,
113                         data="%s\n" % constants.JOB_QUEUE_VERSION)
114
115         # Read again
116         version = ReadVersion()
117
118       if version != constants.JOB_QUEUE_VERSION:
119         raise errors.JobQueueError("Found job queue version %s, expected %s",
120                                    version, constants.JOB_QUEUE_VERSION)
121
122       serial = ReadSerial()
123       if serial is None:
124         # Write new serial file
125         utils.WriteFile(constants.JOB_QUEUE_SERIAL_FILE,
126                         data="%s\n" % 0)
127
128         # Read again
129         serial = ReadSerial()
130
131       if serial is None:
132         # There must be a serious problem
133         raise errors.JobQueueError("Can't read/parse the job queue serial file")
134
135       if not must_lock:
136         # There's no need for more error handling. Closing the lock file below in
137         # case of an error will unlock it anyway.
138         queue_lock.Unlock()
139
140   except:
141     queue_lock.Close()
142     raise
143
144   return queue_lock