LUTest* are moved to test.py.

Signed-off-by: Thomas Thrainer <[email protected]>
---
 Makefile.am            |   3 +-
 lib/cmdlib/__init__.py | 342 +------------------------------------------------
 lib/cmdlib/common.py   |  38 ++++++
 lib/cmdlib/test.py     | 334 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 377 insertions(+), 340 deletions(-)
 create mode 100644 lib/cmdlib/test.py

diff --git a/Makefile.am b/Makefile.am
index 58b1869..d9de703 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -312,7 +312,8 @@ cmdlib_PYTHON = \
        lib/cmdlib/common.py \
        lib/cmdlib/base.py \
        lib/cmdlib/tags.py \
-       lib/cmdlib/network.py
+       lib/cmdlib/network.py \
+       lib/cmdlib/test.py
 
 hypervisor_PYTHON = \
        lib/hypervisor/__init__.py \
diff --git a/lib/cmdlib/__init__.py b/lib/cmdlib/__init__.py
index 88aa001..dda94ec 100644
--- a/lib/cmdlib/__init__.py
+++ b/lib/cmdlib/__init__.py
@@ -34,9 +34,6 @@ import re
 import logging
 import copy
 import OpenSSL
-import socket
-import tempfile
-import shutil
 import itertools
 import operator
 
@@ -66,11 +63,13 @@ from ganeti.masterd import iallocator
 from ganeti.cmdlib.base import ResultWithJobs, LogicalUnit, NoHooksLU, \
   Tasklet, _QueryBase
 from ganeti.cmdlib.common import _ExpandInstanceName, _ExpandItemName, \
-  _ExpandNodeName, _ShareAll, _CheckNodeGroupInstances
+  _ExpandNodeName, _ShareAll, _CheckNodeGroupInstances, _GetWantedNodes, \
+  _GetWantedInstances
 from ganeti.cmdlib.tags import LUTagsGet, LUTagsSearch, LUTagsSet, LUTagsDel
 from ganeti.cmdlib.network import LUNetworkAdd, LUNetworkRemove, \
   LUNetworkSetParams, _NetworkQuery, LUNetworkQuery, LUNetworkConnect, \
   LUNetworkDisconnect
+from ganeti.cmdlib.test import LUTestDelay, LUTestJqueue, LUTestAllocator
 
 import ganeti.masterd.instance # pylint: disable=W0611
 
@@ -214,44 +213,6 @@ def _CopyLockList(names):
     return names[:]
 
 
-def _GetWantedNodes(lu, nodes):
-  """Returns list of checked and expanded node names.
-
-  @type lu: L{LogicalUnit}
-  @param lu: the logical unit on whose behalf we execute
-  @type nodes: list
-  @param nodes: list of node names or None for all nodes
-  @rtype: list
-  @return: the list of nodes, sorted
-  @raise errors.ProgrammerError: if the nodes parameter is wrong type
-
-  """
-  if nodes:
-    return [_ExpandNodeName(lu.cfg, name) for name in nodes]
-
-  return utils.NiceSort(lu.cfg.GetNodeList())
-
-
-def _GetWantedInstances(lu, instances):
-  """Returns list of checked and expanded instance names.
-
-  @type lu: L{LogicalUnit}
-  @param lu: the logical unit on whose behalf we execute
-  @type instances: list
-  @param instances: list of instance names or None for all instances
-  @rtype: list
-  @return: the list of instances, sorted
-  @raise errors.OpPrereqError: if the instances parameter is wrong type
-  @raise errors.OpPrereqError: if any of the passed instances is not found
-
-  """
-  if instances:
-    wanted = [_ExpandInstanceName(lu.cfg, name) for name in instances]
-  else:
-    wanted = utils.NiceSort(lu.cfg.GetInstanceList())
-  return wanted
-
-
 def _GetUpdatedParams(old_params, update_dict,
                       use_default=True, use_none=False):
   """Return the new version of a parameter dictionary.
@@ -15309,54 +15270,6 @@ class LUGroupEvacuate(LogicalUnit):
     return ResultWithJobs(jobs)
 
 
-class LUTestDelay(NoHooksLU):
-  """Sleep for a specified amount of time.
-
-  This LU sleeps on the master and/or nodes for a specified amount of
-  time.
-
-  """
-  REQ_BGL = False
-
-  def ExpandNames(self):
-    """Expand names and set required locks.
-
-    This expands the node list, if any.
-
-    """
-    self.needed_locks = {}
-    if self.op.on_nodes:
-      # _GetWantedNodes can be used here, but is not always appropriate to use
-      # this way in ExpandNames. Check LogicalUnit.ExpandNames docstring for
-      # more information.
-      self.op.on_nodes = _GetWantedNodes(self, self.op.on_nodes)
-      self.needed_locks[locking.LEVEL_NODE] = self.op.on_nodes
-
-  def _TestDelay(self):
-    """Do the actual sleep.
-
-    """
-    if self.op.on_master:
-      if not utils.TestDelay(self.op.duration):
-        raise errors.OpExecError("Error during master delay test")
-    if self.op.on_nodes:
-      result = self.rpc.call_test_delay(self.op.on_nodes, self.op.duration)
-      for node, node_result in result.items():
-        node_result.Raise("Failure during rpc call to node %s" % node)
-
-  def Exec(self, feedback_fn):
-    """Execute the test delay opcode, with the wanted repetitions.
-
-    """
-    if self.op.repeat == 0:
-      self._TestDelay()
-    else:
-      top_value = self.op.repeat - 1
-      for i in range(self.op.repeat):
-        self.LogInfo("Test delay iteration %d/%d", i, top_value)
-        self._TestDelay()
-
-
 class LURestrictedCommand(NoHooksLU):
   """Logical unit for executing restricted commands.
 
@@ -15404,255 +15317,6 @@ class LURestrictedCommand(NoHooksLU):
     return result
 
 
-class LUTestJqueue(NoHooksLU):
-  """Utility LU to test some aspects of the job queue.
-
-  """
-  REQ_BGL = False
-
-  # Must be lower than default timeout for WaitForJobChange to see whether it
-  # notices changed jobs
-  _CLIENT_CONNECT_TIMEOUT = 20.0
-  _CLIENT_CONFIRM_TIMEOUT = 60.0
-
-  @classmethod
-  def _NotifyUsingSocket(cls, cb, errcls):
-    """Opens a Unix socket and waits for another program to connect.
-
-    @type cb: callable
-    @param cb: Callback to send socket name to client
-    @type errcls: class
-    @param errcls: Exception class to use for errors
-
-    """
-    # Using a temporary directory as there's no easy way to create temporary
-    # sockets without writing a custom loop around tempfile.mktemp and
-    # socket.bind
-    tmpdir = tempfile.mkdtemp()
-    try:
-      tmpsock = utils.PathJoin(tmpdir, "sock")
-
-      logging.debug("Creating temporary socket at %s", tmpsock)
-      sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-      try:
-        sock.bind(tmpsock)
-        sock.listen(1)
-
-        # Send details to client
-        cb(tmpsock)
-
-        # Wait for client to connect before continuing
-        sock.settimeout(cls._CLIENT_CONNECT_TIMEOUT)
-        try:
-          (conn, _) = sock.accept()
-        except socket.error, err:
-          raise errcls("Client didn't connect in time (%s)" % err)
-      finally:
-        sock.close()
-    finally:
-      # Remove as soon as client is connected
-      shutil.rmtree(tmpdir)
-
-    # Wait for client to close
-    try:
-      try:
-        # pylint: disable=E1101
-        # Instance of '_socketobject' has no ... member
-        conn.settimeout(cls._CLIENT_CONFIRM_TIMEOUT)
-        conn.recv(1)
-      except socket.error, err:
-        raise errcls("Client failed to confirm notification (%s)" % err)
-    finally:
-      conn.close()
-
-  def _SendNotification(self, test, arg, sockname):
-    """Sends a notification to the client.
-
-    @type test: string
-    @param test: Test name
-    @param arg: Test argument (depends on test)
-    @type sockname: string
-    @param sockname: Socket path
-
-    """
-    self.Log(constants.ELOG_JQUEUE_TEST, (sockname, test, arg))
-
-  def _Notify(self, prereq, test, arg):
-    """Notifies the client of a test.
-
-    @type prereq: bool
-    @param prereq: Whether this is a prereq-phase test
-    @type test: string
-    @param test: Test name
-    @param arg: Test argument (depends on test)
-
-    """
-    if prereq:
-      errcls = errors.OpPrereqError
-    else:
-      errcls = errors.OpExecError
-
-    return self._NotifyUsingSocket(compat.partial(self._SendNotification,
-                                                  test, arg),
-                                   errcls)
-
-  def CheckArguments(self):
-    self.checkargs_calls = getattr(self, "checkargs_calls", 0) + 1
-    self.expandnames_calls = 0
-
-  def ExpandNames(self):
-    checkargs_calls = getattr(self, "checkargs_calls", 0)
-    if checkargs_calls < 1:
-      raise errors.ProgrammerError("CheckArguments was not called")
-
-    self.expandnames_calls += 1
-
-    if self.op.notify_waitlock:
-      self._Notify(True, constants.JQT_EXPANDNAMES, None)
-
-    self.LogInfo("Expanding names")
-
-    # Get lock on master node (just to get a lock, not for a particular reason)
-    self.needed_locks = {
-      locking.LEVEL_NODE: self.cfg.GetMasterNode(),
-      }
-
-  def Exec(self, feedback_fn):
-    if self.expandnames_calls < 1:
-      raise errors.ProgrammerError("ExpandNames was not called")
-
-    if self.op.notify_exec:
-      self._Notify(False, constants.JQT_EXEC, None)
-
-    self.LogInfo("Executing")
-
-    if self.op.log_messages:
-      self._Notify(False, constants.JQT_STARTMSG, len(self.op.log_messages))
-      for idx, msg in enumerate(self.op.log_messages):
-        self.LogInfo("Sending log message %s", idx + 1)
-        feedback_fn(constants.JQT_MSGPREFIX + msg)
-        # Report how many test messages have been sent
-        self._Notify(False, constants.JQT_LOGMSG, idx + 1)
-
-    if self.op.fail:
-      raise errors.OpExecError("Opcode failure was requested")
-
-    return True
-
-
-class LUTestAllocator(NoHooksLU):
-  """Run allocator tests.
-
-  This LU runs the allocator tests
-
-  """
-  def CheckPrereq(self):
-    """Check prerequisites.
-
-    This checks the opcode parameters depending on the director and mode test.
-
-    """
-    if self.op.mode in (constants.IALLOCATOR_MODE_ALLOC,
-                        constants.IALLOCATOR_MODE_MULTI_ALLOC):
-      for attr in ["memory", "disks", "disk_template",
-                   "os", "tags", "nics", "vcpus"]:
-        if not hasattr(self.op, attr):
-          raise errors.OpPrereqError("Missing attribute '%s' on opcode input" %
-                                     attr, errors.ECODE_INVAL)
-      iname = self.cfg.ExpandInstanceName(self.op.name)
-      if iname is not None:
-        raise errors.OpPrereqError("Instance '%s' already in the cluster" %
-                                   iname, errors.ECODE_EXISTS)
-      if not isinstance(self.op.nics, list):
-        raise errors.OpPrereqError("Invalid parameter 'nics'",
-                                   errors.ECODE_INVAL)
-      if not isinstance(self.op.disks, list):
-        raise errors.OpPrereqError("Invalid parameter 'disks'",
-                                   errors.ECODE_INVAL)
-      for row in self.op.disks:
-        if (not isinstance(row, dict) or
-            constants.IDISK_SIZE not in row or
-            not isinstance(row[constants.IDISK_SIZE], int) or
-            constants.IDISK_MODE not in row or
-            row[constants.IDISK_MODE] not in constants.DISK_ACCESS_SET):
-          raise errors.OpPrereqError("Invalid contents of the 'disks'"
-                                     " parameter", errors.ECODE_INVAL)
-      if self.op.hypervisor is None:
-        self.op.hypervisor = self.cfg.GetHypervisorType()
-    elif self.op.mode == constants.IALLOCATOR_MODE_RELOC:
-      fname = _ExpandInstanceName(self.cfg, self.op.name)
-      self.op.name = fname
-      self.relocate_from = \
-          list(self.cfg.GetInstanceInfo(fname).secondary_nodes)
-    elif self.op.mode in (constants.IALLOCATOR_MODE_CHG_GROUP,
-                          constants.IALLOCATOR_MODE_NODE_EVAC):
-      if not self.op.instances:
-        raise errors.OpPrereqError("Missing instances", errors.ECODE_INVAL)
-      self.op.instances = _GetWantedInstances(self, self.op.instances)
-    else:
-      raise errors.OpPrereqError("Invalid test allocator mode '%s'" %
-                                 self.op.mode, errors.ECODE_INVAL)
-
-    if self.op.direction == constants.IALLOCATOR_DIR_OUT:
-      if self.op.iallocator is None:
-        raise errors.OpPrereqError("Missing allocator name",
-                                   errors.ECODE_INVAL)
-    elif self.op.direction != constants.IALLOCATOR_DIR_IN:
-      raise errors.OpPrereqError("Wrong allocator test '%s'" %
-                                 self.op.direction, errors.ECODE_INVAL)
-
-  def Exec(self, feedback_fn):
-    """Run the allocator test.
-
-    """
-    if self.op.mode == constants.IALLOCATOR_MODE_ALLOC:
-      req = iallocator.IAReqInstanceAlloc(name=self.op.name,
-                                          memory=self.op.memory,
-                                          disks=self.op.disks,
-                                          disk_template=self.op.disk_template,
-                                          os=self.op.os,
-                                          tags=self.op.tags,
-                                          nics=self.op.nics,
-                                          vcpus=self.op.vcpus,
-                                          spindle_use=self.op.spindle_use,
-                                          hypervisor=self.op.hypervisor,
-                                          node_whitelist=None)
-    elif self.op.mode == constants.IALLOCATOR_MODE_RELOC:
-      req = iallocator.IAReqRelocate(name=self.op.name,
-                                     relocate_from=list(self.relocate_from))
-    elif self.op.mode == constants.IALLOCATOR_MODE_CHG_GROUP:
-      req = iallocator.IAReqGroupChange(instances=self.op.instances,
-                                        target_groups=self.op.target_groups)
-    elif self.op.mode == constants.IALLOCATOR_MODE_NODE_EVAC:
-      req = iallocator.IAReqNodeEvac(instances=self.op.instances,
-                                     evac_mode=self.op.evac_mode)
-    elif self.op.mode == constants.IALLOCATOR_MODE_MULTI_ALLOC:
-      disk_template = self.op.disk_template
-      insts = [iallocator.IAReqInstanceAlloc(name="%s%s" % (self.op.name, idx),
-                                             memory=self.op.memory,
-                                             disks=self.op.disks,
-                                             disk_template=disk_template,
-                                             os=self.op.os,
-                                             tags=self.op.tags,
-                                             nics=self.op.nics,
-                                             vcpus=self.op.vcpus,
-                                             spindle_use=self.op.spindle_use,
-                                             hypervisor=self.op.hypervisor)
-               for idx in range(self.op.count)]
-      req = iallocator.IAReqMultiInstanceAlloc(instances=insts)
-    else:
-      raise errors.ProgrammerError("Uncatched mode %s in"
-                                   " LUTestAllocator.Exec", self.op.mode)
-
-    ial = iallocator.IAllocator(self.cfg, self.rpc, req)
-    if self.op.direction == constants.IALLOCATOR_DIR_IN:
-      result = ial.in_text
-    else:
-      ial.Run(self.op.iallocator, validate=False)
-      result = ial.out_text
-    return result
-
-
 #: Query type implementations
 _QUERY_IMPL = {
   constants.QR_CLUSTER: _ClusterQuery,
diff --git a/lib/cmdlib/common.py b/lib/cmdlib/common.py
index f3bd9e4..91403ad 100644
--- a/lib/cmdlib/common.py
+++ b/lib/cmdlib/common.py
@@ -82,3 +82,41 @@ def _CheckNodeGroupInstances(cfg, group_uuid, 
owned_instances):
                                errors.ECODE_STATE)
 
   return wanted_instances
+
+
+def _GetWantedNodes(lu, nodes):
+  """Returns list of checked and expanded node names.
+
+  @type lu: L{LogicalUnit}
+  @param lu: the logical unit on whose behalf we execute
+  @type nodes: list
+  @param nodes: list of node names or None for all nodes
+  @rtype: list
+  @return: the list of nodes, sorted
+  @raise errors.ProgrammerError: if the nodes parameter is wrong type
+
+  """
+  if nodes:
+    return [_ExpandNodeName(lu.cfg, name) for name in nodes]
+
+  return utils.NiceSort(lu.cfg.GetNodeList())
+
+
+def _GetWantedInstances(lu, instances):
+  """Returns list of checked and expanded instance names.
+
+  @type lu: L{LogicalUnit}
+  @param lu: the logical unit on whose behalf we execute
+  @type instances: list
+  @param instances: list of instance names or None for all instances
+  @rtype: list
+  @return: the list of instances, sorted
+  @raise errors.OpPrereqError: if the instances parameter is wrong type
+  @raise errors.OpPrereqError: if any of the passed instances is not found
+
+  """
+  if instances:
+    wanted = [_ExpandInstanceName(lu.cfg, name) for name in instances]
+  else:
+    wanted = utils.NiceSort(lu.cfg.GetInstanceList())
+  return wanted
diff --git a/lib/cmdlib/test.py b/lib/cmdlib/test.py
new file mode 100644
index 0000000..02a6749
--- /dev/null
+++ b/lib/cmdlib/test.py
@@ -0,0 +1,334 @@
+#
+#
+
+# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 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.
+
+
+"""Test logical units."""
+
+import logging
+import shutil
+import socket
+import tempfile
+
+from ganeti import compat
+from ganeti import constants
+from ganeti import errors
+from ganeti import locking
+from ganeti import utils
+from ganeti.masterd import iallocator
+from ganeti.cmdlib.base import NoHooksLU
+from ganeti.cmdlib.common import _ExpandInstanceName, _GetWantedNodes, \
+  _GetWantedInstances
+
+
+class LUTestDelay(NoHooksLU):
+  """Sleep for a specified amount of time.
+
+  This LU sleeps on the master and/or nodes for a specified amount of
+  time.
+
+  """
+  REQ_BGL = False
+
+  def ExpandNames(self):
+    """Expand names and set required locks.
+
+    This expands the node list, if any.
+
+    """
+    self.needed_locks = {}
+    if self.op.on_nodes:
+      # _GetWantedNodes can be used here, but is not always appropriate to use
+      # this way in ExpandNames. Check LogicalUnit.ExpandNames docstring for
+      # more information.
+      self.op.on_nodes = _GetWantedNodes(self, self.op.on_nodes)
+      self.needed_locks[locking.LEVEL_NODE] = self.op.on_nodes
+
+  def _TestDelay(self):
+    """Do the actual sleep.
+
+    """
+    if self.op.on_master:
+      if not utils.TestDelay(self.op.duration):
+        raise errors.OpExecError("Error during master delay test")
+    if self.op.on_nodes:
+      result = self.rpc.call_test_delay(self.op.on_nodes, self.op.duration)
+      for node, node_result in result.items():
+        node_result.Raise("Failure during rpc call to node %s" % node)
+
+  def Exec(self, feedback_fn):
+    """Execute the test delay opcode, with the wanted repetitions.
+
+    """
+    if self.op.repeat == 0:
+      self._TestDelay()
+    else:
+      top_value = self.op.repeat - 1
+      for i in range(self.op.repeat):
+        self.LogInfo("Test delay iteration %d/%d", i, top_value)
+        self._TestDelay()
+
+
+class LUTestJqueue(NoHooksLU):
+  """Utility LU to test some aspects of the job queue.
+
+  """
+  REQ_BGL = False
+
+  # Must be lower than default timeout for WaitForJobChange to see whether it
+  # notices changed jobs
+  _CLIENT_CONNECT_TIMEOUT = 20.0
+  _CLIENT_CONFIRM_TIMEOUT = 60.0
+
+  @classmethod
+  def _NotifyUsingSocket(cls, cb, errcls):
+    """Opens a Unix socket and waits for another program to connect.
+
+    @type cb: callable
+    @param cb: Callback to send socket name to client
+    @type errcls: class
+    @param errcls: Exception class to use for errors
+
+    """
+    # Using a temporary directory as there's no easy way to create temporary
+    # sockets without writing a custom loop around tempfile.mktemp and
+    # socket.bind
+    tmpdir = tempfile.mkdtemp()
+    try:
+      tmpsock = utils.PathJoin(tmpdir, "sock")
+
+      logging.debug("Creating temporary socket at %s", tmpsock)
+      sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+      try:
+        sock.bind(tmpsock)
+        sock.listen(1)
+
+        # Send details to client
+        cb(tmpsock)
+
+        # Wait for client to connect before continuing
+        sock.settimeout(cls._CLIENT_CONNECT_TIMEOUT)
+        try:
+          (conn, _) = sock.accept()
+        except socket.error, err:
+          raise errcls("Client didn't connect in time (%s)" % err)
+      finally:
+        sock.close()
+    finally:
+      # Remove as soon as client is connected
+      shutil.rmtree(tmpdir)
+
+    # Wait for client to close
+    try:
+      try:
+        # pylint: disable=E1101
+        # Instance of '_socketobject' has no ... member
+        conn.settimeout(cls._CLIENT_CONFIRM_TIMEOUT)
+        conn.recv(1)
+      except socket.error, err:
+        raise errcls("Client failed to confirm notification (%s)" % err)
+    finally:
+      conn.close()
+
+  def _SendNotification(self, test, arg, sockname):
+    """Sends a notification to the client.
+
+    @type test: string
+    @param test: Test name
+    @param arg: Test argument (depends on test)
+    @type sockname: string
+    @param sockname: Socket path
+
+    """
+    self.Log(constants.ELOG_JQUEUE_TEST, (sockname, test, arg))
+
+  def _Notify(self, prereq, test, arg):
+    """Notifies the client of a test.
+
+    @type prereq: bool
+    @param prereq: Whether this is a prereq-phase test
+    @type test: string
+    @param test: Test name
+    @param arg: Test argument (depends on test)
+
+    """
+    if prereq:
+      errcls = errors.OpPrereqError
+    else:
+      errcls = errors.OpExecError
+
+    return self._NotifyUsingSocket(compat.partial(self._SendNotification,
+                                                  test, arg),
+                                   errcls)
+
+  def CheckArguments(self):
+    self.checkargs_calls = getattr(self, "checkargs_calls", 0) + 1
+    self.expandnames_calls = 0
+
+  def ExpandNames(self):
+    checkargs_calls = getattr(self, "checkargs_calls", 0)
+    if checkargs_calls < 1:
+      raise errors.ProgrammerError("CheckArguments was not called")
+
+    self.expandnames_calls += 1
+
+    if self.op.notify_waitlock:
+      self._Notify(True, constants.JQT_EXPANDNAMES, None)
+
+    self.LogInfo("Expanding names")
+
+    # Get lock on master node (just to get a lock, not for a particular reason)
+    self.needed_locks = {
+      locking.LEVEL_NODE: self.cfg.GetMasterNode(),
+      }
+
+  def Exec(self, feedback_fn):
+    if self.expandnames_calls < 1:
+      raise errors.ProgrammerError("ExpandNames was not called")
+
+    if self.op.notify_exec:
+      self._Notify(False, constants.JQT_EXEC, None)
+
+    self.LogInfo("Executing")
+
+    if self.op.log_messages:
+      self._Notify(False, constants.JQT_STARTMSG, len(self.op.log_messages))
+      for idx, msg in enumerate(self.op.log_messages):
+        self.LogInfo("Sending log message %s", idx + 1)
+        feedback_fn(constants.JQT_MSGPREFIX + msg)
+        # Report how many test messages have been sent
+        self._Notify(False, constants.JQT_LOGMSG, idx + 1)
+
+    if self.op.fail:
+      raise errors.OpExecError("Opcode failure was requested")
+
+    return True
+
+
+class LUTestAllocator(NoHooksLU):
+  """Run allocator tests.
+
+  This LU runs the allocator tests
+
+  """
+  def CheckPrereq(self):
+    """Check prerequisites.
+
+    This checks the opcode parameters depending on the director and mode test.
+
+    """
+    if self.op.mode in (constants.IALLOCATOR_MODE_ALLOC,
+                        constants.IALLOCATOR_MODE_MULTI_ALLOC):
+      for attr in ["memory", "disks", "disk_template",
+                   "os", "tags", "nics", "vcpus"]:
+        if not hasattr(self.op, attr):
+          raise errors.OpPrereqError("Missing attribute '%s' on opcode input" %
+                                     attr, errors.ECODE_INVAL)
+      iname = self.cfg.ExpandInstanceName(self.op.name)
+      if iname is not None:
+        raise errors.OpPrereqError("Instance '%s' already in the cluster" %
+                                   iname, errors.ECODE_EXISTS)
+      if not isinstance(self.op.nics, list):
+        raise errors.OpPrereqError("Invalid parameter 'nics'",
+                                   errors.ECODE_INVAL)
+      if not isinstance(self.op.disks, list):
+        raise errors.OpPrereqError("Invalid parameter 'disks'",
+                                   errors.ECODE_INVAL)
+      for row in self.op.disks:
+        if (not isinstance(row, dict) or
+            constants.IDISK_SIZE not in row or
+            not isinstance(row[constants.IDISK_SIZE], int) or
+            constants.IDISK_MODE not in row or
+            row[constants.IDISK_MODE] not in constants.DISK_ACCESS_SET):
+          raise errors.OpPrereqError("Invalid contents of the 'disks'"
+                                     " parameter", errors.ECODE_INVAL)
+      if self.op.hypervisor is None:
+        self.op.hypervisor = self.cfg.GetHypervisorType()
+    elif self.op.mode == constants.IALLOCATOR_MODE_RELOC:
+      fname = _ExpandInstanceName(self.cfg, self.op.name)
+      self.op.name = fname
+      self.relocate_from = \
+          list(self.cfg.GetInstanceInfo(fname).secondary_nodes)
+    elif self.op.mode in (constants.IALLOCATOR_MODE_CHG_GROUP,
+                          constants.IALLOCATOR_MODE_NODE_EVAC):
+      if not self.op.instances:
+        raise errors.OpPrereqError("Missing instances", errors.ECODE_INVAL)
+      self.op.instances = _GetWantedInstances(self, self.op.instances)
+    else:
+      raise errors.OpPrereqError("Invalid test allocator mode '%s'" %
+                                 self.op.mode, errors.ECODE_INVAL)
+
+    if self.op.direction == constants.IALLOCATOR_DIR_OUT:
+      if self.op.iallocator is None:
+        raise errors.OpPrereqError("Missing allocator name",
+                                   errors.ECODE_INVAL)
+    elif self.op.direction != constants.IALLOCATOR_DIR_IN:
+      raise errors.OpPrereqError("Wrong allocator test '%s'" %
+                                 self.op.direction, errors.ECODE_INVAL)
+
+  def Exec(self, feedback_fn):
+    """Run the allocator test.
+
+    """
+    if self.op.mode == constants.IALLOCATOR_MODE_ALLOC:
+      req = iallocator.IAReqInstanceAlloc(name=self.op.name,
+                                          memory=self.op.memory,
+                                          disks=self.op.disks,
+                                          disk_template=self.op.disk_template,
+                                          os=self.op.os,
+                                          tags=self.op.tags,
+                                          nics=self.op.nics,
+                                          vcpus=self.op.vcpus,
+                                          spindle_use=self.op.spindle_use,
+                                          hypervisor=self.op.hypervisor,
+                                          node_whitelist=None)
+    elif self.op.mode == constants.IALLOCATOR_MODE_RELOC:
+      req = iallocator.IAReqRelocate(name=self.op.name,
+                                     relocate_from=list(self.relocate_from))
+    elif self.op.mode == constants.IALLOCATOR_MODE_CHG_GROUP:
+      req = iallocator.IAReqGroupChange(instances=self.op.instances,
+                                        target_groups=self.op.target_groups)
+    elif self.op.mode == constants.IALLOCATOR_MODE_NODE_EVAC:
+      req = iallocator.IAReqNodeEvac(instances=self.op.instances,
+                                     evac_mode=self.op.evac_mode)
+    elif self.op.mode == constants.IALLOCATOR_MODE_MULTI_ALLOC:
+      disk_template = self.op.disk_template
+      insts = [iallocator.IAReqInstanceAlloc(name="%s%s" % (self.op.name, idx),
+                                             memory=self.op.memory,
+                                             disks=self.op.disks,
+                                             disk_template=disk_template,
+                                             os=self.op.os,
+                                             tags=self.op.tags,
+                                             nics=self.op.nics,
+                                             vcpus=self.op.vcpus,
+                                             spindle_use=self.op.spindle_use,
+                                             hypervisor=self.op.hypervisor)
+               for idx in range(self.op.count)]
+      req = iallocator.IAReqMultiInstanceAlloc(instances=insts)
+    else:
+      raise errors.ProgrammerError("Uncatched mode %s in"
+                                   " LUTestAllocator.Exec", self.op.mode)
+
+    ial = iallocator.IAllocator(self.cfg, self.rpc, req)
+    if self.op.direction == constants.IALLOCATOR_DIR_IN:
+      result = ial.in_text
+    else:
+      ial.Run(self.op.iallocator, validate=False)
+      result = ial.out_text
+    return result
-- 
1.8.2.1

Reply via email to