Statistics
| Branch: | Tag: | Revision:

root / lib / ssconf.py @ efbb4fd2

History | View | Annotate | Download (12.3 kB)

1 2f31098c Iustin Pop
#
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 856c67e1 Michael Hanselmann
# Copyright (C) 2006, 2007, 2008 Google Inc.
5 a8083063 Iustin Pop
#
6 a8083063 Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 a8083063 Iustin Pop
# it under the terms of the GNU General Public License as published by
8 a8083063 Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 a8083063 Iustin Pop
# (at your option) any later version.
10 a8083063 Iustin Pop
#
11 a8083063 Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 a8083063 Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 a8083063 Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 a8083063 Iustin Pop
# General Public License for more details.
15 a8083063 Iustin Pop
#
16 a8083063 Iustin Pop
# You should have received a copy of the GNU General Public License
17 a8083063 Iustin Pop
# along with this program; if not, write to the Free Software
18 a8083063 Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 a8083063 Iustin Pop
# 02110-1301, USA.
20 a8083063 Iustin Pop
21 a8083063 Iustin Pop
22 a8083063 Iustin Pop
"""Global Configuration data for Ganeti.
23 a8083063 Iustin Pop

24 a8083063 Iustin Pop
This module provides the interface to a special case of cluster
25 a8083063 Iustin Pop
configuration data, which is mostly static and available to all nodes.
26 a8083063 Iustin Pop

27 a8083063 Iustin Pop
"""
28 a8083063 Iustin Pop
29 5675cd1f Iustin Pop
import sys
30 03d1dba2 Michael Hanselmann
import re
31 7bcc78e4 Guido Trotter
import os
32 a8083063 Iustin Pop
33 a8083063 Iustin Pop
from ganeti import errors
34 a8083063 Iustin Pop
from ganeti import constants
35 41a57aab Michael Hanselmann
from ganeti import utils
36 856c67e1 Michael Hanselmann
from ganeti import serializer
37 a8083063 Iustin Pop
38 a8083063 Iustin Pop
39 0c223ea9 Michael Hanselmann
SSCONF_LOCK_TIMEOUT = 10
40 0c223ea9 Michael Hanselmann
41 03d1dba2 Michael Hanselmann
RE_VALID_SSCONF_NAME = re.compile(r'^[-_a-z0-9]+$')
42 03d1dba2 Michael Hanselmann
43 0c223ea9 Michael Hanselmann
44 02f99608 Oleksiy Mishchenko
class SimpleConfigReader(object):
45 856c67e1 Michael Hanselmann
  """Simple class to read configuration file.
46 856c67e1 Michael Hanselmann

47 856c67e1 Michael Hanselmann
  """
48 856c67e1 Michael Hanselmann
  def __init__(self, file_name=constants.CLUSTER_CONF_FILE):
49 856c67e1 Michael Hanselmann
    """Initializes this class.
50 856c67e1 Michael Hanselmann

51 856c67e1 Michael Hanselmann
    @type file_name: string
52 856c67e1 Michael Hanselmann
    @param file_name: Configuration file path
53 856c67e1 Michael Hanselmann

54 856c67e1 Michael Hanselmann
    """
55 856c67e1 Michael Hanselmann
    self._file_name = file_name
56 7bcc78e4 Guido Trotter
    self._last_inode = None
57 7bcc78e4 Guido Trotter
    self._last_mtime = None
58 7bcc78e4 Guido Trotter
    self._last_size = None
59 7bcc78e4 Guido Trotter
    # we need a forced reload at class init time, to initialize _last_*
60 7bcc78e4 Guido Trotter
    self._Load(force=True)
61 1fe93c75 Guido Trotter
62 7bcc78e4 Guido Trotter
  def _Load(self, force=False):
63 ad8b2f9b Guido Trotter
    """Loads (or reloads) the config file.
64 1fe93c75 Guido Trotter

65 7bcc78e4 Guido Trotter
    @type force: boolean
66 7bcc78e4 Guido Trotter
    @param force: whether to force the reload without checking the mtime
67 7bcc78e4 Guido Trotter
    @rtype: boolean
68 4d4a651d Michael Hanselmann
    @return: boolean value that says whether we reloaded the configuration or
69 4d4a651d Michael Hanselmann
             not (because we decided it was already up-to-date)
70 7bcc78e4 Guido Trotter

71 1fe93c75 Guido Trotter
    """
72 d4c1bd12 Guido Trotter
    try:
73 d4c1bd12 Guido Trotter
      cfg_stat = os.stat(self._file_name)
74 d4c1bd12 Guido Trotter
    except EnvironmentError, err:
75 d4c1bd12 Guido Trotter
      raise errors.ConfigurationError("Cannot stat config file %s: %s" %
76 d4c1bd12 Guido Trotter
                                      (self._file_name, err))
77 7bcc78e4 Guido Trotter
    inode = cfg_stat.st_ino
78 7bcc78e4 Guido Trotter
    mtime = cfg_stat.st_mtime
79 7bcc78e4 Guido Trotter
    size = cfg_stat.st_size
80 7bcc78e4 Guido Trotter
81 7bcc78e4 Guido Trotter
    reload = False
82 7bcc78e4 Guido Trotter
    if force or inode != self._last_inode or \
83 7bcc78e4 Guido Trotter
       mtime > self._last_mtime or \
84 7bcc78e4 Guido Trotter
       size != self._last_size:
85 7bcc78e4 Guido Trotter
      self._last_inode = inode
86 7bcc78e4 Guido Trotter
      self._last_mtime = mtime
87 7bcc78e4 Guido Trotter
      self._last_size = size
88 7bcc78e4 Guido Trotter
      reload = True
89 7bcc78e4 Guido Trotter
90 7bcc78e4 Guido Trotter
    if not reload:
91 7bcc78e4 Guido Trotter
      return False
92 7bcc78e4 Guido Trotter
93 01cf7dbe Guido Trotter
    try:
94 1fe93c75 Guido Trotter
      self._config_data = serializer.Load(utils.ReadFile(self._file_name))
95 d4c1bd12 Guido Trotter
    except EnvironmentError, err:
96 01cf7dbe Guido Trotter
      raise errors.ConfigurationError("Cannot read config file %s: %s" %
97 1fe93c75 Guido Trotter
                                      (self._file_name, err))
98 01cf7dbe Guido Trotter
    except ValueError, err:
99 01cf7dbe Guido Trotter
      raise errors.ConfigurationError("Cannot load config file %s: %s" %
100 1fe93c75 Guido Trotter
                                      (self._file_name, err))
101 856c67e1 Michael Hanselmann
102 ae130c81 Guido Trotter
    self._ip_to_instance = {}
103 ae130c81 Guido Trotter
    for iname in self._config_data['instances']:
104 ae130c81 Guido Trotter
      instance = self._config_data['instances'][iname]
105 ae130c81 Guido Trotter
      for nic in instance['nics']:
106 ae130c81 Guido Trotter
        if 'ip' in nic and nic['ip']:
107 ae130c81 Guido Trotter
          self._ip_to_instance[nic['ip']] = iname
108 ae130c81 Guido Trotter
109 efbb4fd2 Luca Bigliardi
    self._nodes_primary_ips = []
110 efbb4fd2 Luca Bigliardi
    self._mc_primary_ips = []
111 efbb4fd2 Luca Bigliardi
    for node_name in self._config_data["nodes"]:
112 efbb4fd2 Luca Bigliardi
      node = self._config_data["nodes"][node_name]
113 efbb4fd2 Luca Bigliardi
      self._nodes_primary_ips.append(node["primary_ip"])
114 efbb4fd2 Luca Bigliardi
      if node["master_candidate"]:
115 efbb4fd2 Luca Bigliardi
        self._mc_primary_ips.append(node["primary_ip"])
116 efbb4fd2 Luca Bigliardi
117 7bcc78e4 Guido Trotter
    return True
118 7bcc78e4 Guido Trotter
119 ad8b2f9b Guido Trotter
  # Clients can request a reload of the config file, so we export our internal
120 ad8b2f9b Guido Trotter
  # _Load function as Reload.
121 ad8b2f9b Guido Trotter
  Reload = _Load
122 ad8b2f9b Guido Trotter
123 856c67e1 Michael Hanselmann
  def GetClusterName(self):
124 856c67e1 Michael Hanselmann
    return self._config_data["cluster"]["cluster_name"]
125 856c67e1 Michael Hanselmann
126 856c67e1 Michael Hanselmann
  def GetHostKey(self):
127 856c67e1 Michael Hanselmann
    return self._config_data["cluster"]["rsahostkeypub"]
128 856c67e1 Michael Hanselmann
129 856c67e1 Michael Hanselmann
  def GetMasterNode(self):
130 856c67e1 Michael Hanselmann
    return self._config_data["cluster"]["master_node"]
131 856c67e1 Michael Hanselmann
132 856c67e1 Michael Hanselmann
  def GetMasterIP(self):
133 856c67e1 Michael Hanselmann
    return self._config_data["cluster"]["master_ip"]
134 856c67e1 Michael Hanselmann
135 856c67e1 Michael Hanselmann
  def GetMasterNetdev(self):
136 856c67e1 Michael Hanselmann
    return self._config_data["cluster"]["master_netdev"]
137 856c67e1 Michael Hanselmann
138 856c67e1 Michael Hanselmann
  def GetFileStorageDir(self):
139 856c67e1 Michael Hanselmann
    return self._config_data["cluster"]["file_storage_dir"]
140 856c67e1 Michael Hanselmann
141 856c67e1 Michael Hanselmann
  def GetNodeList(self):
142 856c67e1 Michael Hanselmann
    return self._config_data["nodes"].keys()
143 856c67e1 Michael Hanselmann
144 a0c26bdb Guido Trotter
  def GetConfigSerialNo(self):
145 a0c26bdb Guido Trotter
    return self._config_data["serial_no"]
146 a0c26bdb Guido Trotter
147 a0c26bdb Guido Trotter
  def GetClusterSerialNo(self):
148 a0c26bdb Guido Trotter
    return self._config_data["cluster"]["serial_no"]
149 a0c26bdb Guido Trotter
150 e843991b Guido Trotter
  def GetNodeStatusFlags(self, node):
151 e843991b Guido Trotter
    """Get a node's status flags
152 e843991b Guido Trotter

153 e843991b Guido Trotter
    @type node: string
154 e843991b Guido Trotter
    @param node: node name
155 e843991b Guido Trotter
    @rtype: (bool, bool, bool)
156 e843991b Guido Trotter
    @return: (master_candidate, drained, offline) (or None if no such node)
157 e843991b Guido Trotter

158 e843991b Guido Trotter
    """
159 e843991b Guido Trotter
    if node not in self._config_data["nodes"]:
160 e843991b Guido Trotter
      return None
161 e843991b Guido Trotter
162 e843991b Guido Trotter
    master_candidate = self._config_data["nodes"][node]["master_candidate"]
163 e843991b Guido Trotter
    drained = self._config_data["nodes"][node]["drained"]
164 e843991b Guido Trotter
    offline = self._config_data["nodes"][node]["offline"]
165 e843991b Guido Trotter
    return master_candidate, drained, offline
166 e843991b Guido Trotter
167 ae130c81 Guido Trotter
  def GetInstanceByIp(self, ip):
168 ae130c81 Guido Trotter
    if ip not in self._ip_to_instance:
169 ae130c81 Guido Trotter
      return None
170 ae130c81 Guido Trotter
    return self._ip_to_instance[ip]
171 ae130c81 Guido Trotter
172 ae130c81 Guido Trotter
  def GetNodePrimaryIp(self, node):
173 ae130c81 Guido Trotter
    """Get a node's primary ip
174 ae130c81 Guido Trotter

175 ae130c81 Guido Trotter
    @type node: string
176 ae130c81 Guido Trotter
    @param node: node name
177 ae130c81 Guido Trotter
    @rtype: string, or None
178 ae130c81 Guido Trotter
    @return: node's primary ip, or None if no such node
179 ae130c81 Guido Trotter

180 ae130c81 Guido Trotter
    """
181 ae130c81 Guido Trotter
    if node not in self._config_data["nodes"]:
182 ae130c81 Guido Trotter
      return None
183 ae130c81 Guido Trotter
    return self._config_data["nodes"][node]["primary_ip"]
184 ae130c81 Guido Trotter
185 ae130c81 Guido Trotter
  def GetInstancePrimaryNode(self, instance):
186 ae130c81 Guido Trotter
    """Get an instance's primary node
187 ae130c81 Guido Trotter

188 ae130c81 Guido Trotter
    @type instance: string
189 ae130c81 Guido Trotter
    @param instance: instance name
190 ae130c81 Guido Trotter
    @rtype: string, or None
191 ae130c81 Guido Trotter
    @return: primary node, or None if no such instance
192 ae130c81 Guido Trotter

193 ae130c81 Guido Trotter
    """
194 ae130c81 Guido Trotter
    if instance not in self._config_data["instances"]:
195 ae130c81 Guido Trotter
      return None
196 ae130c81 Guido Trotter
    return self._config_data["instances"][instance]["primary_node"]
197 ae130c81 Guido Trotter
198 efbb4fd2 Luca Bigliardi
  def GetNodesPrimaryIps(self):
199 efbb4fd2 Luca Bigliardi
    return self._nodes_primary_ips
200 efbb4fd2 Luca Bigliardi
201 efbb4fd2 Luca Bigliardi
  def GetMasterCandidatesPrimaryIps(self):
202 efbb4fd2 Luca Bigliardi
    return self._mc_primary_ips
203 efbb4fd2 Luca Bigliardi
204 856c67e1 Michael Hanselmann
205 93384844 Iustin Pop
class SimpleStore(object):
206 93384844 Iustin Pop
  """Interface to static cluster data.
207 93384844 Iustin Pop

208 93384844 Iustin Pop
  This is different that the config.ConfigWriter and
209 93384844 Iustin Pop
  SimpleConfigReader classes in that it holds data that will always be
210 93384844 Iustin Pop
  present, even on nodes which don't have all the cluster data.
211 93384844 Iustin Pop

212 93384844 Iustin Pop
  Other particularities of the datastore:
213 93384844 Iustin Pop
    - keys are restricted to predefined values
214 93384844 Iustin Pop

215 93384844 Iustin Pop
  """
216 93384844 Iustin Pop
  _SS_FILEPREFIX = "ssconf_"
217 93384844 Iustin Pop
  _VALID_KEYS = (
218 93384844 Iustin Pop
    constants.SS_CLUSTER_NAME,
219 5d60b3bd Iustin Pop
    constants.SS_CLUSTER_TAGS,
220 93384844 Iustin Pop
    constants.SS_FILE_STORAGE_DIR,
221 f56618e0 Iustin Pop
    constants.SS_MASTER_CANDIDATES,
222 8113a52e Luca Bigliardi
    constants.SS_MASTER_CANDIDATES_IPS,
223 93384844 Iustin Pop
    constants.SS_MASTER_IP,
224 93384844 Iustin Pop
    constants.SS_MASTER_NETDEV,
225 93384844 Iustin Pop
    constants.SS_MASTER_NODE,
226 93384844 Iustin Pop
    constants.SS_NODE_LIST,
227 f9780ccd Luca Bigliardi
    constants.SS_NODE_PRIMARY_IPS,
228 f9780ccd Luca Bigliardi
    constants.SS_NODE_SECONDARY_IPS,
229 a3316e4a Iustin Pop
    constants.SS_OFFLINE_NODES,
230 81a49123 Iustin Pop
    constants.SS_ONLINE_NODES,
231 81a49123 Iustin Pop
    constants.SS_INSTANCE_LIST,
232 8a113c7a Iustin Pop
    constants.SS_RELEASE_VERSION,
233 93384844 Iustin Pop
    )
234 93384844 Iustin Pop
  _MAX_SIZE = 131072
235 93384844 Iustin Pop
236 93384844 Iustin Pop
  def __init__(self, cfg_location=None):
237 93384844 Iustin Pop
    if cfg_location is None:
238 93384844 Iustin Pop
      self._cfg_dir = constants.DATA_DIR
239 93384844 Iustin Pop
    else:
240 93384844 Iustin Pop
      self._cfg_dir = cfg_location
241 93384844 Iustin Pop
242 93384844 Iustin Pop
  def KeyToFilename(self, key):
243 93384844 Iustin Pop
    """Convert a given key into filename.
244 93384844 Iustin Pop

245 93384844 Iustin Pop
    """
246 93384844 Iustin Pop
    if key not in self._VALID_KEYS:
247 93384844 Iustin Pop
      raise errors.ProgrammerError("Invalid key requested from SSConf: '%s'"
248 93384844 Iustin Pop
                                   % str(key))
249 93384844 Iustin Pop
250 93384844 Iustin Pop
    filename = self._cfg_dir + '/' + self._SS_FILEPREFIX + key
251 93384844 Iustin Pop
    return filename
252 93384844 Iustin Pop
253 93384844 Iustin Pop
  def _ReadFile(self, key):
254 93384844 Iustin Pop
    """Generic routine to read keys.
255 93384844 Iustin Pop

256 93384844 Iustin Pop
    This will read the file which holds the value requested. Errors
257 93384844 Iustin Pop
    will be changed into ConfigurationErrors.
258 93384844 Iustin Pop

259 93384844 Iustin Pop
    """
260 93384844 Iustin Pop
    filename = self.KeyToFilename(key)
261 93384844 Iustin Pop
    try:
262 920b5878 Guido Trotter
      data = utils.ReadFile(filename, size=self._MAX_SIZE)
263 93384844 Iustin Pop
    except EnvironmentError, err:
264 93384844 Iustin Pop
      raise errors.ConfigurationError("Can't read from the ssconf file:"
265 93384844 Iustin Pop
                                      " '%s'" % str(err))
266 920b5878 Guido Trotter
    data = data.rstrip('\n')
267 93384844 Iustin Pop
    return data
268 93384844 Iustin Pop
269 89b14f05 Iustin Pop
  def WriteFiles(self, values):
270 89b14f05 Iustin Pop
    """Writes ssconf files used by external scripts.
271 89b14f05 Iustin Pop

272 89b14f05 Iustin Pop
    @type values: dict
273 89b14f05 Iustin Pop
    @param values: Dictionary of (name, value)
274 89b14f05 Iustin Pop

275 89b14f05 Iustin Pop
    """
276 89b14f05 Iustin Pop
    ssconf_lock = utils.FileLock(constants.SSCONF_LOCK_FILE)
277 89b14f05 Iustin Pop
278 89b14f05 Iustin Pop
    # Get lock while writing files
279 89b14f05 Iustin Pop
    ssconf_lock.Exclusive(blocking=True, timeout=SSCONF_LOCK_TIMEOUT)
280 89b14f05 Iustin Pop
    try:
281 89b14f05 Iustin Pop
      for name, value in values.iteritems():
282 02b31f32 Iustin Pop
        if value and not value.endswith("\n"):
283 89b14f05 Iustin Pop
          value += "\n"
284 81a49123 Iustin Pop
        utils.WriteFile(self.KeyToFilename(name), data=value, mode=0444)
285 89b14f05 Iustin Pop
    finally:
286 89b14f05 Iustin Pop
      ssconf_lock.Unlock()
287 89b14f05 Iustin Pop
288 93384844 Iustin Pop
  def GetFileList(self):
289 93384844 Iustin Pop
    """Return the list of all config files.
290 93384844 Iustin Pop

291 93384844 Iustin Pop
    This is used for computing node replication data.
292 93384844 Iustin Pop

293 93384844 Iustin Pop
    """
294 93384844 Iustin Pop
    return [self.KeyToFilename(key) for key in self._VALID_KEYS]
295 93384844 Iustin Pop
296 93384844 Iustin Pop
  def GetClusterName(self):
297 93384844 Iustin Pop
    """Get the cluster name.
298 93384844 Iustin Pop

299 93384844 Iustin Pop
    """
300 93384844 Iustin Pop
    return self._ReadFile(constants.SS_CLUSTER_NAME)
301 93384844 Iustin Pop
302 93384844 Iustin Pop
  def GetFileStorageDir(self):
303 93384844 Iustin Pop
    """Get the file storage dir.
304 93384844 Iustin Pop

305 93384844 Iustin Pop
    """
306 93384844 Iustin Pop
    return self._ReadFile(constants.SS_FILE_STORAGE_DIR)
307 93384844 Iustin Pop
308 f56618e0 Iustin Pop
  def GetMasterCandidates(self):
309 f56618e0 Iustin Pop
    """Return the list of master candidates.
310 f56618e0 Iustin Pop

311 f56618e0 Iustin Pop
    """
312 f56618e0 Iustin Pop
    data = self._ReadFile(constants.SS_MASTER_CANDIDATES)
313 f56618e0 Iustin Pop
    nl = data.splitlines(False)
314 f56618e0 Iustin Pop
    return nl
315 f56618e0 Iustin Pop
316 8113a52e Luca Bigliardi
  def GetMasterCandidatesIPList(self):
317 8113a52e Luca Bigliardi
    """Return the list of master candidates' primary IP.
318 8113a52e Luca Bigliardi

319 8113a52e Luca Bigliardi
    """
320 8113a52e Luca Bigliardi
    data = self._ReadFile(constants.SS_MASTER_CANDIDATES_IPS)
321 8113a52e Luca Bigliardi
    nl = data.splitlines(False)
322 8113a52e Luca Bigliardi
    return nl
323 8113a52e Luca Bigliardi
324 93384844 Iustin Pop
  def GetMasterIP(self):
325 93384844 Iustin Pop
    """Get the IP of the master node for this cluster.
326 93384844 Iustin Pop

327 93384844 Iustin Pop
    """
328 93384844 Iustin Pop
    return self._ReadFile(constants.SS_MASTER_IP)
329 93384844 Iustin Pop
330 93384844 Iustin Pop
  def GetMasterNetdev(self):
331 93384844 Iustin Pop
    """Get the netdev to which we'll add the master ip.
332 93384844 Iustin Pop

333 93384844 Iustin Pop
    """
334 93384844 Iustin Pop
    return self._ReadFile(constants.SS_MASTER_NETDEV)
335 93384844 Iustin Pop
336 93384844 Iustin Pop
  def GetMasterNode(self):
337 93384844 Iustin Pop
    """Get the hostname of the master node for this cluster.
338 93384844 Iustin Pop

339 93384844 Iustin Pop
    """
340 93384844 Iustin Pop
    return self._ReadFile(constants.SS_MASTER_NODE)
341 93384844 Iustin Pop
342 93384844 Iustin Pop
  def GetNodeList(self):
343 93384844 Iustin Pop
    """Return the list of cluster nodes.
344 93384844 Iustin Pop

345 93384844 Iustin Pop
    """
346 93384844 Iustin Pop
    data = self._ReadFile(constants.SS_NODE_LIST)
347 93384844 Iustin Pop
    nl = data.splitlines(False)
348 93384844 Iustin Pop
    return nl
349 93384844 Iustin Pop
350 f9780ccd Luca Bigliardi
  def GetNodePrimaryIPList(self):
351 f9780ccd Luca Bigliardi
    """Return the list of cluster nodes' primary IP.
352 f9780ccd Luca Bigliardi

353 f9780ccd Luca Bigliardi
    """
354 f9780ccd Luca Bigliardi
    data = self._ReadFile(constants.SS_NODE_PRIMARY_IPS)
355 f9780ccd Luca Bigliardi
    nl = data.splitlines(False)
356 f9780ccd Luca Bigliardi
    return nl
357 f9780ccd Luca Bigliardi
358 f9780ccd Luca Bigliardi
  def GetNodeSecondaryIPList(self):
359 f9780ccd Luca Bigliardi
    """Return the list of cluster nodes' secondary IP.
360 f9780ccd Luca Bigliardi

361 f9780ccd Luca Bigliardi
    """
362 f9780ccd Luca Bigliardi
    data = self._ReadFile(constants.SS_NODE_SECONDARY_IPS)
363 f9780ccd Luca Bigliardi
    nl = data.splitlines(False)
364 f9780ccd Luca Bigliardi
    return nl
365 f9780ccd Luca Bigliardi
366 25e39bfa Iustin Pop
  def GetClusterTags(self):
367 25e39bfa Iustin Pop
    """Return the cluster tags.
368 25e39bfa Iustin Pop

369 25e39bfa Iustin Pop
    """
370 25e39bfa Iustin Pop
    data = self._ReadFile(constants.SS_CLUSTER_TAGS)
371 25e39bfa Iustin Pop
    nl = data.splitlines(False)
372 25e39bfa Iustin Pop
    return nl
373 25e39bfa Iustin Pop
374 93384844 Iustin Pop
375 b33e986b Iustin Pop
def GetMasterAndMyself(ss=None):
376 b33e986b Iustin Pop
  """Get the master node and my own hostname.
377 b33e986b Iustin Pop

378 b33e986b Iustin Pop
  This can be either used for a 'soft' check (compared to CheckMaster,
379 b33e986b Iustin Pop
  which exits) or just for computing both at the same time.
380 b33e986b Iustin Pop

381 b33e986b Iustin Pop
  The function does not handle any errors, these should be handled in
382 b33e986b Iustin Pop
  the caller (errors.ConfigurationError, errors.ResolverError).
383 b33e986b Iustin Pop

384 8135a2db Iustin Pop
  @param ss: either a sstore.SimpleConfigReader or a
385 8135a2db Iustin Pop
      sstore.SimpleStore instance
386 8135a2db Iustin Pop
  @rtype: tuple
387 8135a2db Iustin Pop
  @return: a tuple (master node name, my own name)
388 8135a2db Iustin Pop

389 b33e986b Iustin Pop
  """
390 b33e986b Iustin Pop
  if ss is None:
391 93384844 Iustin Pop
    ss = SimpleStore()
392 b33e986b Iustin Pop
  return ss.GetMasterNode(), utils.HostInfo().name
393 b33e986b Iustin Pop
394 06dc5b44 Iustin Pop
395 b33e986b Iustin Pop
def CheckMaster(debug, ss=None):
396 5675cd1f Iustin Pop
  """Checks the node setup.
397 5675cd1f Iustin Pop

398 5675cd1f Iustin Pop
  If this is the master, the function will return. Otherwise it will
399 5675cd1f Iustin Pop
  exit with an exit code based on the node status.
400 5675cd1f Iustin Pop

401 5675cd1f Iustin Pop
  """
402 5675cd1f Iustin Pop
  try:
403 b33e986b Iustin Pop
    master_name, myself = GetMasterAndMyself(ss)
404 5675cd1f Iustin Pop
  except errors.ConfigurationError, err:
405 5675cd1f Iustin Pop
    print "Cluster configuration incomplete: '%s'" % str(err)
406 5675cd1f Iustin Pop
    sys.exit(constants.EXIT_NODESETUP_ERROR)
407 5675cd1f Iustin Pop
  except errors.ResolverError, err:
408 5675cd1f Iustin Pop
    sys.stderr.write("Cannot resolve my own name (%s)\n" % err.args[0])
409 5675cd1f Iustin Pop
    sys.exit(constants.EXIT_NODESETUP_ERROR)
410 5675cd1f Iustin Pop
411 b33e986b Iustin Pop
  if myself != master_name:
412 5675cd1f Iustin Pop
    if debug:
413 5675cd1f Iustin Pop
      sys.stderr.write("Not master, exiting.\n")
414 5675cd1f Iustin Pop
    sys.exit(constants.EXIT_NOTMASTER)
415 3f71b464 Guido Trotter
416 3f71b464 Guido Trotter
417 3f71b464 Guido Trotter
def CheckMasterCandidate(debug, ss=None):
418 3f71b464 Guido Trotter
  """Checks the node setup.
419 3f71b464 Guido Trotter

420 3f71b464 Guido Trotter
  If this is a master candidate, the function will return. Otherwise it will
421 3f71b464 Guido Trotter
  exit with an exit code based on the node status.
422 3f71b464 Guido Trotter

423 3f71b464 Guido Trotter
  """
424 3f71b464 Guido Trotter
  try:
425 3f71b464 Guido Trotter
    if ss is None:
426 3f71b464 Guido Trotter
      ss = SimpleStore()
427 3f71b464 Guido Trotter
    myself = utils.HostInfo().name
428 3f71b464 Guido Trotter
    candidates = ss.GetMasterCandidates()
429 3f71b464 Guido Trotter
  except errors.ConfigurationError, err:
430 3f71b464 Guido Trotter
    print "Cluster configuration incomplete: '%s'" % str(err)
431 3f71b464 Guido Trotter
    sys.exit(constants.EXIT_NODESETUP_ERROR)
432 3f71b464 Guido Trotter
  except errors.ResolverError, err:
433 3f71b464 Guido Trotter
    sys.stderr.write("Cannot resolve my own name (%s)\n" % err.args[0])
434 3f71b464 Guido Trotter
    sys.exit(constants.EXIT_NODESETUP_ERROR)
435 3f71b464 Guido Trotter
436 3f71b464 Guido Trotter
  if myself not in candidates:
437 3f71b464 Guido Trotter
    if debug:
438 3f71b464 Guido Trotter
      sys.stderr.write("Not master candidate, exiting.\n")
439 3f71b464 Guido Trotter
    sys.exit(constants.EXIT_NOTCANDIDATE)