Statistics
| Branch: | Tag: | Revision:

root / lib / ssconf.py @ 03d1dba2

History | View | Annotate | Download (4.7 kB)

1
#
2
#
3

    
4
# Copyright (C) 2006, 2007, 2008 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
"""Global Configuration data for Ganeti.
23

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

27
"""
28

    
29
import sys
30
import re
31

    
32
from ganeti import errors
33
from ganeti import constants
34
from ganeti import utils
35
from ganeti import serializer
36

    
37

    
38
SSCONF_LOCK_TIMEOUT = 10
39

    
40
RE_VALID_SSCONF_NAME = re.compile(r'^[-_a-z0-9]+$')
41

    
42

    
43
class SimpleConfigReader(object):
44
  """Simple class to read configuration file.
45

46
  """
47
  def __init__(self, file_name=constants.CLUSTER_CONF_FILE):
48
    """Initializes this class.
49

50
    @type file_name: string
51
    @param file_name: Configuration file path
52

53
    """
54
    self._file_name = file_name
55
    self._config_data = serializer.Load(utils.ReadFile(file_name))
56
    # TODO: Error handling
57

    
58
  def GetClusterName(self):
59
    return self._config_data["cluster"]["cluster_name"]
60

    
61
  def GetHostKey(self):
62
    return self._config_data["cluster"]["rsahostkeypub"]
63

    
64
  def GetMasterNode(self):
65
    return self._config_data["cluster"]["master_node"]
66

    
67
  def GetMasterIP(self):
68
    return self._config_data["cluster"]["master_ip"]
69

    
70
  def GetMasterNetdev(self):
71
    return self._config_data["cluster"]["master_netdev"]
72

    
73
  def GetFileStorageDir(self):
74
    return self._config_data["cluster"]["file_storage_dir"]
75

    
76
  def GetHypervisorType(self):
77
    return self._config_data["cluster"]["hypervisor"]
78

    
79
  def GetNodeList(self):
80
    return self._config_data["nodes"].keys()
81

    
82
  @classmethod
83
  def FromDict(cls, val, cfg_file=constants.CLUSTER_CONF_FILE):
84
    """Alternative construction from a dictionary.
85

86
    """
87
    obj = SimpleConfigReader.__new__(cls)
88
    obj._config_data = val
89
    obj._file_name = cfg_file
90
    return obj
91

    
92

    
93
class SimpleConfigWriter(SimpleConfigReader):
94
  """Simple class to write configuration file.
95

96
  """
97
  def SetMasterNode(self, node):
98
    """Change master node.
99

100
    """
101
    self._config_data["cluster"]["master_node"] = node
102

    
103
  def Save(self):
104
    """Writes configuration file.
105

106
    Warning: Doesn't take care of locking or synchronizing with other
107
    processes.
108

109
    """
110
    utils.WriteFile(self._file_name,
111
                    data=serializer.Dump(self._config_data),
112
                    mode=0600)
113

    
114

    
115
def _SsconfPath(name):
116
  if not RE_VALID_SSCONF_NAME.match(name):
117
    raise errors.ParameterError("Invalid ssconf name: %s" % name)
118
  return "%s/ssconf_%s" % (constants.DATA_DIR, name)
119

    
120

    
121
def WriteSsconfFiles(values):
122
  """Writes legacy ssconf files to be used by external scripts.
123

124
  @type values: dict
125
  @param values: Dictionary of (name, value)
126

127
  """
128
  ssconf_lock = utils.FileLock(constants.SSCONF_LOCK_FILE)
129

    
130
  # Get lock while writing files
131
  ssconf_lock.Exclusive(blocking=True, timeout=SSCONF_LOCK_TIMEOUT)
132
  try:
133
    for name, value in values.iteritems():
134
      if not value.endswith("\n"):
135
        value += "\n"
136
      utils.WriteFile(_SsconfPath(name),
137
                      data=value)
138
  finally:
139
    ssconf_lock.Unlock()
140

    
141

    
142
def GetMasterAndMyself(ss=None):
143
  """Get the master node and my own hostname.
144

145
  This can be either used for a 'soft' check (compared to CheckMaster,
146
  which exits) or just for computing both at the same time.
147

148
  The function does not handle any errors, these should be handled in
149
  the caller (errors.ConfigurationError, errors.ResolverError).
150

151
  """
152
  if ss is None:
153
    ss = SimpleConfigReader()
154
  return ss.GetMasterNode(), utils.HostInfo().name
155

    
156

    
157
def CheckMaster(debug, ss=None):
158
  """Checks the node setup.
159

160
  If this is the master, the function will return. Otherwise it will
161
  exit with an exit code based on the node status.
162

163
  """
164
  try:
165
    master_name, myself = GetMasterAndMyself(ss)
166
  except errors.ConfigurationError, err:
167
    print "Cluster configuration incomplete: '%s'" % str(err)
168
    sys.exit(constants.EXIT_NODESETUP_ERROR)
169
  except errors.ResolverError, err:
170
    sys.stderr.write("Cannot resolve my own name (%s)\n" % err.args[0])
171
    sys.exit(constants.EXIT_NODESETUP_ERROR)
172

    
173
  if myself != master_name:
174
    if debug:
175
      sys.stderr.write("Not master, exiting.\n")
176
    sys.exit(constants.EXIT_NOTMASTER)