Revision f12e1736

b/Makefile.am
124 124
	lib/objects.py \
125 125
	lib/opcodes.py \
126 126
	lib/rpc.py \
127
	lib/runtime.py \
127 128
	lib/serializer.py \
128 129
	lib/ssconf.py \
129 130
	lib/ssh.py \
......
393 394
	test/ganeti.rapi.resources_unittest.py \
394 395
	test/ganeti.rapi.rlib2_unittest.py \
395 396
	test/ganeti.rpc_unittest.py \
397
	test/ganeti.runtime_unittest.py \
396 398
	test/ganeti.serializer_unittest.py \
397 399
	test/ganeti.ssh_unittest.py \
398 400
	test/ganeti.uidpool_unittest.py \
......
565 567
	  echo "DRBD_BARRIERS = $(DRBD_BARRIERS)"; \
566 568
	  echo "SYSLOG_USAGE = '$(SYSLOG_USAGE)'"; \
567 569
	  echo "DAEMONS_GROUP = '$(DAEMONS_GROUP)'"; \
570
	  echo "ADMIN_GROUP = '$(ADMIN_GROUP)'"; \
568 571
	  echo "MASTERD_USER = '$(MASTERD_USER)'"; \
572
	  echo "MASTERD_GROUP = '$(MASTERD_GROUP)'"; \
569 573
	  echo "RAPI_USER = '$(RAPI_USER)'"; \
574
	  echo "RAPI_GROUP = '$(RAPI_GROUP)'"; \
575
	  echo "CONFD_USER = '$(CONFD_USER)'"; \
576
	  echo "CONFD_GROUP = '$(CONFD_GROUP)'"; \
577
	  echo "NODED_USER = '$(NODED_USER)'"; \
570 578
	  echo "VCS_VERSION = '$$VCSVER'"; \
571 579
	} > $@
572 580

  
b/lib/constants.py
86 86

  
87 87
# user separation
88 88
DAEMONS_GROUP = _autoconf.DAEMONS_GROUP
89
ADMIN_GROUP = _autoconf.ADMIN_GROUP
89 90
MASTERD_USER = _autoconf.MASTERD_USER
91
MASTERD_GROUP = _autoconf.MASTERD_GROUP
90 92
RAPI_USER = _autoconf.RAPI_USER
93
RAPI_GROUP = _autoconf.RAPI_GROUP
94
CONFD_USER = _autoconf.CONFD_USER
95
CONFD_GROUP = _autoconf.CONFD_GROUP
96
NODED_USER = _autoconf.NODED_USER
91 97

  
92 98
# file paths
93 99
DATA_DIR = _autoconf.LOCALSTATEDIR + "/lib/ganeti"
b/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

  
32

  
33
_priv = None
34
_priv_lock = threading.Lock()
35

  
36

  
37
def GetUid(user, _getpwnam):
38
  """Retrieve the uid from the database.
39

  
40
  @type user: string
41
  @param user: The username to retrieve
42
  @return: The resolved uid
43

  
44
  """
45
  try:
46
    return _getpwnam(user).pw_uid
47
  except KeyError, err:
48
    raise errors.ConfigurationError("User '%s' not found (%s)" % (user, err))
49

  
50

  
51
def GetGid(group, _getgrnam):
52
  """Retrieve the gid from the database.
53

  
54
  @type group: string
55
  @param group: The group name to retrieve
56
  @return: The resolved gid
57

  
58
  """
59
  try:
60
    return _getgrnam(group).gr_gid
61
  except KeyError, err:
62
    raise errors.ConfigurationError("Group '%s' not found (%s)" % (group, err))
63

  
64

  
65
class GetentResolver:
66
  """Resolves Ganeti uids and gids by name.
67

  
68
  @ivar masterd_uid: The resolved uid of the masterd user
69
  @ivar masterd_gid: The resolved gid of the masterd group
70
  @ivar confd_uid: The resolved uid of the confd user
71
  @ivar confd_gid: The resolved gid of the confd group
72
  @ivar rapi_uid: The resolved uid of the rapi user
73
  @ivar rapi_gid: The resolved gid of the rapi group
74
  @ivar noded_uid: The resolved uid of the noded user
75

  
76
  @ivar daemons_gid: The resolved gid of the daemons group
77
  @ivar admin_gid: The resolved gid of the admin group
78
  """
79
  def __init__(self, _getpwnam=pwd.getpwnam, _getgrnam=grp.getgrnam):
80
    """Initialize the resolver.
81

  
82
    """
83
    # Daemon pairs
84
    self.masterd_uid = GetUid(constants.MASTERD_USER, _getpwnam)
85
    self.masterd_gid = GetGid(constants.MASTERD_GROUP, _getgrnam)
86

  
87
    self.confd_uid = GetUid(constants.CONFD_USER, _getpwnam)
88
    self.confd_gid = GetGid(constants.CONFD_GROUP, _getgrnam)
89

  
90
    self.rapi_uid = GetUid(constants.RAPI_USER, _getpwnam)
91
    self.rapi_gid = GetGid(constants.RAPI_GROUP, _getgrnam)
92

  
93
    self.noded_uid = GetUid(constants.NODED_USER, _getpwnam)
94

  
95
    # Misc Ganeti groups
96
    self.daemons_gid = GetGid(constants.DAEMONS_GROUP, _getgrnam)
97
    self.admin_gid = GetGid(constants.ADMIN_GROUP, _getgrnam)
98

  
99

  
100
def GetEnts(resolver=GetentResolver):
101
  """Singleton wrapper around resolver instance.
102

  
103
  As this method is accessed by multiple threads at the same time
104
  we need to take thread-safty carefully
105

  
106
  """
107
  # We need to use the global keyword here
108
  global _priv # pylint: disable-msg=W0603
109

  
110
  if not _priv:
111
    _priv_lock.acquire()
112
    try:
113
      if not _priv:
114
        # W0621: Redefine '_priv' from outer scope (used for singleton)
115
        _priv = resolver() # pylint: disable-msg=W0621
116
    finally:
117
      _priv_lock.release()
118

  
119
  return _priv
120

  
b/test/ganeti.runtime_unittest.py
1
#!/usr/bin/python
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
"""Script for testing ganeti.runtime"""
22

  
23
from ganeti import constants
24
from ganeti import errors
25
from ganeti import runtime
26

  
27
import testutils
28

  
29

  
30
class _EntStub:
31
  def __init__(self, uid=None, gid=None):
32
    self.pw_uid = uid
33
    self.gr_gid = gid
34

  
35

  
36
def _StubGetpwnam(user):
37
  users = {
38
    constants.MASTERD_USER: _EntStub(uid=0),
39
    constants.CONFD_USER: _EntStub(uid=1),
40
    constants.RAPI_USER: _EntStub(uid=2),
41
    constants.NODED_USER: _EntStub(uid=3),
42
    }
43
  return users[user]
44

  
45

  
46
def _StubGetgrnam(group):
47
  groups = {
48
    constants.MASTERD_GROUP: _EntStub(gid=0),
49
    constants.CONFD_GROUP: _EntStub(gid=1),
50
    constants.RAPI_GROUP: _EntStub(gid=2),
51
    constants.DAEMONS_GROUP: _EntStub(gid=3),
52
    constants.ADMIN_GROUP: _EntStub(gid=4),
53
    }
54
  return groups[group]
55

  
56

  
57
def _RaisingStubGetpwnam(user):
58
  raise KeyError("user not found")
59

  
60

  
61
def _RaisingStubGetgrnam(group):
62
  raise KeyError("group not found")
63

  
64

  
65
class ResolverStubRaising(object):
66
  def __init__(self):
67
    raise errors.ConfigurationError("No entries")
68

  
69

  
70
class TestErrors(testutils.GanetiTestCase):
71
  def testEverythingSuccessful(self):
72
    resolver = runtime.GetentResolver(_getpwnam=_StubGetpwnam,
73
                                      _getgrnam=_StubGetgrnam)
74

  
75
    self.assertEqual(resolver.masterd_uid,
76
                     _StubGetpwnam(constants.MASTERD_USER).pw_uid)
77
    self.assertEqual(resolver.masterd_gid,
78
                     _StubGetgrnam(constants.MASTERD_GROUP).gr_gid)
79
    self.assertEqual(resolver.confd_uid,
80
                     _StubGetpwnam(constants.CONFD_USER).pw_uid)
81
    self.assertEqual(resolver.confd_gid,
82
                     _StubGetgrnam(constants.CONFD_GROUP).gr_gid)
83
    self.assertEqual(resolver.rapi_uid,
84
                     _StubGetpwnam(constants.RAPI_USER).pw_uid)
85
    self.assertEqual(resolver.rapi_gid,
86
                     _StubGetgrnam(constants.RAPI_GROUP).gr_gid)
87
    self.assertEqual(resolver.noded_uid,
88
                     _StubGetpwnam(constants.NODED_USER).pw_uid)
89

  
90
    self.assertEqual(resolver.daemons_gid,
91
                     _StubGetgrnam(constants.DAEMONS_GROUP).gr_gid)
92
    self.assertEqual(resolver.admin_gid,
93
                     _StubGetgrnam(constants.ADMIN_GROUP).gr_gid)
94

  
95
  def testUserNotFound(self):
96
    self.assertRaises(errors.ConfigurationError, runtime.GetentResolver,
97
                      _getpwnam=_RaisingStubGetpwnam, _getgrnam=_StubGetgrnam)
98

  
99
  def testGroupNotFound(self):
100
    self.assertRaises(errors.ConfigurationError, runtime.GetentResolver,
101
                      _getpwnam=_StubGetpwnam, _getgrnam=_RaisingStubGetgrnam)
102

  
103
  def testUserNotFoundGetEnts(self):
104
    self.assertRaises(errors.ConfigurationError, runtime.GetEnts,
105
                      resolver=ResolverStubRaising)
106

  
107

  
108
if __name__ == "__main__":
109
  testutils.GanetiTestProgram()

Also available in: Unified diff