4 # Copyright (C) 2006, 2007, 2008 Google Inc.
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.
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.
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
22 """Global Configuration data for Ganeti.
24 This module provides the interface to a special case of cluster
25 configuration data, which is mostly static and available to all nodes.
32 from ganeti import errors
33 from ganeti import constants
34 from ganeti import utils
35 from ganeti import serializer
38 SSCONF_LOCK_TIMEOUT = 10
40 RE_VALID_SSCONF_NAME = re.compile(r'^[-_a-z0-9]+$')
43 class SimpleConfigReader(object):
44 """Simple class to read configuration file.
47 def __init__(self, file_name=constants.CLUSTER_CONF_FILE):
48 """Initializes this class.
50 @type file_name: string
51 @param file_name: Configuration file path
54 self._file_name = file_name
55 self._config_data = serializer.Load(utils.ReadFile(file_name))
56 # TODO: Error handling
58 def GetClusterName(self):
59 return self._config_data["cluster"]["cluster_name"]
62 return self._config_data["cluster"]["rsahostkeypub"]
64 def GetMasterNode(self):
65 return self._config_data["cluster"]["master_node"]
67 def GetMasterIP(self):
68 return self._config_data["cluster"]["master_ip"]
70 def GetMasterNetdev(self):
71 return self._config_data["cluster"]["master_netdev"]
73 def GetFileStorageDir(self):
74 return self._config_data["cluster"]["file_storage_dir"]
76 def GetHypervisorType(self):
77 return self._config_data["cluster"]["hypervisor"]
79 def GetNodeList(self):
80 return self._config_data["nodes"].keys()
83 def FromDict(cls, val, cfg_file=constants.CLUSTER_CONF_FILE):
84 """Alternative construction from a dictionary.
87 obj = SimpleConfigReader.__new__(cls)
88 obj._config_data = val
89 obj._file_name = cfg_file
93 class SimpleConfigWriter(SimpleConfigReader):
94 """Simple class to write configuration file.
97 def SetMasterNode(self, node):
98 """Change master node.
101 self._config_data["cluster"]["master_node"] = node
104 """Writes configuration file.
106 Warning: Doesn't take care of locking or synchronizing with other
110 utils.WriteFile(self._file_name,
111 data=serializer.Dump(self._config_data),
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)
121 def WriteSsconfFiles(values):
122 """Writes legacy ssconf files to be used by external scripts.
125 @param values: Dictionary of (name, value)
128 ssconf_lock = utils.FileLock(constants.SSCONF_LOCK_FILE)
130 # Get lock while writing files
131 ssconf_lock.Exclusive(blocking=True, timeout=SSCONF_LOCK_TIMEOUT)
133 for name, value in values.iteritems():
134 if not value.endswith("\n"):
136 utils.WriteFile(_SsconfPath(name),
142 def GetMasterAndMyself(ss=None):
143 """Get the master node and my own hostname.
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.
148 The function does not handle any errors, these should be handled in
149 the caller (errors.ConfigurationError, errors.ResolverError).
153 ss = SimpleConfigReader()
154 return ss.GetMasterNode(), utils.HostInfo().name
157 def CheckMaster(debug, ss=None):
158 """Checks the node setup.
160 If this is the master, the function will return. Otherwise it will
161 exit with an exit code based on the node status.
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)
173 if myself != master_name:
175 sys.stderr.write("Not master, exiting.\n")
176 sys.exit(constants.EXIT_NOTMASTER)