Package ganeti :: Module runtime
[hide private]
[frames] | no frames]

Source Code for Module ganeti.runtime

  1  # 
  2  # 
  3   
  4  # Copyright (C) 2010 Google Inc. 
  5  # All rights reserved. 
  6  # 
  7  # Redistribution and use in source and binary forms, with or without 
  8  # modification, are permitted provided that the following conditions are 
  9  # met: 
 10  # 
 11  # 1. Redistributions of source code must retain the above copyright notice, 
 12  # this list of conditions and the following disclaimer. 
 13  # 
 14  # 2. Redistributions in binary form must reproduce the above copyright 
 15  # notice, this list of conditions and the following disclaimer in the 
 16  # documentation and/or other materials provided with the distribution. 
 17  # 
 18  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
 19  # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
 20  # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 21  # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
 22  # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 23  # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 24  # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 25  # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 26  # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 27  # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 28  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 29   
 30  """Module implementing configuration details at runtime. 
 31   
 32  """ 
 33   
 34   
 35  import grp 
 36  import pwd 
 37  import threading 
 38  import platform 
 39   
 40  from ganeti import constants 
 41  from ganeti import errors 
 42  from ganeti import luxi 
 43  from ganeti.rpc.errors import NoMasterError 
 44  from ganeti import pathutils 
 45  from ganeti import ssconf 
 46  from ganeti import utils 
 47   
 48   
 49  _priv = None 
 50  _priv_lock = threading.Lock() 
 51   
 52  #: Architecture information 
 53  _arch = None 
 54   
 55   
56 -def GetUid(user, _getpwnam):
57 """Retrieve the uid from the database. 58 59 @type user: string 60 @param user: The username to retrieve 61 @return: The resolved uid 62 63 """ 64 try: 65 return _getpwnam(user).pw_uid 66 except KeyError, err: 67 raise errors.ConfigurationError("User '%s' not found (%s)" % (user, err))
68 69
70 -def GetGid(group, _getgrnam):
71 """Retrieve the gid from the database. 72 73 @type group: string 74 @param group: The group name to retrieve 75 @return: The resolved gid 76 77 """ 78 try: 79 return _getgrnam(group).gr_gid 80 except KeyError, err: 81 raise errors.ConfigurationError("Group '%s' not found (%s)" % (group, err))
82 83
84 -class GetentResolver(object):
85 """Resolves Ganeti uids and gids by name. 86 87 @ivar masterd_uid: The resolved uid of the masterd user 88 @ivar masterd_gid: The resolved gid of the masterd group 89 @ivar confd_uid: The resolved uid of the confd user 90 @ivar confd_gid: The resolved gid of the confd group 91 @ivar wconfd_uid: The resolved uid of the wconfd user 92 @ivar wconfd_gid: The resolved gid of the wconfd group 93 @ivar luxid_uid: The resolved uid of the luxid user 94 @ivar luxid_gid: The resolved gid of the luxid group 95 @ivar rapi_uid: The resolved uid of the rapi user 96 @ivar rapi_gid: The resolved gid of the rapi group 97 @ivar noded_uid: The resolved uid of the noded user 98 @ivar daemons_gid: The resolved gid of the daemons group 99 @ivar admin_gid: The resolved gid of the admin group 100 101 """
102 - def __init__(self, _getpwnam=pwd.getpwnam, _getgrnam=grp.getgrnam):
103 """Initialize the resolver. 104 105 """ 106 # Daemon pairs 107 self.masterd_uid = GetUid(constants.MASTERD_USER, _getpwnam) 108 self.masterd_gid = GetGid(constants.MASTERD_GROUP, _getgrnam) 109 110 self.confd_uid = GetUid(constants.CONFD_USER, _getpwnam) 111 self.confd_gid = GetGid(constants.CONFD_GROUP, _getgrnam) 112 113 self.wconfd_uid = GetUid(constants.WCONFD_USER, _getpwnam) 114 self.wconfd_gid = GetGid(constants.WCONFD_GROUP, _getgrnam) 115 116 self.luxid_uid = GetUid(constants.LUXID_USER, _getpwnam) 117 self.luxid_gid = GetGid(constants.LUXID_GROUP, _getgrnam) 118 119 self.rapi_uid = GetUid(constants.RAPI_USER, _getpwnam) 120 self.rapi_gid = GetGid(constants.RAPI_GROUP, _getgrnam) 121 122 self.noded_uid = GetUid(constants.NODED_USER, _getpwnam) 123 self.noded_gid = GetGid(constants.NODED_GROUP, _getgrnam) 124 125 self.mond_uid = GetUid(constants.MOND_USER, _getpwnam) 126 self.mond_gid = GetGid(constants.MOND_GROUP, _getgrnam) 127 128 # Misc Ganeti groups 129 self.daemons_gid = GetGid(constants.DAEMONS_GROUP, _getgrnam) 130 self.admin_gid = GetGid(constants.ADMIN_GROUP, _getgrnam) 131 132 self._uid2user = { 133 self.masterd_uid: constants.MASTERD_USER, 134 self.confd_uid: constants.CONFD_USER, 135 self.wconfd_uid: constants.WCONFD_USER, 136 self.luxid_uid: constants.LUXID_USER, 137 self.rapi_uid: constants.RAPI_USER, 138 self.noded_uid: constants.NODED_USER, 139 self.mond_uid: constants.MOND_USER, 140 } 141 142 self._gid2group = { 143 self.masterd_gid: constants.MASTERD_GROUP, 144 self.confd_gid: constants.CONFD_GROUP, 145 self.wconfd_gid: constants.WCONFD_GROUP, 146 self.luxid_gid: constants.LUXID_GROUP, 147 self.rapi_gid: constants.RAPI_GROUP, 148 self.noded_gid: constants.NODED_GROUP, 149 self.mond_gid: constants.MOND_GROUP, 150 self.daemons_gid: constants.DAEMONS_GROUP, 151 self.admin_gid: constants.ADMIN_GROUP, 152 } 153 154 self._user2uid = utils.InvertDict(self._uid2user) 155 self._group2gid = utils.InvertDict(self._gid2group)
156
157 - def LookupUid(self, uid):
158 """Looks which Ganeti user belongs to this uid. 159 160 @param uid: The uid to lookup 161 @returns The user name associated with that uid 162 163 """ 164 try: 165 return self._uid2user[uid] 166 except KeyError: 167 raise errors.ConfigurationError("Unknown Ganeti uid '%d'" % uid)
168
169 - def LookupGid(self, gid):
170 """Looks which Ganeti group belongs to this gid. 171 172 @param gid: The gid to lookup 173 @returns The group name associated with that gid 174 175 """ 176 try: 177 return self._gid2group[gid] 178 except KeyError: 179 raise errors.ConfigurationError("Unknown Ganeti gid '%d'" % gid)
180
181 - def LookupUser(self, name):
182 """Looks which uid belongs to this name. 183 184 @param name: The name to lookup 185 @returns The uid associated with that user name 186 187 """ 188 try: 189 return self._user2uid[name] 190 except KeyError: 191 raise errors.ConfigurationError("Unknown Ganeti user '%s'" % name)
192
193 - def LookupGroup(self, name):
194 """Looks which gid belongs to this name. 195 196 @param name: The name to lookup 197 @returns The gid associated with that group name 198 199 """ 200 try: 201 return self._group2gid[name] 202 except KeyError: 203 raise errors.ConfigurationError("Unknown Ganeti group '%s'" % name)
204 205
206 -def GetEnts(resolver=GetentResolver):
207 """Singleton wrapper around resolver instance. 208 209 As this method is accessed by multiple threads at the same time 210 we need to take thread-safety carefully. 211 212 """ 213 # We need to use the global keyword here 214 global _priv # pylint: disable=W0603 215 216 if not _priv: 217 _priv_lock.acquire() 218 try: 219 if not _priv: 220 # W0621: Redefine '_priv' from outer scope (used for singleton) 221 _priv = resolver() # pylint: disable=W0621 222 finally: 223 _priv_lock.release() 224 225 return _priv
226 227
228 -def InitArchInfo():
229 """Initialize architecture information. 230 231 We can assume this information never changes during the lifetime of a 232 process, therefore the information can easily be cached. 233 234 @note: This function uses C{platform.architecture} to retrieve the Python 235 binary architecture and does so by forking to run C{file} (see Python 236 documentation for more information). Therefore it must not be used in a 237 multi-threaded environment. 238 239 """ 240 global _arch # pylint: disable=W0603 241 242 if _arch is not None: 243 raise errors.ProgrammerError("Architecture information can only be" 244 " initialized once") 245 246 _arch = (platform.architecture()[0], platform.machine())
247 248
249 -def GetArchInfo():
250 """Returns previsouly initialized architecture information. 251 252 """ 253 if _arch is None: 254 raise errors.ProgrammerError("Architecture information hasn't been" 255 " initialized") 256 257 return _arch
258 259
260 -def GetClient():
261 """Connects to the a luxi socket and returns a client. 262 263 """ 264 try: 265 client = luxi.Client(address=pathutils.QUERY_SOCKET) 266 except NoMasterError: 267 ss = ssconf.SimpleStore() 268 269 # Try to read ssconf file 270 try: 271 ss.GetMasterNode() 272 except errors.ConfigurationError: 273 raise errors.OpPrereqError("Cluster not initialized or this machine is" 274 " not part of a cluster", 275 errors.ECODE_INVAL) 276 277 master, myself = ssconf.GetMasterAndMyself(ss=ss) 278 if master != myself: 279 raise errors.OpPrereqError("This is not the master node, please connect" 280 " to node '%s' and rerun the command" % 281 master, errors.ECODE_INVAL) 282 raise 283 return client
284