Add --force-join option to gnt-node add
[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 errno
25
26 from ganeti import constants
27 from ganeti import errors
28 from ganeti import runtime
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     return int(utils.ReadFile(file_name))
41   except EnvironmentError, err:
42     if err.errno in (errno.ENOENT, ):
43       return None
44     raise
45
46
47 def ReadSerial():
48   """Read the serial file.
49
50   The queue should be locked while this function is called.
51
52   """
53   return _ReadNumericFile(constants.JOB_QUEUE_SERIAL_FILE)
54
55
56 def ReadVersion():
57   """Read the queue version.
58
59   The queue should be locked while this function is called.
60
61   """
62   return _ReadNumericFile(constants.JOB_QUEUE_VERSION_FILE)
63
64
65 def InitAndVerifyQueue(must_lock):
66   """Open and lock job queue.
67
68   If necessary, the queue is automatically initialized.
69
70   @type must_lock: bool
71   @param must_lock: Whether an exclusive lock must be held.
72   @rtype: utils.FileLock
73   @return: Lock object for the queue. This can be used to change the
74            locking mode.
75
76   """
77   getents = runtime.GetEnts()
78
79   # Lock queue
80   queue_lock = utils.FileLock.Open(constants.JOB_QUEUE_LOCK_FILE)
81   try:
82     # The queue needs to be locked in exclusive mode to write to the serial and
83     # version files.
84     if must_lock:
85       queue_lock.Exclusive(blocking=True)
86       holding_lock = True
87     else:
88       try:
89         queue_lock.Exclusive(blocking=False)
90         holding_lock = True
91       except errors.LockError:
92         # Ignore errors and assume the process keeping the lock checked
93         # everything.
94         holding_lock = False
95
96     if holding_lock:
97       # Verify version
98       version = ReadVersion()
99       if version is None:
100         # Write new version file
101         utils.WriteFile(constants.JOB_QUEUE_VERSION_FILE,
102                         uid=getents.masterd_uid, gid=getents.masterd_gid,
103                         data="%s\n" % constants.JOB_QUEUE_VERSION)
104
105         # Read again
106         version = ReadVersion()
107
108       if version != constants.JOB_QUEUE_VERSION:
109         raise errors.JobQueueError("Found job queue version %s, expected %s",
110                                    version, constants.JOB_QUEUE_VERSION)
111
112       serial = ReadSerial()
113       if serial is None:
114         # Write new serial file
115         utils.WriteFile(constants.JOB_QUEUE_SERIAL_FILE,
116                         uid=getents.masterd_uid, gid=getents.masterd_gid,
117                         data="%s\n" % 0)
118
119         # Read again
120         serial = ReadSerial()
121
122       if serial is None:
123         # There must be a serious problem
124         raise errors.JobQueueError("Can't read/parse the job queue"
125                                    " serial file")
126
127       if not must_lock:
128         # There's no need for more error handling. Closing the lock
129         # file below in case of an error will unlock it anyway.
130         queue_lock.Unlock()
131
132   except:
133     queue_lock.Close()
134     raise
135
136   return queue_lock