Statistics
| Branch: | Tag: | Revision:

root / lib / jstore.py @ b4478d34

History | View | Annotate | Download (3.8 kB)

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.Open(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"
134
                                   " serial file")
135

    
136
      if not must_lock:
137
        # There's no need for more error handling. Closing the lock
138
        # file below in case of an error will unlock it anyway.
139
        queue_lock.Unlock()
140

    
141
  except:
142
    queue_lock.Close()
143
    raise
144

    
145
  return queue_lock