---
lib/runtime.py | 69 ++++++++++++++++++++++++++++++++++++
lib/utils/algo.py | 10 +++++
test/ganeti.runtime_unittest.py | 59 ++++++++++++++++++++++++-------
test/ganeti.utils.algo_unittest.py | 7 ++++
4 files changed, 132 insertions(+), 13 deletions(-)
diff --git a/lib/runtime.py b/lib/runtime.py
index 2d65ef0..4d5e3ef 100644
--- a/lib/runtime.py
+++ b/lib/runtime.py
@@ -28,6 +28,7 @@ import threading
from ganeti import constants
from ganeti import errors
+from ganeti import utils
_priv = None
@@ -91,11 +92,79 @@ class GetentResolver:
self.rapi_gid = GetGid(constants.RAPI_GROUP, _getgrnam)
self.noded_uid = GetUid(constants.NODED_USER, _getpwnam)
+ self.noded_gid = GetGid(constants.NODED_GROUP, _getgrnam)
# Misc Ganeti groups
self.daemons_gid = GetGid(constants.DAEMONS_GROUP, _getgrnam)
self.admin_gid = GetGid(constants.ADMIN_GROUP, _getgrnam)
+ self._uid2user = {
+ self.masterd_uid: constants.MASTERD_USER,
+ self.confd_uid: constants.CONFD_USER,
+ self.rapi_uid: constants.RAPI_USER,
+ self.noded_uid: constants.NODED_USER,
+ }
+
+ self._gid2group = {
+ self.masterd_gid: constants.MASTERD_GROUP,
+ self.confd_gid: constants.CONFD_GROUP,
+ self.rapi_gid: constants.RAPI_GROUP,
+ self.noded_gid: constants.NODED_GROUP,
+ self.daemons_gid: constants.DAEMONS_GROUP,
+ self.admin_gid: constants.ADMIN_GROUP,
+ }
+
+ self._user2uid = utils.InvertDict(self._uid2user)
+ self._group2gid = utils.InvertDict(self._gid2group)
+
+ def LookupUid(self, uid):
+ """Looks which Ganeti user belongs to this uid.
+
+ @param uid: The uid to lookup
+ @returns The user name associated with that uid
+
+ """
+ try:
+ return self._uid2user[uid]
+ except KeyError:
+ raise errors.ConfigurationError("Unknown Ganeti uid '%d'" % uid)
+
+ def LookupGid(self, gid):
+ """Looks which Ganeti group belongs to this gid.
+
+ @param gid: The gid to lookup
+ @returns The group name associated with that gid
+
+ """
+ try:
+ return self._gid2group[gid]
+ except KeyError:
+ raise errors.ConfigurationError("Unknown Ganeti gid '%d'" % gid)
+
+ def LookupUser(self, name):
+ """Looks which uid belongs to this name.
+
+ @param name: The name to lookup
+ @returns The uid associated with that user name
+
+ """
+ try:
+ return self._user2uid[name]
+ except KeyError:
+ raise errors.ConfigurationError("Unknown Ganeti user '%s'" % name)
+
+ def LookupGroup(self, name):
+ """Looks which gid belongs to this name.
+
+ @param name: The name to lookup
+ @returns The gid associated with that group name
+
+ """
+ try:
+ return self._group2gid[name]
+ except KeyError:
+ raise errors.ConfigurationError("Unknown Ganeti group '%s'" % name)
+
def GetEnts(resolver=GetentResolver):
"""Singleton wrapper around resolver instance.
diff --git a/lib/utils/algo.py b/lib/utils/algo.py
index 543ac77..280a1b7 100644
--- a/lib/utils/algo.py
+++ b/lib/utils/algo.py
@@ -115,6 +115,16 @@ def NiceSort(values, key=None):
return sorted(values, key=keyfunc)
+def InvertDict(dict_in):
+ """Inverts the key/value mapping of a dict.
+
+ @param dict_in: The dict to invert
+ @returns the inverted dict
+
+ """
+ return dict(zip(dict_in.values(), dict_in.keys()))
+
+
class RunningTimeout(object):
"""Class to calculate remaining timeout when doing several operations.
diff --git a/test/ganeti.runtime_unittest.py b/test/ganeti.runtime_unittest.py
index 3ba9ac8..79ede58 100755
--- a/test/ganeti.runtime_unittest.py
+++ b/test/ganeti.runtime_unittest.py
@@ -25,6 +25,7 @@ from ganeti import errors
from ganeti import runtime
import testutils
+import unittest
class _EntStub:
@@ -50,6 +51,7 @@ def _StubGetgrnam(group):
constants.RAPI_GROUP: _EntStub(gid=2),
constants.DAEMONS_GROUP: _EntStub(gid=3),
constants.ADMIN_GROUP: _EntStub(gid=4),
+ constants.NODED_GROUP: _EntStub(gid=5),
}
return groups[group]
@@ -67,29 +69,30 @@ class ResolverStubRaising(object):
raise errors.ConfigurationError("No entries")
-class TestErrors(testutils.GanetiTestCase):
- def testEverythingSuccessful(self):
- resolver = runtime.GetentResolver(_getpwnam=_StubGetpwnam,
- _getgrnam=_StubGetgrnam)
+class TestErrors(unittest.TestCase):
+ def setUp(self):
+ self.resolver = runtime.GetentResolver(_getpwnam=_StubGetpwnam,
+ _getgrnam=_StubGetgrnam)
- self.assertEqual(resolver.masterd_uid,
+ def testEverythingSuccessful(self):
+ self.assertEqual(self.resolver.masterd_uid,
_StubGetpwnam(constants.MASTERD_USER).pw_uid)
- self.assertEqual(resolver.masterd_gid,
+ self.assertEqual(self.resolver.masterd_gid,
_StubGetgrnam(constants.MASTERD_GROUP).gr_gid)
- self.assertEqual(resolver.confd_uid,
+ self.assertEqual(self.resolver.confd_uid,
_StubGetpwnam(constants.CONFD_USER).pw_uid)
- self.assertEqual(resolver.confd_gid,
+ self.assertEqual(self.resolver.confd_gid,
_StubGetgrnam(constants.CONFD_GROUP).gr_gid)
- self.assertEqual(resolver.rapi_uid,
+ self.assertEqual(self.resolver.rapi_uid,
_StubGetpwnam(constants.RAPI_USER).pw_uid)
- self.assertEqual(resolver.rapi_gid,
+ self.assertEqual(self.resolver.rapi_gid,
_StubGetgrnam(constants.RAPI_GROUP).gr_gid)
- self.assertEqual(resolver.noded_uid,
+ self.assertEqual(self.resolver.noded_uid,
_StubGetpwnam(constants.NODED_USER).pw_uid)
- self.assertEqual(resolver.daemons_gid,
+ self.assertEqual(self.resolver.daemons_gid,
_StubGetgrnam(constants.DAEMONS_GROUP).gr_gid)
- self.assertEqual(resolver.admin_gid,
+ self.assertEqual(self.resolver.admin_gid,
_StubGetgrnam(constants.ADMIN_GROUP).gr_gid)
def testUserNotFound(self):
@@ -104,6 +107,36 @@ class TestErrors(testutils.GanetiTestCase):
self.assertRaises(errors.ConfigurationError, runtime.GetEnts,
resolver=ResolverStubRaising)
+ def testLookupForUser(self):
+ master_stub = _StubGetpwnam(constants.MASTERD_USER)
+ rapi_stub = _StubGetpwnam(constants.RAPI_USER)
+ self.assertEqual(self.resolver.LookupUid(master_stub.pw_uid),
+ constants.MASTERD_USER)
+ self.assertEqual(self.resolver.LookupUid(rapi_stub.pw_uid),
+ constants.RAPI_USER)
+ self.assertEqual(self.resolver.LookupUser(constants.MASTERD_USER),
+ master_stub.pw_uid)
+ self.assertEqual(self.resolver.LookupUser(constants.RAPI_USER),
+ rapi_stub.pw_uid)
+
+ def testLookupForGroup(self):
+ master_stub = _StubGetgrnam(constants.MASTERD_GROUP)
+ rapi_stub = _StubGetgrnam(constants.RAPI_GROUP)
+ self.assertEqual(self.resolver.LookupGid(master_stub.gr_gid),
+ constants.MASTERD_GROUP)
+ self.assertEqual(self.resolver.LookupGid(rapi_stub.gr_gid),
+ constants.RAPI_GROUP)
+
+ def testLookupForUserNotFound(self):
+ self.assertRaises(errors.ConfigurationError, self.resolver.LookupUid, 9999)
+ self.assertRaises(errors.ConfigurationError,
+ self.resolver.LookupUser, "does-not-exist-foo")
+
+ def testLookupForGroupNotFound(self):
+ self.assertRaises(errors.ConfigurationError, self.resolver.LookupGid, 9999)
+ self.assertRaises(errors.ConfigurationError,
+ self.resolver.LookupGroup, "does-not-exist-foo")
+
if __name__ == "__main__":
testutils.GanetiTestProgram()
diff --git a/test/ganeti.utils.algo_unittest.py
b/test/ganeti.utils.algo_unittest.py
index b4e3a64..96b4ff5 100755
--- a/test/ganeti.utils.algo_unittest.py
+++ b/test/ganeti.utils.algo_unittest.py
@@ -229,6 +229,13 @@ class TestNiceSort(unittest.TestCase):
None, ""])
+class TestInvertDict(unittest.TestCase):
+ def testInvertDict(self):
+ test_dict = { "foo": 1, "bar": 2, "baz": 5 }
+ self.assertEqual(algo.InvertDict(test_dict),
+ { 1: "foo", 2: "bar", 5: "baz"})
+
+
class TimeMock:
def __init__(self, values):
self.values = values
--
1.7.3.1