Statistics
| Branch: | Tag: | Revision:

root / lib / jstore.py @ 9afb67fe

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 logging
26
import errno
27
import re
28

    
29
from ganeti import constants
30
from ganeti import errors
31
from ganeti import utils
32

    
33

    
34
def _ReadNumericFile(file_name):
35
  """Reads a file containing a number.
36

37
  @rtype: None or int
38
  @return: None if file is not found, otherwise number
39

40
  """
41
  try:
42
    fd = open(file_name, "r")
43
  except IOError, err:
44
    if err.errno in (errno.ENOENT, ):
45
      return None
46
    raise
47

    
48
  try:
49
    return int(fd.read(128))
50
  finally:
51
    fd.close()
52

    
53

    
54
def ReadSerial():
55
  """Read the serial file.
56

57
  The queue should be locked while this function is called.
58

59
  """
60
  return _ReadNumericFile(constants.JOB_QUEUE_SERIAL_FILE)
61

    
62

    
63
def ReadVersion():
64
  """Read the queue version.
65

66
  The queue should be locked while this function is called.
67

68
  """
69
  return _ReadNumericFile(constants.JOB_QUEUE_VERSION_FILE)
70

    
71

    
72
def InitAndVerifyQueue(must_lock):
73
  """Open and lock job queue.
74

75
  If necessary, the queue is automatically initialized.
76

77
  @type must_lock: bool
78
  @param must_lock: Whether an exclusive lock must be held.
79
  @rtype: utils.FileLock
80
  @return: Lock object for the queue. This can be used to change the
81
           locking mode.
82

83
  """
84
  # Make sure our directories exists
85
  for path in (constants.QUEUE_DIR, constants.JOB_QUEUE_ARCHIVE_DIR):
86
    try:
87
      os.mkdir(path, 0700)
88
    except OSError, err:
89
      if err.errno not in (errno.EEXIST, ):
90
        raise
91

    
92
  # Lock queue
93
  queue_lock = utils.FileLock(constants.JOB_QUEUE_LOCK_FILE)
94
  try:
95
    # The queue needs to be locked in exclusive mode to write to the serial and
96
    # version files.
97
    if must_lock:
98
      queue_lock.Exclusive(blocking=True)
99
      holding_lock = True
100
    else:
101
      try:
102
        queue_lock.Exclusive(blocking=False)
103
        holding_lock = True
104
      except errors.LockError:
105
        # Ignore errors and assume the process keeping the lock checked
106
        # everything.
107
        holding_lock = False
108

    
109
    if holding_lock:
110
      # Verify version
111
      version = ReadVersion()
112
      if version is None:
113
        # Write new version file
114
        utils.WriteFile(constants.JOB_QUEUE_VERSION_FILE,
115
                        data="%s\n" % constants.JOB_QUEUE_VERSION)
116

    
117
        # Read again
118
        version = ReadVersion()
119

    
120
      if version != constants.JOB_QUEUE_VERSION:
121
        raise errors.JobQueueError("Found job queue version %s, expected %s",
122
                                   version, constants.JOB_QUEUE_VERSION)
123

    
124
      serial = ReadSerial()
125
      if serial is None:
126
        # Write new serial file
127
        utils.WriteFile(constants.JOB_QUEUE_SERIAL_FILE,
128
                        data="%s\n" % 0)
129

    
130
        # Read again
131
        serial = ReadSerial()
132

    
133
      if serial is None:
134
        # There must be a serious problem
135
        raise errors.JobQueueError("Can't read/parse the job queue serial file")
136

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

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

    
146
  return queue_lock