ht: Add new check for numbers
[ganeti-local] / lib / runtime.py
1 #
2
3 # Copyright (C) 2010 Google Inc.
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 # 02110-1301, USA.
19
20 """Module implementing configuration details at runtime.
21
22 """
23
24
25 import grp
26 import pwd
27 import threading
28
29 from ganeti import constants
30 from ganeti import errors
31 from ganeti import utils
32
33
34 _priv = None
35 _priv_lock = threading.Lock()
36
37
38 def GetUid(user, _getpwnam):
39   """Retrieve the uid from the database.
40
41   @type user: string
42   @param user: The username to retrieve
43   @return: The resolved uid
44
45   """
46   try:
47     return _getpwnam(user).pw_uid
48   except KeyError, err:
49     raise errors.ConfigurationError("User '%s' not found (%s)" % (user, err))
50
51
52 def GetGid(group, _getgrnam):
53   """Retrieve the gid from the database.
54
55   @type group: string
56   @param group: The group name to retrieve
57   @return: The resolved gid
58
59   """
60   try:
61     return _getgrnam(group).gr_gid
62   except KeyError, err:
63     raise errors.ConfigurationError("Group '%s' not found (%s)" % (group, err))
64
65
66 class GetentResolver:
67   """Resolves Ganeti uids and gids by name.
68
69   @ivar masterd_uid: The resolved uid of the masterd user
70   @ivar masterd_gid: The resolved gid of the masterd group
71   @ivar confd_uid: The resolved uid of the confd user
72   @ivar confd_gid: The resolved gid of the confd group
73   @ivar rapi_uid: The resolved uid of the rapi user
74   @ivar rapi_gid: The resolved gid of the rapi group
75   @ivar noded_uid: The resolved uid of the noded user
76
77   @ivar daemons_gid: The resolved gid of the daemons group
78   @ivar admin_gid: The resolved gid of the admin group
79   """
80   def __init__(self, _getpwnam=pwd.getpwnam, _getgrnam=grp.getgrnam):
81     """Initialize the resolver.
82
83     """
84     # Daemon pairs
85     self.masterd_uid = GetUid(constants.MASTERD_USER, _getpwnam)
86     self.masterd_gid = GetGid(constants.MASTERD_GROUP, _getgrnam)
87
88     self.confd_uid = GetUid(constants.CONFD_USER, _getpwnam)
89     self.confd_gid = GetGid(constants.CONFD_GROUP, _getgrnam)
90
91     self.rapi_uid = GetUid(constants.RAPI_USER, _getpwnam)
92     self.rapi_gid = GetGid(constants.RAPI_GROUP, _getgrnam)
93
94     self.noded_uid = GetUid(constants.NODED_USER, _getpwnam)
95     self.noded_gid = GetGid(constants.NODED_GROUP, _getgrnam)
96
97     # Misc Ganeti groups
98     self.daemons_gid = GetGid(constants.DAEMONS_GROUP, _getgrnam)
99     self.admin_gid = GetGid(constants.ADMIN_GROUP, _getgrnam)
100
101     self._uid2user = {
102       self.masterd_uid: constants.MASTERD_USER,
103       self.confd_uid: constants.CONFD_USER,
104       self.rapi_uid: constants.RAPI_USER,
105       self.noded_uid: constants.NODED_USER,
106       }
107
108     self._gid2group = {
109       self.masterd_gid: constants.MASTERD_GROUP,
110       self.confd_gid: constants.CONFD_GROUP,
111       self.rapi_gid: constants.RAPI_GROUP,
112       self.noded_gid: constants.NODED_GROUP,
113       self.daemons_gid: constants.DAEMONS_GROUP,
114       self.admin_gid: constants.ADMIN_GROUP,
115       }
116
117     self._user2uid = utils.InvertDict(self._uid2user)
118     self._group2gid = utils.InvertDict(self._gid2group)
119
120   def LookupUid(self, uid):
121     """Looks which Ganeti user belongs to this uid.
122
123     @param uid: The uid to lookup
124     @returns The user name associated with that uid
125
126     """
127     try:
128       return self._uid2user[uid]
129     except KeyError:
130       raise errors.ConfigurationError("Unknown Ganeti uid '%d'" % uid)
131
132   def LookupGid(self, gid):
133     """Looks which Ganeti group belongs to this gid.
134
135     @param gid: The gid to lookup
136     @returns The group name associated with that gid
137
138     """
139     try:
140       return self._gid2group[gid]
141     except KeyError:
142       raise errors.ConfigurationError("Unknown Ganeti gid '%d'" % gid)
143
144   def LookupUser(self, name):
145     """Looks which uid belongs to this name.
146
147     @param name: The name to lookup
148     @returns The uid associated with that user name
149
150     """
151     try:
152       return self._user2uid[name]
153     except KeyError:
154       raise errors.ConfigurationError("Unknown Ganeti user '%s'" % name)
155
156   def LookupGroup(self, name):
157     """Looks which gid belongs to this name.
158
159     @param name: The name to lookup
160     @returns The gid associated with that group name
161
162     """
163     try:
164       return self._group2gid[name]
165     except KeyError:
166       raise errors.ConfigurationError("Unknown Ganeti group '%s'" % name)
167
168
169 def GetEnts(resolver=GetentResolver):
170   """Singleton wrapper around resolver instance.
171
172   As this method is accessed by multiple threads at the same time
173   we need to take thread-safty carefully
174
175   """
176   # We need to use the global keyword here
177   global _priv # pylint: disable-msg=W0603
178
179   if not _priv:
180     _priv_lock.acquire()
181     try:
182       if not _priv:
183         # W0621: Redefine '_priv' from outer scope (used for singleton)
184         _priv = resolver() # pylint: disable-msg=W0621
185     finally:
186       _priv_lock.release()
187
188   return _priv
189