From cfaeaaf7db3b2289c693f48dece03a345fa6d04b Mon Sep 17 00:00:00 2001 From: Michael Hanselmann <hansmi@google.com> Date: Tue, 4 Jan 2011 17:29:50 +0100 Subject: [PATCH] baserlib: Add function for filling opcodes This function makes use of the opcode parameters which now live directly in the opcode. A number of RAPI resources can now be simplified. Signed-off-by: Michael Hanselmann <hansmi@google.com> Reviewed-by: Iustin Pop <iustin@google.com> --- Makefile.am | 1 + lib/rapi/baserlib.py | 40 +++++++++++++ test/ganeti.rapi.baserlib_unittest.py | 86 +++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100755 test/ganeti.rapi.baserlib_unittest.py diff --git a/Makefile.am b/Makefile.am index 9f1e1a65b..fab0ee8df 100644 --- a/Makefile.am +++ b/Makefile.am @@ -461,6 +461,7 @@ python_tests = \ test/ganeti.opcodes_unittest.py \ test/ganeti.qlang_unittest.py \ test/ganeti.query_unittest.py \ + test/ganeti.rapi.baserlib_unittest.py \ test/ganeti.rapi.client_unittest.py \ test/ganeti.rapi.resources_unittest.py \ test/ganeti.rapi.rlib2_unittest.py \ diff --git a/lib/rapi/baserlib.py b/lib/rapi/baserlib.py index e59681654..d30f0cddf 100644 --- a/lib/rapi/baserlib.py +++ b/lib/rapi/baserlib.py @@ -170,6 +170,46 @@ def MakeParamsDict(opts, params): return result +def FillOpcode(opcls, body, static): + """Fills an opcode with body parameters. + + Parameter types are checked. + + @type opcls: L{opcodes.OpCode} + @param opcls: Opcode class + @type body: dict + @param body: Body parameters as received from client + @type static: dict + @param static: Static parameters which can't be modified by client + @return: Opcode object + + """ + CheckType(body, dict, "Body contents") + + if static: + overwritten = set(body.keys()) & set(static.keys()) + if overwritten: + raise http.HttpBadRequest("Can't overwrite static parameters %r" % + overwritten) + + # Combine parameters + params = body.copy() + + if static: + params.update(static) + + # Convert keys to strings (simplejson decodes them as unicode) + params = dict((str(key), value) for (key, value) in params.items()) + + try: + op = opcls(**params) # pylint: disable-msg=W0142 + op.Validate(False) + except (errors.OpPrereqError, TypeError), err: + raise http.HttpBadRequest("Invalid body parameters: %s" % err) + + return op + + def SubmitJob(op, cl=None): """Generic wrapper for submit job, for better http compatibility. diff --git a/test/ganeti.rapi.baserlib_unittest.py b/test/ganeti.rapi.baserlib_unittest.py new file mode 100755 index 000000000..570636fa7 --- /dev/null +++ b/test/ganeti.rapi.baserlib_unittest.py @@ -0,0 +1,86 @@ +#!/usr/bin/python +# + +# Copyright (C) 2011 Google Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + + +"""Script for testing ganeti.rapi.baserlib""" + +import unittest + +from ganeti import errors +from ganeti import opcodes +from ganeti import ht +from ganeti import http +from ganeti.rapi import baserlib + +import testutils + + +class TestFillOpcode(unittest.TestCase): + class _TestOp(opcodes.OpCode): + OP_ID = "RAPI_TEST_OP" + OP_PARAMS = [ + ("test", None, ht.TMaybeString), + ] + + def test(self): + for static in [None, {}]: + op = baserlib.FillOpcode(self._TestOp, {}, static) + self.assertTrue(isinstance(op, self._TestOp)) + self.assertFalse(hasattr(op, "test")) + + def testStatic(self): + op = baserlib.FillOpcode(self._TestOp, {}, {"test": "abc"}) + self.assertTrue(isinstance(op, self._TestOp)) + self.assertEqual(op.test, "abc") + + # Overwrite static parameter + self.assertRaises(http.HttpBadRequest, baserlib.FillOpcode, + self._TestOp, {"test": 123}, {"test": "abc"}) + + def testType(self): + self.assertRaises(http.HttpBadRequest, baserlib.FillOpcode, + self._TestOp, {"test": [1, 2, 3]}, {}) + + def testStaticType(self): + self.assertRaises(http.HttpBadRequest, baserlib.FillOpcode, + self._TestOp, {}, {"test": [1, 2, 3]}) + + def testUnicode(self): + op = baserlib.FillOpcode(self._TestOp, {u"test": "abc"}, {}) + self.assertTrue(isinstance(op, self._TestOp)) + self.assertEqual(op.test, "abc") + + op = baserlib.FillOpcode(self._TestOp, {}, {u"test": "abc"}) + self.assertTrue(isinstance(op, self._TestOp)) + self.assertEqual(op.test, "abc") + + def testUnknownParameter(self): + self.assertRaises(http.HttpBadRequest, baserlib.FillOpcode, + self._TestOp, {"othervalue": 123}, None) + + def testInvalidBody(self): + self.assertRaises(http.HttpBadRequest, baserlib.FillOpcode, + self._TestOp, "", None) + self.assertRaises(http.HttpBadRequest, baserlib.FillOpcode, + self._TestOp, range(10), None) + + +if __name__ == "__main__": + testutils.GanetiTestProgram() -- GitLab