# pylint: disable-msg=R0903
import logging
+import re
from ganeti import constants
from ganeti import errors
#: List of tag strings
_PTags = ("tags", ht.NoDefault, ht.TListOf(ht.TNonEmptyString))
+#: OP_ID conversion regular expression
+_OPID_RE = re.compile("([a-z])([A-Z])")
+
+
+def _NameToId(name):
+ """Convert an opcode class name to an OP_ID.
+
+ @type name: string
+ @param name: the class name, as OpXxxYyy
+ @rtype: string
+ @return: the name in the OP_XXXX_YYYY format
+
+ """
+ if not name.startswith("Op"):
+ return None
+ # Note: (?<=[a-z])(?=[A-Z]) would be ideal, since it wouldn't
+ # consume any input, and hence we would just have all the elements
+ # in the list, one by one; but it seems that split doesn't work on
+ # non-consuming input, hence we have to process the input string a
+ # bit
+ name = _OPID_RE.sub(r"\1,\2", name)
+ elems = name.split(",")
+ return "_".join(n.upper() for n in elems)
+
def RequireFileStorage():
"""Checks that file storage is enabled.
"""
assert "__slots__" not in attrs, \
"Class '%s' defines __slots__ when it should use OP_PARAMS" % name
- assert "OP_ID" in attrs, "Class '%s' is missing OP_ID attribute" % name
+
+ op_id = _NameToId(name)
+ if "OP_ID" in attrs:
+ assert attrs["OP_ID"] == op_id, ("Class '%s' defining wrong OP_ID"
+ " attribute %s, should be %s" %
+ (name, attrs["OP_ID"], op_id))
+
+ attrs["OP_ID"] = op_id
# Always set OP_PARAMS to avoid duplicates in BaseOpCode.GetAllParams
params = attrs.setdefault("OP_PARAMS", [])
@ivar priority: Opcode priority for queue
"""
- OP_ID = "OP_ABSTRACT"
+ OP_ID = "OP_CODE"
WITH_LU = True
OP_PARAMS = [
("dry_run", None, ht.TMaybeBool),
def Summary(self):
"""Generates a summary description of this opcode.
- The summary is the value of the OP_ID attribute (without the "OP_" prefix),
- plus the value of the OP_DSC_FIELD attribute, if one was defined; this field
- should allow to easily identify the operation (for an instance creation job,
- e.g., it would be the instance name).
+ The summary is the value of the OP_ID attribute (without the "OP_"
+ prefix), plus the value of the OP_DSC_FIELD attribute, if one was
+ defined; this field should allow to easily identify the operation
+ (for an instance creation job, e.g., it would be the instance
+ name).
"""
+ assert self.OP_ID is not None and len(self.OP_ID) > 3
# all OP_ID start with OP_, we remove that
txt = self.OP_ID[3:]
field_name = getattr(self, "OP_DSC_FIELD", None)
#!/usr/bin/python
#
-# Copyright (C) 2008 Google Inc.
+# Copyright (C) 2008, 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
self.cfg = mocks.FakeConfig()
self.op = opcode
- class TestOpcode(opcodes.OpCode):
- OP_ID = "OP_TEST"
- OP_PARAMS = [
+ class OpTest(opcodes.OpCode):
+ OP_PARAMS = [
("iallocator", None, ht.NoType),
("node", None, ht.NoType),
]
default_iallocator = mocks.FakeConfig().GetDefaultIAllocator()
other_iallocator = default_iallocator + "_not"
- op = TestOpcode()
+ op = OpTest()
lu = TestLU(op)
c_i = lambda: cmdlib._CheckIAllocatorOrNode(lu, "iallocator", "node")
self.assert_(cls.OP_ID.startswith("OP_"))
self.assert_(len(cls.OP_ID) > 3)
self.assertEqual(cls.OP_ID, cls.OP_ID.upper())
+ self.assertEqual(cls.OP_ID, opcodes._NameToId(cls.__name__))
self.assertRaises(TypeError, cls, unsupported_parameter="some value")
self.assertEqual("OP_%s" % summary, op.OP_ID)
def testSummary(self):
- class _TestOp(opcodes.OpCode):
- OP_ID = "OP_TEST"
+ class OpTest(opcodes.OpCode):
OP_DSC_FIELD = "data"
OP_PARAMS = [
("data", ht.NoDefault, ht.TString),
]
- self.assertEqual(_TestOp(data="").Summary(), "TEST()")
- self.assertEqual(_TestOp(data="Hello World").Summary(),
+ self.assertEqual(OpTest(data="").Summary(), "TEST()")
+ self.assertEqual(OpTest(data="Hello World").Summary(),
"TEST(Hello World)")
- self.assertEqual(_TestOp(data="node1.example.com").Summary(),
+ self.assertEqual(OpTest(data="node1.example.com").Summary(),
"TEST(node1.example.com)")
def testListSummary(self):
- class _TestOp(opcodes.OpCode):
- OP_ID = "OP_TEST"
+ class OpTest(opcodes.OpCode):
OP_DSC_FIELD = "data"
OP_PARAMS = [
("data", ht.NoDefault, ht.TList),
]
- self.assertEqual(_TestOp(data=["a", "b", "c"]).Summary(),
+ self.assertEqual(OpTest(data=["a", "b", "c"]).Summary(),
"TEST(a,b,c)")
- self.assertEqual(_TestOp(data=["a", None, "c"]).Summary(),
+ self.assertEqual(OpTest(data=["a", None, "c"]).Summary(),
"TEST(a,None,c)")
- self.assertEqual(_TestOp(data=[1, 2, 3, 4]).Summary(), "TEST(1,2,3,4)")
+ self.assertEqual(OpTest(data=[1, 2, 3, 4]).Summary(), "TEST(1,2,3,4)")
def testOpId(self):
self.assertFalse(utils.FindDuplicates(cls.OP_ID
msg="Default value returned by function is callable")
def testValidateNoModification(self):
- class _TestOp(opcodes.OpCode):
- OP_ID = "OP_TEST"
+ class OpTest(opcodes.OpCode):
OP_PARAMS = [
("nodef", ht.NoDefault, ht.TMaybeString),
("wdef", "default", ht.TMaybeString),
]
# Missing required parameter "nodef"
- op = _TestOp()
+ op = OpTest()
before = op.__getstate__()
self.assertRaises(errors.OpPrereqError, op.Validate, False)
self.assertFalse(hasattr(op, "nodef"))
self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
# Required parameter "nodef" is provided
- op = _TestOp(nodef="foo")
+ op = OpTest(nodef="foo")
before = op.__getstate__()
op.Validate(False)
self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
self.assertFalse(hasattr(op, "notype"))
# Missing required parameter "nodef"
- op = _TestOp(wdef="hello", number=999)
+ op = OpTest(wdef="hello", number=999)
before = op.__getstate__()
self.assertRaises(errors.OpPrereqError, op.Validate, False)
self.assertFalse(hasattr(op, "nodef"))
self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
# Wrong type for "nodef"
- op = _TestOp(nodef=987)
+ op = OpTest(nodef=987)
before = op.__getstate__()
self.assertRaises(errors.OpPrereqError, op.Validate, False)
self.assertEqual(op.nodef, 987)
self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
# Testing different types for "notype"
- op = _TestOp(nodef="foo", notype=[1, 2, 3])
+ op = OpTest(nodef="foo", notype=[1, 2, 3])
before = op.__getstate__()
op.Validate(False)
self.assertEqual(op.nodef, "foo")
self.assertEqual(op.notype, [1, 2, 3])
self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
- op = _TestOp(nodef="foo", notype="Hello World")
+ op = OpTest(nodef="foo", notype="Hello World")
before = op.__getstate__()
op.Validate(False)
self.assertEqual(op.nodef, "foo")
self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
def testValidateSetDefaults(self):
- class _TestOp(opcodes.OpCode):
- OP_ID = "OP_TEST"
+ class OpTest(opcodes.OpCode):
OP_PARAMS = [
# Static default value
("value1", "default", ht.TMaybeString),
("value2", lambda: "result", ht.TMaybeString),
]
- op = _TestOp()
+ op = OpTest()
before = op.__getstate__()
op.Validate(True)
self.assertNotEqual(op.__getstate__(), before,
self.assert_(op.debug_level is None)
self.assertEqual(op.priority, constants.OP_PRIO_DEFAULT)
- op = _TestOp(value1="hello", value2="world", debug_level=123)
+ op = OpTest(value1="hello", value2="world", debug_level=123)
before = op.__getstate__()
op.Validate(True)
self.assertNotEqual(op.__getstate__(), before,
class TestFillOpcode(unittest.TestCase):
- class _TestOp(opcodes.OpCode):
- OP_ID = "RAPI_TEST_OP"
+ class OpTest(opcodes.OpCode):
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))
+ op = baserlib.FillOpcode(self.OpTest, {}, static)
+ self.assertTrue(isinstance(op, self.OpTest))
self.assertFalse(hasattr(op, "test"))
def testStatic(self):
- op = baserlib.FillOpcode(self._TestOp, {}, {"test": "abc"})
- self.assertTrue(isinstance(op, self._TestOp))
+ op = baserlib.FillOpcode(self.OpTest, {}, {"test": "abc"})
+ self.assertTrue(isinstance(op, self.OpTest))
self.assertEqual(op.test, "abc")
# Overwrite static parameter
self.assertRaises(http.HttpBadRequest, baserlib.FillOpcode,
- self._TestOp, {"test": 123}, {"test": "abc"})
+ self.OpTest, {"test": 123}, {"test": "abc"})
def testType(self):
self.assertRaises(http.HttpBadRequest, baserlib.FillOpcode,
- self._TestOp, {"test": [1, 2, 3]}, {})
+ self.OpTest, {"test": [1, 2, 3]}, {})
def testStaticType(self):
self.assertRaises(http.HttpBadRequest, baserlib.FillOpcode,
- self._TestOp, {}, {"test": [1, 2, 3]})
+ self.OpTest, {}, {"test": [1, 2, 3]})
def testUnicode(self):
- op = baserlib.FillOpcode(self._TestOp, {u"test": "abc"}, {})
- self.assertTrue(isinstance(op, self._TestOp))
+ op = baserlib.FillOpcode(self.OpTest, {u"test": "abc"}, {})
+ self.assertTrue(isinstance(op, self.OpTest))
self.assertEqual(op.test, "abc")
- op = baserlib.FillOpcode(self._TestOp, {}, {u"test": "abc"})
- self.assertTrue(isinstance(op, self._TestOp))
+ op = baserlib.FillOpcode(self.OpTest, {}, {u"test": "abc"})
+ self.assertTrue(isinstance(op, self.OpTest))
self.assertEqual(op.test, "abc")
def testUnknownParameter(self):
self.assertRaises(http.HttpBadRequest, baserlib.FillOpcode,
- self._TestOp, {"othervalue": 123}, None)
+ self.OpTest, {"othervalue": 123}, None)
def testInvalidBody(self):
self.assertRaises(http.HttpBadRequest, baserlib.FillOpcode,
- self._TestOp, "", None)
+ self.OpTest, "", None)
self.assertRaises(http.HttpBadRequest, baserlib.FillOpcode,
- self._TestOp, range(10), None)
+ self.OpTest, range(10), None)
if __name__ == "__main__":