Statistics
| Branch: | Tag: | Revision:

root / lib / ssconf.py @ 0c223ea9

History | View | Annotate | Download (4.9 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

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

    
36

    
37
SSCONF_LOCK_TIMEOUT = 10
38

    
39

    
40
class SimpleConfigReader(object):
41
  """Simple class to read configuration file.
42

43
  """
44
  def __init__(self, file_name=constants.CLUSTER_CONF_FILE):
45
    """Initializes this class.
46

47
    @type file_name: string
48
    @param file_name: Configuration file path
49

50
    """
51
    self._file_name = file_name
52
    self._config_data = serializer.Load(utils.ReadFile(file_name))
53
    # TODO: Error handling
54

    
55
  def GetClusterName(self):
56
    return self._config_data["cluster"]["cluster_name"]
57

    
58
  def GetHostKey(self):
59
    return self._config_data["cluster"]["rsahostkeypub"]
60

    
61
  def GetMasterNode(self):
62
    return self._config_data["cluster"]["master_node"]
63

    
64
  def GetMasterIP(self):
65
    return self._config_data["cluster"]["master_ip"]
66

    
67
  def GetMasterNetdev(self):
68
    return self._config_data["cluster"]["master_netdev"]
69

    
70
  def GetFileStorageDir(self):
71
    return self._config_data["cluster"]["file_storage_dir"]
72

    
73
  def GetHypervisorType(self):
74
    return self._config_data["cluster"]["hypervisor"]
75

    
76
  def GetNodeList(self):
77
    return self._config_data["nodes"].keys()
78

    
79
  @classmethod
80
  def FromDict(cls, val, cfg_file=constants.CLUSTER_CONF_FILE):
81
    """Alternative construction from a dictionary.
82

83
    """
84
    obj = SimpleConfigReader.__new__(cls)
85
    obj._config_data = val
86
    obj._file_name = cfg_file
87
    return obj
88

    
89

    
90
class SimpleConfigWriter(SimpleConfigReader):
91
  """Simple class to write configuration file.
92

93
  """
94
  def SetMasterNode(self, node):
95
    """Change master node.
96

97
    """
98
    self._config_data["cluster"]["master_node"] = node
99

    
100
  def Save(self):
101
    """Writes configuration file.
102

103
    Warning: Doesn't take care of locking or synchronizing with other
104
    processes.
105

106
    """
107
    utils.WriteFile(self._file_name,
108
                    data=serializer.Dump(self._config_data),
109
                    mode=0600)
110

    
111

    
112
def _SsconfPath(name):
113
  return "%s/ssconf_%s" % (constants.DATA_DIR, name)
114

    
115

    
116
def WriteSsconfFiles(file_name):
117
  """Writes legacy ssconf files to be used by external scripts.
118

119
  @type file_name: string
120
  @param file_name: Path to configuration file
121

122
  """
123
  ssconf_lock = utils.FileLock(constants.SSCONF_LOCK_FILE)
124

    
125
  # Read config
126
  cfg = SimpleConfigReader(file_name=file_name)
127

    
128
  # Get lock while writing files
129
  ssconf_lock.Exclusive(blocking=True, timeout=SSCONF_LOCK_TIMEOUT)
130
  try:
131
    utils.WriteFile(_SsconfPath("cluster_name"),
132
                    data="%s\n" % cfg.GetClusterName())
133

    
134
    utils.WriteFile(_SsconfPath("master_ip"),
135
                    data="%s\n" % cfg.GetMasterIP())
136

    
137
    utils.WriteFile(_SsconfPath("master_netdev"),
138
                    data="%s\n" % cfg.GetMasterNetdev())
139

    
140
    utils.WriteFile(_SsconfPath("master_node"),
141
                    data="%s\n" % cfg.GetMasterNode())
142
  finally:
143
    ssconf_lock.Unlock()
144

    
145

    
146
def GetMasterAndMyself(ss=None):
147
  """Get the master node and my own hostname.
148

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

152
  The function does not handle any errors, these should be handled in
153
  the caller (errors.ConfigurationError, errors.ResolverError).
154

155
  """
156
  if ss is None:
157
    ss = SimpleConfigReader()
158
  return ss.GetMasterNode(), utils.HostInfo().name
159

    
160

    
161
def CheckMaster(debug, ss=None):
162
  """Checks the node setup.
163

164
  If this is the master, the function will return. Otherwise it will
165
  exit with an exit code based on the node status.
166

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

    
177
  if myself != master_name:
178
    if debug:
179
      sys.stderr.write("Not master, exiting.\n")
180
    sys.exit(constants.EXIT_NOTMASTER)