Statistics
| Branch: | Tag: | Revision:

root / lib / ssconf.py @ 90d726a8

History | View | Annotate | Download (12.4 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 d01ae714 Luca Bigliardi
    self._instances_ips = []
104 ae130c81 Guido Trotter
    for iname in self._config_data['instances']:
105 ae130c81 Guido Trotter
      instance = self._config_data['instances'][iname]
106 ae130c81 Guido Trotter
      for nic in instance['nics']:
107 ae130c81 Guido Trotter
        if 'ip' in nic and nic['ip']:
108 d01ae714 Luca Bigliardi
          self._instances_ips.append(nic['ip'])
109 ae130c81 Guido Trotter
          self._ip_to_instance[nic['ip']] = iname
110 ae130c81 Guido Trotter
111 efbb4fd2 Luca Bigliardi
    self._nodes_primary_ips = []
112 efbb4fd2 Luca Bigliardi
    self._mc_primary_ips = []
113 efbb4fd2 Luca Bigliardi
    for node_name in self._config_data["nodes"]:
114 efbb4fd2 Luca Bigliardi
      node = self._config_data["nodes"][node_name]
115 efbb4fd2 Luca Bigliardi
      self._nodes_primary_ips.append(node["primary_ip"])
116 efbb4fd2 Luca Bigliardi
      if node["master_candidate"]:
117 efbb4fd2 Luca Bigliardi
        self._mc_primary_ips.append(node["primary_ip"])
118 efbb4fd2 Luca Bigliardi
119 7bcc78e4 Guido Trotter
    return True
120 7bcc78e4 Guido Trotter
121 ad8b2f9b Guido Trotter
  # Clients can request a reload of the config file, so we export our internal
122 ad8b2f9b Guido Trotter
  # _Load function as Reload.
123 ad8b2f9b Guido Trotter
  Reload = _Load
124 ad8b2f9b Guido Trotter
125 856c67e1 Michael Hanselmann
  def GetClusterName(self):
126 856c67e1 Michael Hanselmann
    return self._config_data["cluster"]["cluster_name"]
127 856c67e1 Michael Hanselmann
128 856c67e1 Michael Hanselmann
  def GetHostKey(self):
129 856c67e1 Michael Hanselmann
    return self._config_data["cluster"]["rsahostkeypub"]
130 856c67e1 Michael Hanselmann
131 856c67e1 Michael Hanselmann
  def GetMasterNode(self):
132 856c67e1 Michael Hanselmann
    return self._config_data["cluster"]["master_node"]
133 856c67e1 Michael Hanselmann
134 856c67e1 Michael Hanselmann
  def GetMasterIP(self):
135 856c67e1 Michael Hanselmann
    return self._config_data["cluster"]["master_ip"]
136 856c67e1 Michael Hanselmann
137 856c67e1 Michael Hanselmann
  def GetMasterNetdev(self):
138 856c67e1 Michael Hanselmann
    return self._config_data["cluster"]["master_netdev"]
139 856c67e1 Michael Hanselmann
140 856c67e1 Michael Hanselmann
  def GetFileStorageDir(self):
141 856c67e1 Michael Hanselmann
    return self._config_data["cluster"]["file_storage_dir"]
142 856c67e1 Michael Hanselmann
143 856c67e1 Michael Hanselmann
  def GetNodeList(self):
144 856c67e1 Michael Hanselmann
    return self._config_data["nodes"].keys()
145 856c67e1 Michael Hanselmann
146 a0c26bdb Guido Trotter
  def GetConfigSerialNo(self):
147 a0c26bdb Guido Trotter
    return self._config_data["serial_no"]
148 a0c26bdb Guido Trotter
149 a0c26bdb Guido Trotter
  def GetClusterSerialNo(self):
150 a0c26bdb Guido Trotter
    return self._config_data["cluster"]["serial_no"]
151 a0c26bdb Guido Trotter
152 e843991b Guido Trotter
  def GetNodeStatusFlags(self, node):
153 e843991b Guido Trotter
    """Get a node's status flags
154 e843991b Guido Trotter

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

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

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

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

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

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

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

217 93384844 Iustin Pop
  Other particularities of the datastore:
218 93384844 Iustin Pop
    - keys are restricted to predefined values
219 93384844 Iustin Pop

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

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

261 93384844 Iustin Pop
    This will read the file which holds the value requested. Errors
262 93384844 Iustin Pop
    will be changed into ConfigurationErrors.
263 93384844 Iustin Pop

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

277 89b14f05 Iustin Pop
    @type values: dict
278 89b14f05 Iustin Pop
    @param values: Dictionary of (name, value)
279 89b14f05 Iustin Pop

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

296 93384844 Iustin Pop
    This is used for computing node replication data.
297 93384844 Iustin Pop

298 93384844 Iustin Pop
    """
299 93384844 Iustin Pop
    return [self.KeyToFilename(key) for key in self._VALID_KEYS]
300 93384844 Iustin Pop
301 93384844 Iustin Pop
  def GetClusterName(self):
302 93384844 Iustin Pop
    """Get the cluster name.
303 93384844 Iustin Pop

304 93384844 Iustin Pop
    """
305 93384844 Iustin Pop
    return self._ReadFile(constants.SS_CLUSTER_NAME)
306 93384844 Iustin Pop
307 93384844 Iustin Pop
  def GetFileStorageDir(self):
308 93384844 Iustin Pop
    """Get the file storage dir.
309 93384844 Iustin Pop

310 93384844 Iustin Pop
    """
311 93384844 Iustin Pop
    return self._ReadFile(constants.SS_FILE_STORAGE_DIR)
312 93384844 Iustin Pop
313 f56618e0 Iustin Pop
  def GetMasterCandidates(self):
314 f56618e0 Iustin Pop
    """Return the list of master candidates.
315 f56618e0 Iustin Pop

316 f56618e0 Iustin Pop
    """
317 f56618e0 Iustin Pop
    data = self._ReadFile(constants.SS_MASTER_CANDIDATES)
318 f56618e0 Iustin Pop
    nl = data.splitlines(False)
319 f56618e0 Iustin Pop
    return nl
320 f56618e0 Iustin Pop
321 8113a52e Luca Bigliardi
  def GetMasterCandidatesIPList(self):
322 8113a52e Luca Bigliardi
    """Return the list of master candidates' primary IP.
323 8113a52e Luca Bigliardi

324 8113a52e Luca Bigliardi
    """
325 8113a52e Luca Bigliardi
    data = self._ReadFile(constants.SS_MASTER_CANDIDATES_IPS)
326 8113a52e Luca Bigliardi
    nl = data.splitlines(False)
327 8113a52e Luca Bigliardi
    return nl
328 8113a52e Luca Bigliardi
329 93384844 Iustin Pop
  def GetMasterIP(self):
330 93384844 Iustin Pop
    """Get the IP of the master node for this cluster.
331 93384844 Iustin Pop

332 93384844 Iustin Pop
    """
333 93384844 Iustin Pop
    return self._ReadFile(constants.SS_MASTER_IP)
334 93384844 Iustin Pop
335 93384844 Iustin Pop
  def GetMasterNetdev(self):
336 93384844 Iustin Pop
    """Get the netdev to which we'll add the master ip.
337 93384844 Iustin Pop

338 93384844 Iustin Pop
    """
339 93384844 Iustin Pop
    return self._ReadFile(constants.SS_MASTER_NETDEV)
340 93384844 Iustin Pop
341 93384844 Iustin Pop
  def GetMasterNode(self):
342 93384844 Iustin Pop
    """Get the hostname of the master node for this cluster.
343 93384844 Iustin Pop

344 93384844 Iustin Pop
    """
345 93384844 Iustin Pop
    return self._ReadFile(constants.SS_MASTER_NODE)
346 93384844 Iustin Pop
347 93384844 Iustin Pop
  def GetNodeList(self):
348 93384844 Iustin Pop
    """Return the list of cluster nodes.
349 93384844 Iustin Pop

350 93384844 Iustin Pop
    """
351 93384844 Iustin Pop
    data = self._ReadFile(constants.SS_NODE_LIST)
352 93384844 Iustin Pop
    nl = data.splitlines(False)
353 93384844 Iustin Pop
    return nl
354 93384844 Iustin Pop
355 f9780ccd Luca Bigliardi
  def GetNodePrimaryIPList(self):
356 f9780ccd Luca Bigliardi
    """Return the list of cluster nodes' primary IP.
357 f9780ccd Luca Bigliardi

358 f9780ccd Luca Bigliardi
    """
359 f9780ccd Luca Bigliardi
    data = self._ReadFile(constants.SS_NODE_PRIMARY_IPS)
360 f9780ccd Luca Bigliardi
    nl = data.splitlines(False)
361 f9780ccd Luca Bigliardi
    return nl
362 f9780ccd Luca Bigliardi
363 f9780ccd Luca Bigliardi
  def GetNodeSecondaryIPList(self):
364 f9780ccd Luca Bigliardi
    """Return the list of cluster nodes' secondary IP.
365 f9780ccd Luca Bigliardi

366 f9780ccd Luca Bigliardi
    """
367 f9780ccd Luca Bigliardi
    data = self._ReadFile(constants.SS_NODE_SECONDARY_IPS)
368 f9780ccd Luca Bigliardi
    nl = data.splitlines(False)
369 f9780ccd Luca Bigliardi
    return nl
370 f9780ccd Luca Bigliardi
371 25e39bfa Iustin Pop
  def GetClusterTags(self):
372 25e39bfa Iustin Pop
    """Return the cluster tags.
373 25e39bfa Iustin Pop

374 25e39bfa Iustin Pop
    """
375 25e39bfa Iustin Pop
    data = self._ReadFile(constants.SS_CLUSTER_TAGS)
376 25e39bfa Iustin Pop
    nl = data.splitlines(False)
377 25e39bfa Iustin Pop
    return nl
378 25e39bfa Iustin Pop
379 93384844 Iustin Pop
380 b33e986b Iustin Pop
def GetMasterAndMyself(ss=None):
381 b33e986b Iustin Pop
  """Get the master node and my own hostname.
382 b33e986b Iustin Pop

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

386 b33e986b Iustin Pop
  The function does not handle any errors, these should be handled in
387 b33e986b Iustin Pop
  the caller (errors.ConfigurationError, errors.ResolverError).
388 b33e986b Iustin Pop

389 8135a2db Iustin Pop
  @param ss: either a sstore.SimpleConfigReader or a
390 8135a2db Iustin Pop
      sstore.SimpleStore instance
391 8135a2db Iustin Pop
  @rtype: tuple
392 8135a2db Iustin Pop
  @return: a tuple (master node name, my own name)
393 8135a2db Iustin Pop

394 b33e986b Iustin Pop
  """
395 b33e986b Iustin Pop
  if ss is None:
396 93384844 Iustin Pop
    ss = SimpleStore()
397 b33e986b Iustin Pop
  return ss.GetMasterNode(), utils.HostInfo().name
398 b33e986b Iustin Pop
399 06dc5b44 Iustin Pop
400 b33e986b Iustin Pop
def CheckMaster(debug, ss=None):
401 5675cd1f Iustin Pop
  """Checks the node setup.
402 5675cd1f Iustin Pop

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

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

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

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