Statistics
| Branch: | Tag: | Revision:

root / lib / runtime.py @ d08a8359

History | View | Annotate | Download (6.8 kB)

1
#
2
#
3

    
4
# Copyright (C) 2010 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
"""Module implementing configuration details at runtime.
22

23
"""
24

    
25

    
26
import grp
27
import pwd
28
import threading
29
import platform
30

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

    
35

    
36
_priv = None
37
_priv_lock = threading.Lock()
38

    
39
#: Architecture information
40
_arch = None
41

    
42

    
43
def GetUid(user, _getpwnam):
44
  """Retrieve the uid from the database.
45

46
  @type user: string
47
  @param user: The username to retrieve
48
  @return: The resolved uid
49

50
  """
51
  try:
52
    return _getpwnam(user).pw_uid
53
  except KeyError, err:
54
    raise errors.ConfigurationError("User '%s' not found (%s)" % (user, err))
55

    
56

    
57
def GetGid(group, _getgrnam):
58
  """Retrieve the gid from the database.
59

60
  @type group: string
61
  @param group: The group name to retrieve
62
  @return: The resolved gid
63

64
  """
65
  try:
66
    return _getgrnam(group).gr_gid
67
  except KeyError, err:
68
    raise errors.ConfigurationError("Group '%s' not found (%s)" % (group, err))
69

    
70

    
71
class GetentResolver:
72
  """Resolves Ganeti uids and gids by name.
73

74
  @ivar masterd_uid: The resolved uid of the masterd user
75
  @ivar masterd_gid: The resolved gid of the masterd group
76
  @ivar confd_uid: The resolved uid of the confd user
77
  @ivar confd_gid: The resolved gid of the confd group
78
  @ivar luxid_uid: The resolved uid of the luxid user
79
  @ivar luxid_gid: The resolved gid of the luxid group
80
  @ivar rapi_uid: The resolved uid of the rapi user
81
  @ivar rapi_gid: The resolved gid of the rapi group
82
  @ivar noded_uid: The resolved uid of the noded user
83
  @ivar daemons_gid: The resolved gid of the daemons group
84
  @ivar admin_gid: The resolved gid of the admin group
85

86
  """
87
  def __init__(self, _getpwnam=pwd.getpwnam, _getgrnam=grp.getgrnam):
88
    """Initialize the resolver.
89

90
    """
91
    # Daemon pairs
92
    self.masterd_uid = GetUid(constants.MASTERD_USER, _getpwnam)
93
    self.masterd_gid = GetGid(constants.MASTERD_GROUP, _getgrnam)
94

    
95
    self.confd_uid = GetUid(constants.CONFD_USER, _getpwnam)
96
    self.confd_gid = GetGid(constants.CONFD_GROUP, _getgrnam)
97

    
98
    self.luxid_uid = GetUid(constants.LUXID_USER, _getpwnam)
99
    self.luxid_gid = GetGid(constants.LUXID_GROUP, _getgrnam)
100

    
101
    self.rapi_uid = GetUid(constants.RAPI_USER, _getpwnam)
102
    self.rapi_gid = GetGid(constants.RAPI_GROUP, _getgrnam)
103

    
104
    self.noded_uid = GetUid(constants.NODED_USER, _getpwnam)
105
    self.noded_gid = GetGid(constants.NODED_GROUP, _getgrnam)
106

    
107
    self.mond_uid = GetUid(constants.MOND_USER, _getpwnam)
108
    self.mond_gid = GetGid(constants.MOND_GROUP, _getgrnam)
109

    
110
    # Misc Ganeti groups
111
    self.daemons_gid = GetGid(constants.DAEMONS_GROUP, _getgrnam)
112
    self.admin_gid = GetGid(constants.ADMIN_GROUP, _getgrnam)
113

    
114
    self._uid2user = {
115
      self.masterd_uid: constants.MASTERD_USER,
116
      self.confd_uid: constants.CONFD_USER,
117
      self.luxid_uid: constants.LUXID_USER,
118
      self.rapi_uid: constants.RAPI_USER,
119
      self.noded_uid: constants.NODED_USER,
120
      self.mond_uid: constants.MOND_USER,
121
      }
122

    
123
    self._gid2group = {
124
      self.masterd_gid: constants.MASTERD_GROUP,
125
      self.confd_gid: constants.CONFD_GROUP,
126
      self.luxid_gid: constants.LUXID_GROUP,
127
      self.rapi_gid: constants.RAPI_GROUP,
128
      self.noded_gid: constants.NODED_GROUP,
129
      self.mond_gid: constants.MOND_GROUP,
130
      self.daemons_gid: constants.DAEMONS_GROUP,
131
      self.admin_gid: constants.ADMIN_GROUP,
132
      }
133

    
134
    self._user2uid = utils.InvertDict(self._uid2user)
135
    self._group2gid = utils.InvertDict(self._gid2group)
136

    
137
  def LookupUid(self, uid):
138
    """Looks which Ganeti user belongs to this uid.
139

140
    @param uid: The uid to lookup
141
    @returns The user name associated with that uid
142

143
    """
144
    try:
145
      return self._uid2user[uid]
146
    except KeyError:
147
      raise errors.ConfigurationError("Unknown Ganeti uid '%d'" % uid)
148

    
149
  def LookupGid(self, gid):
150
    """Looks which Ganeti group belongs to this gid.
151

152
    @param gid: The gid to lookup
153
    @returns The group name associated with that gid
154

155
    """
156
    try:
157
      return self._gid2group[gid]
158
    except KeyError:
159
      raise errors.ConfigurationError("Unknown Ganeti gid '%d'" % gid)
160

    
161
  def LookupUser(self, name):
162
    """Looks which uid belongs to this name.
163

164
    @param name: The name to lookup
165
    @returns The uid associated with that user name
166

167
    """
168
    try:
169
      return self._user2uid[name]
170
    except KeyError:
171
      raise errors.ConfigurationError("Unknown Ganeti user '%s'" % name)
172

    
173
  def LookupGroup(self, name):
174
    """Looks which gid belongs to this name.
175

176
    @param name: The name to lookup
177
    @returns The gid associated with that group name
178

179
    """
180
    try:
181
      return self._group2gid[name]
182
    except KeyError:
183
      raise errors.ConfigurationError("Unknown Ganeti group '%s'" % name)
184

    
185

    
186
def GetEnts(resolver=GetentResolver):
187
  """Singleton wrapper around resolver instance.
188

189
  As this method is accessed by multiple threads at the same time
190
  we need to take thread-safety carefully.
191

192
  """
193
  # We need to use the global keyword here
194
  global _priv # pylint: disable=W0603
195

    
196
  if not _priv:
197
    _priv_lock.acquire()
198
    try:
199
      if not _priv:
200
        # W0621: Redefine '_priv' from outer scope (used for singleton)
201
        _priv = resolver() # pylint: disable=W0621
202
    finally:
203
      _priv_lock.release()
204

    
205
  return _priv
206

    
207

    
208
def InitArchInfo():
209
  """Initialize architecture information.
210

211
  We can assume this information never changes during the lifetime of a
212
  process, therefore the information can easily be cached.
213

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

219
  """
220
  global _arch # pylint: disable=W0603
221

    
222
  if _arch is not None:
223
    raise errors.ProgrammerError("Architecture information can only be"
224
                                 " initialized once")
225

    
226
  _arch = (platform.architecture()[0], platform.machine())
227

    
228

    
229
def GetArchInfo():
230
  """Returns previsouly initialized architecture information.
231

232
  """
233
  if _arch is None:
234
    raise errors.ProgrammerError("Architecture information hasn't been"
235
                                 " initialized")
236

    
237
  return _arch