Statistics
| Branch: | Tag: | Revision:

root / lib / runtime.py @ a51b19de

History | View | Annotate | Download (8.3 kB)

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

23 f12e1736 René Nussbaumer
"""
24 f12e1736 René Nussbaumer
25 f12e1736 René Nussbaumer
26 f12e1736 René Nussbaumer
import grp
27 f12e1736 René Nussbaumer
import pwd
28 f12e1736 René Nussbaumer
import threading
29 a51b19de Helga Velroyen
import os
30 a20e4768 Michael Hanselmann
import platform
31 f12e1736 René Nussbaumer
32 f12e1736 René Nussbaumer
from ganeti import constants
33 f12e1736 René Nussbaumer
from ganeti import errors
34 a51b19de Helga Velroyen
from ganeti import luxi
35 a51b19de Helga Velroyen
from ganeti import pathutils
36 a51b19de Helga Velroyen
from ganeti import ssconf
37 44fbd23b René Nussbaumer
from ganeti import utils
38 f12e1736 René Nussbaumer
39 f12e1736 René Nussbaumer
40 f12e1736 René Nussbaumer
_priv = None
41 f12e1736 René Nussbaumer
_priv_lock = threading.Lock()
42 f12e1736 René Nussbaumer
43 a20e4768 Michael Hanselmann
#: Architecture information
44 a20e4768 Michael Hanselmann
_arch = None
45 a20e4768 Michael Hanselmann
46 f12e1736 René Nussbaumer
47 f12e1736 René Nussbaumer
def GetUid(user, _getpwnam):
48 f12e1736 René Nussbaumer
  """Retrieve the uid from the database.
49 f12e1736 René Nussbaumer

50 f12e1736 René Nussbaumer
  @type user: string
51 f12e1736 René Nussbaumer
  @param user: The username to retrieve
52 f12e1736 René Nussbaumer
  @return: The resolved uid
53 f12e1736 René Nussbaumer

54 f12e1736 René Nussbaumer
  """
55 f12e1736 René Nussbaumer
  try:
56 f12e1736 René Nussbaumer
    return _getpwnam(user).pw_uid
57 f12e1736 René Nussbaumer
  except KeyError, err:
58 f12e1736 René Nussbaumer
    raise errors.ConfigurationError("User '%s' not found (%s)" % (user, err))
59 f12e1736 René Nussbaumer
60 f12e1736 René Nussbaumer
61 f12e1736 René Nussbaumer
def GetGid(group, _getgrnam):
62 f12e1736 René Nussbaumer
  """Retrieve the gid from the database.
63 f12e1736 René Nussbaumer

64 f12e1736 René Nussbaumer
  @type group: string
65 f12e1736 René Nussbaumer
  @param group: The group name to retrieve
66 f12e1736 René Nussbaumer
  @return: The resolved gid
67 f12e1736 René Nussbaumer

68 f12e1736 René Nussbaumer
  """
69 f12e1736 René Nussbaumer
  try:
70 f12e1736 René Nussbaumer
    return _getgrnam(group).gr_gid
71 f12e1736 René Nussbaumer
  except KeyError, err:
72 f12e1736 René Nussbaumer
    raise errors.ConfigurationError("Group '%s' not found (%s)" % (group, err))
73 f12e1736 René Nussbaumer
74 f12e1736 René Nussbaumer
75 f12e1736 René Nussbaumer
class GetentResolver:
76 f12e1736 René Nussbaumer
  """Resolves Ganeti uids and gids by name.
77 f12e1736 René Nussbaumer

78 f12e1736 René Nussbaumer
  @ivar masterd_uid: The resolved uid of the masterd user
79 f12e1736 René Nussbaumer
  @ivar masterd_gid: The resolved gid of the masterd group
80 f12e1736 René Nussbaumer
  @ivar confd_uid: The resolved uid of the confd user
81 f12e1736 René Nussbaumer
  @ivar confd_gid: The resolved gid of the confd group
82 3695a4e0 Thomas Thrainer
  @ivar luxid_uid: The resolved uid of the luxid user
83 3695a4e0 Thomas Thrainer
  @ivar luxid_gid: The resolved gid of the luxid group
84 f12e1736 René Nussbaumer
  @ivar rapi_uid: The resolved uid of the rapi user
85 f12e1736 René Nussbaumer
  @ivar rapi_gid: The resolved gid of the rapi group
86 f12e1736 René Nussbaumer
  @ivar noded_uid: The resolved uid of the noded user
87 f12e1736 René Nussbaumer
  @ivar daemons_gid: The resolved gid of the daemons group
88 f12e1736 René Nussbaumer
  @ivar admin_gid: The resolved gid of the admin group
89 f00170e2 Michael Hanselmann

90 f12e1736 René Nussbaumer
  """
91 f12e1736 René Nussbaumer
  def __init__(self, _getpwnam=pwd.getpwnam, _getgrnam=grp.getgrnam):
92 f12e1736 René Nussbaumer
    """Initialize the resolver.
93 f12e1736 René Nussbaumer

94 f12e1736 René Nussbaumer
    """
95 f12e1736 René Nussbaumer
    # Daemon pairs
96 f12e1736 René Nussbaumer
    self.masterd_uid = GetUid(constants.MASTERD_USER, _getpwnam)
97 f12e1736 René Nussbaumer
    self.masterd_gid = GetGid(constants.MASTERD_GROUP, _getgrnam)
98 f12e1736 René Nussbaumer
99 f12e1736 René Nussbaumer
    self.confd_uid = GetUid(constants.CONFD_USER, _getpwnam)
100 f12e1736 René Nussbaumer
    self.confd_gid = GetGid(constants.CONFD_GROUP, _getgrnam)
101 f12e1736 René Nussbaumer
102 3695a4e0 Thomas Thrainer
    self.luxid_uid = GetUid(constants.LUXID_USER, _getpwnam)
103 3695a4e0 Thomas Thrainer
    self.luxid_gid = GetGid(constants.LUXID_GROUP, _getgrnam)
104 670e954a Thomas Thrainer
105 f12e1736 René Nussbaumer
    self.rapi_uid = GetUid(constants.RAPI_USER, _getpwnam)
106 f12e1736 René Nussbaumer
    self.rapi_gid = GetGid(constants.RAPI_GROUP, _getgrnam)
107 f12e1736 René Nussbaumer
108 f12e1736 René Nussbaumer
    self.noded_uid = GetUid(constants.NODED_USER, _getpwnam)
109 44fbd23b René Nussbaumer
    self.noded_gid = GetGid(constants.NODED_GROUP, _getgrnam)
110 f12e1736 René Nussbaumer
111 d08a8359 Thomas Thrainer
    self.mond_uid = GetUid(constants.MOND_USER, _getpwnam)
112 d08a8359 Thomas Thrainer
    self.mond_gid = GetGid(constants.MOND_GROUP, _getgrnam)
113 d08a8359 Thomas Thrainer
114 f12e1736 René Nussbaumer
    # Misc Ganeti groups
115 f12e1736 René Nussbaumer
    self.daemons_gid = GetGid(constants.DAEMONS_GROUP, _getgrnam)
116 f12e1736 René Nussbaumer
    self.admin_gid = GetGid(constants.ADMIN_GROUP, _getgrnam)
117 f12e1736 René Nussbaumer
118 44fbd23b René Nussbaumer
    self._uid2user = {
119 44fbd23b René Nussbaumer
      self.masterd_uid: constants.MASTERD_USER,
120 44fbd23b René Nussbaumer
      self.confd_uid: constants.CONFD_USER,
121 3695a4e0 Thomas Thrainer
      self.luxid_uid: constants.LUXID_USER,
122 44fbd23b René Nussbaumer
      self.rapi_uid: constants.RAPI_USER,
123 44fbd23b René Nussbaumer
      self.noded_uid: constants.NODED_USER,
124 d08a8359 Thomas Thrainer
      self.mond_uid: constants.MOND_USER,
125 44fbd23b René Nussbaumer
      }
126 44fbd23b René Nussbaumer
127 44fbd23b René Nussbaumer
    self._gid2group = {
128 44fbd23b René Nussbaumer
      self.masterd_gid: constants.MASTERD_GROUP,
129 44fbd23b René Nussbaumer
      self.confd_gid: constants.CONFD_GROUP,
130 3695a4e0 Thomas Thrainer
      self.luxid_gid: constants.LUXID_GROUP,
131 44fbd23b René Nussbaumer
      self.rapi_gid: constants.RAPI_GROUP,
132 44fbd23b René Nussbaumer
      self.noded_gid: constants.NODED_GROUP,
133 d08a8359 Thomas Thrainer
      self.mond_gid: constants.MOND_GROUP,
134 44fbd23b René Nussbaumer
      self.daemons_gid: constants.DAEMONS_GROUP,
135 44fbd23b René Nussbaumer
      self.admin_gid: constants.ADMIN_GROUP,
136 44fbd23b René Nussbaumer
      }
137 44fbd23b René Nussbaumer
138 44fbd23b René Nussbaumer
    self._user2uid = utils.InvertDict(self._uid2user)
139 44fbd23b René Nussbaumer
    self._group2gid = utils.InvertDict(self._gid2group)
140 44fbd23b René Nussbaumer
141 44fbd23b René Nussbaumer
  def LookupUid(self, uid):
142 44fbd23b René Nussbaumer
    """Looks which Ganeti user belongs to this uid.
143 44fbd23b René Nussbaumer

144 44fbd23b René Nussbaumer
    @param uid: The uid to lookup
145 44fbd23b René Nussbaumer
    @returns The user name associated with that uid
146 44fbd23b René Nussbaumer

147 44fbd23b René Nussbaumer
    """
148 44fbd23b René Nussbaumer
    try:
149 44fbd23b René Nussbaumer
      return self._uid2user[uid]
150 44fbd23b René Nussbaumer
    except KeyError:
151 44fbd23b René Nussbaumer
      raise errors.ConfigurationError("Unknown Ganeti uid '%d'" % uid)
152 44fbd23b René Nussbaumer
153 44fbd23b René Nussbaumer
  def LookupGid(self, gid):
154 44fbd23b René Nussbaumer
    """Looks which Ganeti group belongs to this gid.
155 44fbd23b René Nussbaumer

156 44fbd23b René Nussbaumer
    @param gid: The gid to lookup
157 44fbd23b René Nussbaumer
    @returns The group name associated with that gid
158 44fbd23b René Nussbaumer

159 44fbd23b René Nussbaumer
    """
160 44fbd23b René Nussbaumer
    try:
161 44fbd23b René Nussbaumer
      return self._gid2group[gid]
162 44fbd23b René Nussbaumer
    except KeyError:
163 44fbd23b René Nussbaumer
      raise errors.ConfigurationError("Unknown Ganeti gid '%d'" % gid)
164 44fbd23b René Nussbaumer
165 44fbd23b René Nussbaumer
  def LookupUser(self, name):
166 44fbd23b René Nussbaumer
    """Looks which uid belongs to this name.
167 44fbd23b René Nussbaumer

168 44fbd23b René Nussbaumer
    @param name: The name to lookup
169 44fbd23b René Nussbaumer
    @returns The uid associated with that user name
170 44fbd23b René Nussbaumer

171 44fbd23b René Nussbaumer
    """
172 44fbd23b René Nussbaumer
    try:
173 44fbd23b René Nussbaumer
      return self._user2uid[name]
174 44fbd23b René Nussbaumer
    except KeyError:
175 44fbd23b René Nussbaumer
      raise errors.ConfigurationError("Unknown Ganeti user '%s'" % name)
176 44fbd23b René Nussbaumer
177 44fbd23b René Nussbaumer
  def LookupGroup(self, name):
178 44fbd23b René Nussbaumer
    """Looks which gid belongs to this name.
179 44fbd23b René Nussbaumer

180 44fbd23b René Nussbaumer
    @param name: The name to lookup
181 44fbd23b René Nussbaumer
    @returns The gid associated with that group name
182 44fbd23b René Nussbaumer

183 44fbd23b René Nussbaumer
    """
184 44fbd23b René Nussbaumer
    try:
185 44fbd23b René Nussbaumer
      return self._group2gid[name]
186 44fbd23b René Nussbaumer
    except KeyError:
187 44fbd23b René Nussbaumer
      raise errors.ConfigurationError("Unknown Ganeti group '%s'" % name)
188 44fbd23b René Nussbaumer
189 f12e1736 René Nussbaumer
190 f12e1736 René Nussbaumer
def GetEnts(resolver=GetentResolver):
191 f12e1736 René Nussbaumer
  """Singleton wrapper around resolver instance.
192 f12e1736 René Nussbaumer

193 f12e1736 René Nussbaumer
  As this method is accessed by multiple threads at the same time
194 1fdfa87a Iustin Pop
  we need to take thread-safety carefully.
195 f12e1736 René Nussbaumer

196 f12e1736 René Nussbaumer
  """
197 f12e1736 René Nussbaumer
  # We need to use the global keyword here
198 b459a848 Andrea Spadaccini
  global _priv # pylint: disable=W0603
199 f12e1736 René Nussbaumer
200 f12e1736 René Nussbaumer
  if not _priv:
201 f12e1736 René Nussbaumer
    _priv_lock.acquire()
202 f12e1736 René Nussbaumer
    try:
203 f12e1736 René Nussbaumer
      if not _priv:
204 f12e1736 René Nussbaumer
        # W0621: Redefine '_priv' from outer scope (used for singleton)
205 b459a848 Andrea Spadaccini
        _priv = resolver() # pylint: disable=W0621
206 f12e1736 René Nussbaumer
    finally:
207 f12e1736 René Nussbaumer
      _priv_lock.release()
208 f12e1736 René Nussbaumer
209 f12e1736 René Nussbaumer
  return _priv
210 a20e4768 Michael Hanselmann
211 a20e4768 Michael Hanselmann
212 a20e4768 Michael Hanselmann
def InitArchInfo():
213 a20e4768 Michael Hanselmann
  """Initialize architecture information.
214 a20e4768 Michael Hanselmann

215 a20e4768 Michael Hanselmann
  We can assume this information never changes during the lifetime of a
216 a20e4768 Michael Hanselmann
  process, therefore the information can easily be cached.
217 a20e4768 Michael Hanselmann

218 a20e4768 Michael Hanselmann
  @note: This function uses C{platform.architecture} to retrieve the Python
219 a20e4768 Michael Hanselmann
    binary architecture and does so by forking to run C{file} (see Python
220 a20e4768 Michael Hanselmann
    documentation for more information). Therefore it must not be used in a
221 a20e4768 Michael Hanselmann
    multi-threaded environment.
222 a20e4768 Michael Hanselmann

223 a20e4768 Michael Hanselmann
  """
224 a20e4768 Michael Hanselmann
  global _arch # pylint: disable=W0603
225 a20e4768 Michael Hanselmann
226 a20e4768 Michael Hanselmann
  if _arch is not None:
227 a20e4768 Michael Hanselmann
    raise errors.ProgrammerError("Architecture information can only be"
228 a20e4768 Michael Hanselmann
                                 " initialized once")
229 a20e4768 Michael Hanselmann
230 a20e4768 Michael Hanselmann
  _arch = (platform.architecture()[0], platform.machine())
231 a20e4768 Michael Hanselmann
232 a20e4768 Michael Hanselmann
233 a20e4768 Michael Hanselmann
def GetArchInfo():
234 a20e4768 Michael Hanselmann
  """Returns previsouly initialized architecture information.
235 a20e4768 Michael Hanselmann

236 a20e4768 Michael Hanselmann
  """
237 a20e4768 Michael Hanselmann
  if _arch is None:
238 a20e4768 Michael Hanselmann
    raise errors.ProgrammerError("Architecture information hasn't been"
239 a20e4768 Michael Hanselmann
                                 " initialized")
240 a20e4768 Michael Hanselmann
241 a20e4768 Michael Hanselmann
  return _arch
242 a51b19de Helga Velroyen
243 a51b19de Helga Velroyen
244 a51b19de Helga Velroyen
def GetClient(query=False):
245 a51b19de Helga Velroyen
  """Connects to the a luxi socket and returns a client.
246 a51b19de Helga Velroyen

247 a51b19de Helga Velroyen
  @type query: boolean
248 a51b19de Helga Velroyen
  @param query: this signifies that the client will only be
249 a51b19de Helga Velroyen
      used for queries; if the build-time parameter
250 a51b19de Helga Velroyen
      enable-split-queries is enabled, then the client will be
251 a51b19de Helga Velroyen
      connected to the query socket instead of the masterd socket
252 a51b19de Helga Velroyen

253 a51b19de Helga Velroyen
  """
254 a51b19de Helga Velroyen
  override_socket = os.getenv(constants.LUXI_OVERRIDE, "")
255 a51b19de Helga Velroyen
  if override_socket:
256 a51b19de Helga Velroyen
    if override_socket == constants.LUXI_OVERRIDE_MASTER:
257 a51b19de Helga Velroyen
      address = pathutils.MASTER_SOCKET
258 a51b19de Helga Velroyen
    elif override_socket == constants.LUXI_OVERRIDE_QUERY:
259 a51b19de Helga Velroyen
      address = pathutils.QUERY_SOCKET
260 a51b19de Helga Velroyen
    else:
261 a51b19de Helga Velroyen
      address = override_socket
262 a51b19de Helga Velroyen
  elif query:
263 a51b19de Helga Velroyen
    address = pathutils.QUERY_SOCKET
264 a51b19de Helga Velroyen
  else:
265 a51b19de Helga Velroyen
    address = None
266 a51b19de Helga Velroyen
  # TODO: Cache object?
267 a51b19de Helga Velroyen
  try:
268 a51b19de Helga Velroyen
    client = luxi.Client(address=address)
269 a51b19de Helga Velroyen
  except luxi.NoMasterError:
270 a51b19de Helga Velroyen
    ss = ssconf.SimpleStore()
271 a51b19de Helga Velroyen
272 a51b19de Helga Velroyen
    # Try to read ssconf file
273 a51b19de Helga Velroyen
    try:
274 a51b19de Helga Velroyen
      ss.GetMasterNode()
275 a51b19de Helga Velroyen
    except errors.ConfigurationError:
276 a51b19de Helga Velroyen
      raise errors.OpPrereqError("Cluster not initialized or this machine is"
277 a51b19de Helga Velroyen
                                 " not part of a cluster",
278 a51b19de Helga Velroyen
                                 errors.ECODE_INVAL)
279 a51b19de Helga Velroyen
280 a51b19de Helga Velroyen
    master, myself = ssconf.GetMasterAndMyself(ss=ss)
281 a51b19de Helga Velroyen
    if master != myself:
282 a51b19de Helga Velroyen
      raise errors.OpPrereqError("This is not the master node, please connect"
283 a51b19de Helga Velroyen
                                 " to node '%s' and rerun the command" %
284 a51b19de Helga Velroyen
                                 master, errors.ECODE_INVAL)
285 a51b19de Helga Velroyen
    raise
286 a51b19de Helga Velroyen
  return client