Statistics
| Branch: | Tag: | Revision:

root / lib / cmdlib / test.py @ ec3a7362

History | View | Annotate | Download (11.7 kB)

1 1d870e0d Thomas Thrainer
#
2 1d870e0d Thomas Thrainer
#
3 1d870e0d Thomas Thrainer
4 054a9d17 Hrvoje Ribicic
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Google Inc.
5 1d870e0d Thomas Thrainer
#
6 1d870e0d Thomas Thrainer
# This program is free software; you can redistribute it and/or modify
7 1d870e0d Thomas Thrainer
# it under the terms of the GNU General Public License as published by
8 1d870e0d Thomas Thrainer
# the Free Software Foundation; either version 2 of the License, or
9 1d870e0d Thomas Thrainer
# (at your option) any later version.
10 1d870e0d Thomas Thrainer
#
11 1d870e0d Thomas Thrainer
# This program is distributed in the hope that it will be useful, but
12 1d870e0d Thomas Thrainer
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 1d870e0d Thomas Thrainer
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 1d870e0d Thomas Thrainer
# General Public License for more details.
15 1d870e0d Thomas Thrainer
#
16 1d870e0d Thomas Thrainer
# You should have received a copy of the GNU General Public License
17 1d870e0d Thomas Thrainer
# along with this program; if not, write to the Free Software
18 1d870e0d Thomas Thrainer
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 1d870e0d Thomas Thrainer
# 02110-1301, USA.
20 1d870e0d Thomas Thrainer
21 1d870e0d Thomas Thrainer
22 1d870e0d Thomas Thrainer
"""Test logical units."""
23 1d870e0d Thomas Thrainer
24 1d870e0d Thomas Thrainer
import logging
25 1d870e0d Thomas Thrainer
import shutil
26 1d870e0d Thomas Thrainer
import socket
27 1d870e0d Thomas Thrainer
import tempfile
28 1d870e0d Thomas Thrainer
29 1d870e0d Thomas Thrainer
from ganeti import compat
30 1d870e0d Thomas Thrainer
from ganeti import constants
31 1d870e0d Thomas Thrainer
from ganeti import errors
32 1d870e0d Thomas Thrainer
from ganeti import locking
33 1d870e0d Thomas Thrainer
from ganeti import utils
34 1d870e0d Thomas Thrainer
from ganeti.masterd import iallocator
35 1d870e0d Thomas Thrainer
from ganeti.cmdlib.base import NoHooksLU
36 da4a52a3 Thomas Thrainer
from ganeti.cmdlib.common import ExpandInstanceUuidAndName, GetWantedNodes, \
37 5eacbcae Thomas Thrainer
  GetWantedInstances
38 1d870e0d Thomas Thrainer
39 1d870e0d Thomas Thrainer
40 1d870e0d Thomas Thrainer
class LUTestDelay(NoHooksLU):
41 1d870e0d Thomas Thrainer
  """Sleep for a specified amount of time.
42 1d870e0d Thomas Thrainer

43 1d870e0d Thomas Thrainer
  This LU sleeps on the master and/or nodes for a specified amount of
44 1d870e0d Thomas Thrainer
  time.
45 1d870e0d Thomas Thrainer

46 1d870e0d Thomas Thrainer
  """
47 1d870e0d Thomas Thrainer
  REQ_BGL = False
48 1d870e0d Thomas Thrainer
49 1d870e0d Thomas Thrainer
  def ExpandNames(self):
50 1d870e0d Thomas Thrainer
    """Expand names and set required locks.
51 1d870e0d Thomas Thrainer

52 1d870e0d Thomas Thrainer
    This expands the node list, if any.
53 1d870e0d Thomas Thrainer

54 1d870e0d Thomas Thrainer
    """
55 1d870e0d Thomas Thrainer
    self.needed_locks = {}
56 054a9d17 Hrvoje Ribicic
57 054a9d17 Hrvoje Ribicic
    if self.op.on_nodes or self.op.on_master:
58 054a9d17 Hrvoje Ribicic
      self.needed_locks[locking.LEVEL_NODE] = []
59 054a9d17 Hrvoje Ribicic
60 1d870e0d Thomas Thrainer
    if self.op.on_nodes:
61 1d870e0d Thomas Thrainer
      # _GetWantedNodes can be used here, but is not always appropriate to use
62 1d870e0d Thomas Thrainer
      # this way in ExpandNames. Check LogicalUnit.ExpandNames docstring for
63 1d870e0d Thomas Thrainer
      # more information.
64 1c3231aa Thomas Thrainer
      (self.op.on_node_uuids, self.op.on_nodes) = \
65 1c3231aa Thomas Thrainer
        GetWantedNodes(self, self.op.on_nodes)
66 5a93930f Klaus Aehlig
      self.needed_locks[locking.LEVEL_NODE].extend(self.op.on_node_uuids)
67 054a9d17 Hrvoje Ribicic
68 054a9d17 Hrvoje Ribicic
    if self.op.on_master:
69 054a9d17 Hrvoje Ribicic
      # The node lock should be acquired for the master as well.
70 054a9d17 Hrvoje Ribicic
      self.needed_locks[locking.LEVEL_NODE].append(self.cfg.GetMasterNode())
71 1d870e0d Thomas Thrainer
72 1d870e0d Thomas Thrainer
  def _TestDelay(self):
73 1d870e0d Thomas Thrainer
    """Do the actual sleep.
74 1d870e0d Thomas Thrainer

75 1d870e0d Thomas Thrainer
    """
76 1d870e0d Thomas Thrainer
    if self.op.on_master:
77 3efa7659 Thomas Thrainer
      if not utils.TestDelay(self.op.duration)[0]:
78 1d870e0d Thomas Thrainer
        raise errors.OpExecError("Error during master delay test")
79 1c3231aa Thomas Thrainer
    if self.op.on_node_uuids:
80 1c3231aa Thomas Thrainer
      result = self.rpc.call_test_delay(self.op.on_node_uuids, self.op.duration)
81 1c3231aa Thomas Thrainer
      for node_uuid, node_result in result.items():
82 1c3231aa Thomas Thrainer
        node_result.Raise("Failure during rpc call to node %s" %
83 1c3231aa Thomas Thrainer
                          self.cfg.GetNodeName(node_uuid))
84 1d870e0d Thomas Thrainer
85 1d870e0d Thomas Thrainer
  def Exec(self, feedback_fn):
86 1d870e0d Thomas Thrainer
    """Execute the test delay opcode, with the wanted repetitions.
87 1d870e0d Thomas Thrainer

88 1d870e0d Thomas Thrainer
    """
89 1d870e0d Thomas Thrainer
    if self.op.repeat == 0:
90 1d870e0d Thomas Thrainer
      self._TestDelay()
91 1d870e0d Thomas Thrainer
    else:
92 1d870e0d Thomas Thrainer
      top_value = self.op.repeat - 1
93 1d870e0d Thomas Thrainer
      for i in range(self.op.repeat):
94 1d870e0d Thomas Thrainer
        self.LogInfo("Test delay iteration %d/%d", i, top_value)
95 1d870e0d Thomas Thrainer
        self._TestDelay()
96 1d870e0d Thomas Thrainer
97 1d870e0d Thomas Thrainer
98 1d870e0d Thomas Thrainer
class LUTestJqueue(NoHooksLU):
99 1d870e0d Thomas Thrainer
  """Utility LU to test some aspects of the job queue.
100 1d870e0d Thomas Thrainer

101 1d870e0d Thomas Thrainer
  """
102 1d870e0d Thomas Thrainer
  REQ_BGL = False
103 1d870e0d Thomas Thrainer
104 1d870e0d Thomas Thrainer
  # Must be lower than default timeout for WaitForJobChange to see whether it
105 1d870e0d Thomas Thrainer
  # notices changed jobs
106 1d870e0d Thomas Thrainer
  _CLIENT_CONNECT_TIMEOUT = 20.0
107 1d870e0d Thomas Thrainer
  _CLIENT_CONFIRM_TIMEOUT = 60.0
108 1d870e0d Thomas Thrainer
109 1d870e0d Thomas Thrainer
  @classmethod
110 1d870e0d Thomas Thrainer
  def _NotifyUsingSocket(cls, cb, errcls):
111 1d870e0d Thomas Thrainer
    """Opens a Unix socket and waits for another program to connect.
112 1d870e0d Thomas Thrainer

113 1d870e0d Thomas Thrainer
    @type cb: callable
114 1d870e0d Thomas Thrainer
    @param cb: Callback to send socket name to client
115 1d870e0d Thomas Thrainer
    @type errcls: class
116 1d870e0d Thomas Thrainer
    @param errcls: Exception class to use for errors
117 1d870e0d Thomas Thrainer

118 1d870e0d Thomas Thrainer
    """
119 1d870e0d Thomas Thrainer
    # Using a temporary directory as there's no easy way to create temporary
120 1d870e0d Thomas Thrainer
    # sockets without writing a custom loop around tempfile.mktemp and
121 1d870e0d Thomas Thrainer
    # socket.bind
122 1d870e0d Thomas Thrainer
    tmpdir = tempfile.mkdtemp()
123 1d870e0d Thomas Thrainer
    try:
124 1d870e0d Thomas Thrainer
      tmpsock = utils.PathJoin(tmpdir, "sock")
125 1d870e0d Thomas Thrainer
126 1d870e0d Thomas Thrainer
      logging.debug("Creating temporary socket at %s", tmpsock)
127 1d870e0d Thomas Thrainer
      sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
128 1d870e0d Thomas Thrainer
      try:
129 1d870e0d Thomas Thrainer
        sock.bind(tmpsock)
130 1d870e0d Thomas Thrainer
        sock.listen(1)
131 1d870e0d Thomas Thrainer
132 1d870e0d Thomas Thrainer
        # Send details to client
133 1d870e0d Thomas Thrainer
        cb(tmpsock)
134 1d870e0d Thomas Thrainer
135 1d870e0d Thomas Thrainer
        # Wait for client to connect before continuing
136 1d870e0d Thomas Thrainer
        sock.settimeout(cls._CLIENT_CONNECT_TIMEOUT)
137 1d870e0d Thomas Thrainer
        try:
138 1d870e0d Thomas Thrainer
          (conn, _) = sock.accept()
139 1d870e0d Thomas Thrainer
        except socket.error, err:
140 1d870e0d Thomas Thrainer
          raise errcls("Client didn't connect in time (%s)" % err)
141 1d870e0d Thomas Thrainer
      finally:
142 1d870e0d Thomas Thrainer
        sock.close()
143 1d870e0d Thomas Thrainer
    finally:
144 1d870e0d Thomas Thrainer
      # Remove as soon as client is connected
145 1d870e0d Thomas Thrainer
      shutil.rmtree(tmpdir)
146 1d870e0d Thomas Thrainer
147 1d870e0d Thomas Thrainer
    # Wait for client to close
148 1d870e0d Thomas Thrainer
    try:
149 1d870e0d Thomas Thrainer
      try:
150 1d870e0d Thomas Thrainer
        # pylint: disable=E1101
151 1d870e0d Thomas Thrainer
        # Instance of '_socketobject' has no ... member
152 1d870e0d Thomas Thrainer
        conn.settimeout(cls._CLIENT_CONFIRM_TIMEOUT)
153 1d870e0d Thomas Thrainer
        conn.recv(1)
154 1d870e0d Thomas Thrainer
      except socket.error, err:
155 1d870e0d Thomas Thrainer
        raise errcls("Client failed to confirm notification (%s)" % err)
156 1d870e0d Thomas Thrainer
    finally:
157 1d870e0d Thomas Thrainer
      conn.close()
158 1d870e0d Thomas Thrainer
159 1d870e0d Thomas Thrainer
  def _SendNotification(self, test, arg, sockname):
160 1d870e0d Thomas Thrainer
    """Sends a notification to the client.
161 1d870e0d Thomas Thrainer

162 1d870e0d Thomas Thrainer
    @type test: string
163 1d870e0d Thomas Thrainer
    @param test: Test name
164 1d870e0d Thomas Thrainer
    @param arg: Test argument (depends on test)
165 1d870e0d Thomas Thrainer
    @type sockname: string
166 1d870e0d Thomas Thrainer
    @param sockname: Socket path
167 1d870e0d Thomas Thrainer

168 1d870e0d Thomas Thrainer
    """
169 1d870e0d Thomas Thrainer
    self.Log(constants.ELOG_JQUEUE_TEST, (sockname, test, arg))
170 1d870e0d Thomas Thrainer
171 1d870e0d Thomas Thrainer
  def _Notify(self, prereq, test, arg):
172 1d870e0d Thomas Thrainer
    """Notifies the client of a test.
173 1d870e0d Thomas Thrainer

174 1d870e0d Thomas Thrainer
    @type prereq: bool
175 1d870e0d Thomas Thrainer
    @param prereq: Whether this is a prereq-phase test
176 1d870e0d Thomas Thrainer
    @type test: string
177 1d870e0d Thomas Thrainer
    @param test: Test name
178 1d870e0d Thomas Thrainer
    @param arg: Test argument (depends on test)
179 1d870e0d Thomas Thrainer

180 1d870e0d Thomas Thrainer
    """
181 1d870e0d Thomas Thrainer
    if prereq:
182 1d870e0d Thomas Thrainer
      errcls = errors.OpPrereqError
183 1d870e0d Thomas Thrainer
    else:
184 1d870e0d Thomas Thrainer
      errcls = errors.OpExecError
185 1d870e0d Thomas Thrainer
186 1d870e0d Thomas Thrainer
    return self._NotifyUsingSocket(compat.partial(self._SendNotification,
187 1d870e0d Thomas Thrainer
                                                  test, arg),
188 1d870e0d Thomas Thrainer
                                   errcls)
189 1d870e0d Thomas Thrainer
190 1d870e0d Thomas Thrainer
  def CheckArguments(self):
191 1d870e0d Thomas Thrainer
    self.checkargs_calls = getattr(self, "checkargs_calls", 0) + 1
192 1d870e0d Thomas Thrainer
    self.expandnames_calls = 0
193 1d870e0d Thomas Thrainer
194 1d870e0d Thomas Thrainer
  def ExpandNames(self):
195 1d870e0d Thomas Thrainer
    checkargs_calls = getattr(self, "checkargs_calls", 0)
196 1d870e0d Thomas Thrainer
    if checkargs_calls < 1:
197 1d870e0d Thomas Thrainer
      raise errors.ProgrammerError("CheckArguments was not called")
198 1d870e0d Thomas Thrainer
199 1d870e0d Thomas Thrainer
    self.expandnames_calls += 1
200 1d870e0d Thomas Thrainer
201 1d870e0d Thomas Thrainer
    if self.op.notify_waitlock:
202 1d870e0d Thomas Thrainer
      self._Notify(True, constants.JQT_EXPANDNAMES, None)
203 1d870e0d Thomas Thrainer
204 1d870e0d Thomas Thrainer
    self.LogInfo("Expanding names")
205 1d870e0d Thomas Thrainer
206 1d870e0d Thomas Thrainer
    # Get lock on master node (just to get a lock, not for a particular reason)
207 1d870e0d Thomas Thrainer
    self.needed_locks = {
208 1d870e0d Thomas Thrainer
      locking.LEVEL_NODE: self.cfg.GetMasterNode(),
209 1d870e0d Thomas Thrainer
      }
210 1d870e0d Thomas Thrainer
211 1d870e0d Thomas Thrainer
  def Exec(self, feedback_fn):
212 1d870e0d Thomas Thrainer
    if self.expandnames_calls < 1:
213 1d870e0d Thomas Thrainer
      raise errors.ProgrammerError("ExpandNames was not called")
214 1d870e0d Thomas Thrainer
215 1d870e0d Thomas Thrainer
    if self.op.notify_exec:
216 1d870e0d Thomas Thrainer
      self._Notify(False, constants.JQT_EXEC, None)
217 1d870e0d Thomas Thrainer
218 1d870e0d Thomas Thrainer
    self.LogInfo("Executing")
219 1d870e0d Thomas Thrainer
220 1d870e0d Thomas Thrainer
    if self.op.log_messages:
221 1d870e0d Thomas Thrainer
      self._Notify(False, constants.JQT_STARTMSG, len(self.op.log_messages))
222 1d870e0d Thomas Thrainer
      for idx, msg in enumerate(self.op.log_messages):
223 1d870e0d Thomas Thrainer
        self.LogInfo("Sending log message %s", idx + 1)
224 1d870e0d Thomas Thrainer
        feedback_fn(constants.JQT_MSGPREFIX + msg)
225 1d870e0d Thomas Thrainer
        # Report how many test messages have been sent
226 1d870e0d Thomas Thrainer
        self._Notify(False, constants.JQT_LOGMSG, idx + 1)
227 1d870e0d Thomas Thrainer
228 1d870e0d Thomas Thrainer
    if self.op.fail:
229 1d870e0d Thomas Thrainer
      raise errors.OpExecError("Opcode failure was requested")
230 1d870e0d Thomas Thrainer
231 1d870e0d Thomas Thrainer
    return True
232 1d870e0d Thomas Thrainer
233 1d870e0d Thomas Thrainer
234 1d870e0d Thomas Thrainer
class LUTestAllocator(NoHooksLU):
235 1d870e0d Thomas Thrainer
  """Run allocator tests.
236 1d870e0d Thomas Thrainer

237 1d870e0d Thomas Thrainer
  This LU runs the allocator tests
238 1d870e0d Thomas Thrainer

239 1d870e0d Thomas Thrainer
  """
240 1d870e0d Thomas Thrainer
  def CheckPrereq(self):
241 1d870e0d Thomas Thrainer
    """Check prerequisites.
242 1d870e0d Thomas Thrainer

243 1d870e0d Thomas Thrainer
    This checks the opcode parameters depending on the director and mode test.
244 1d870e0d Thomas Thrainer

245 1d870e0d Thomas Thrainer
    """
246 1d870e0d Thomas Thrainer
    if self.op.mode in (constants.IALLOCATOR_MODE_ALLOC,
247 1d870e0d Thomas Thrainer
                        constants.IALLOCATOR_MODE_MULTI_ALLOC):
248 da4a52a3 Thomas Thrainer
      (self.inst_uuid, iname) = self.cfg.ExpandInstanceName(self.op.name)
249 1d870e0d Thomas Thrainer
      if iname is not None:
250 1d870e0d Thomas Thrainer
        raise errors.OpPrereqError("Instance '%s' already in the cluster" %
251 1d870e0d Thomas Thrainer
                                   iname, errors.ECODE_EXISTS)
252 1d870e0d Thomas Thrainer
      for row in self.op.disks:
253 1d870e0d Thomas Thrainer
        if (not isinstance(row, dict) or
254 1d870e0d Thomas Thrainer
            constants.IDISK_SIZE not in row or
255 1d870e0d Thomas Thrainer
            not isinstance(row[constants.IDISK_SIZE], int) or
256 1d870e0d Thomas Thrainer
            constants.IDISK_MODE not in row or
257 1d870e0d Thomas Thrainer
            row[constants.IDISK_MODE] not in constants.DISK_ACCESS_SET):
258 1d870e0d Thomas Thrainer
          raise errors.OpPrereqError("Invalid contents of the 'disks'"
259 1d870e0d Thomas Thrainer
                                     " parameter", errors.ECODE_INVAL)
260 1d870e0d Thomas Thrainer
      if self.op.hypervisor is None:
261 1d870e0d Thomas Thrainer
        self.op.hypervisor = self.cfg.GetHypervisorType()
262 1d870e0d Thomas Thrainer
    elif self.op.mode == constants.IALLOCATOR_MODE_RELOC:
263 e969a81f Thomas Thrainer
      (self.inst_uuid, self.op.name) = ExpandInstanceUuidAndName(self.cfg, None,
264 e969a81f Thomas Thrainer
                                                                 self.op.name)
265 1c3231aa Thomas Thrainer
      self.relocate_from_node_uuids = \
266 e969a81f Thomas Thrainer
          list(self.cfg.GetInstanceInfo(self.inst_uuid).secondary_nodes)
267 1d870e0d Thomas Thrainer
    elif self.op.mode in (constants.IALLOCATOR_MODE_CHG_GROUP,
268 1d870e0d Thomas Thrainer
                          constants.IALLOCATOR_MODE_NODE_EVAC):
269 1d870e0d Thomas Thrainer
      if not self.op.instances:
270 1d870e0d Thomas Thrainer
        raise errors.OpPrereqError("Missing instances", errors.ECODE_INVAL)
271 da4a52a3 Thomas Thrainer
      (_, self.op.instances) = GetWantedInstances(self, self.op.instances)
272 1d870e0d Thomas Thrainer
    else:
273 1d870e0d Thomas Thrainer
      raise errors.OpPrereqError("Invalid test allocator mode '%s'" %
274 1d870e0d Thomas Thrainer
                                 self.op.mode, errors.ECODE_INVAL)
275 1d870e0d Thomas Thrainer
276 1d870e0d Thomas Thrainer
    if self.op.direction == constants.IALLOCATOR_DIR_OUT:
277 1d870e0d Thomas Thrainer
      if self.op.iallocator is None:
278 1d870e0d Thomas Thrainer
        raise errors.OpPrereqError("Missing allocator name",
279 1d870e0d Thomas Thrainer
                                   errors.ECODE_INVAL)
280 1d870e0d Thomas Thrainer
281 1d870e0d Thomas Thrainer
  def Exec(self, feedback_fn):
282 1d870e0d Thomas Thrainer
    """Run the allocator test.
283 1d870e0d Thomas Thrainer

284 1d870e0d Thomas Thrainer
    """
285 1d870e0d Thomas Thrainer
    if self.op.mode == constants.IALLOCATOR_MODE_ALLOC:
286 1d870e0d Thomas Thrainer
      req = iallocator.IAReqInstanceAlloc(name=self.op.name,
287 1d870e0d Thomas Thrainer
                                          memory=self.op.memory,
288 1d870e0d Thomas Thrainer
                                          disks=self.op.disks,
289 1d870e0d Thomas Thrainer
                                          disk_template=self.op.disk_template,
290 1d870e0d Thomas Thrainer
                                          os=self.op.os,
291 1d870e0d Thomas Thrainer
                                          tags=self.op.tags,
292 1d870e0d Thomas Thrainer
                                          nics=self.op.nics,
293 1d870e0d Thomas Thrainer
                                          vcpus=self.op.vcpus,
294 1d870e0d Thomas Thrainer
                                          spindle_use=self.op.spindle_use,
295 1d870e0d Thomas Thrainer
                                          hypervisor=self.op.hypervisor,
296 1d870e0d Thomas Thrainer
                                          node_whitelist=None)
297 1d870e0d Thomas Thrainer
    elif self.op.mode == constants.IALLOCATOR_MODE_RELOC:
298 1c3231aa Thomas Thrainer
      req = iallocator.IAReqRelocate(
299 da4a52a3 Thomas Thrainer
            inst_uuid=self.inst_uuid,
300 1c3231aa Thomas Thrainer
            relocate_from_node_uuids=list(self.relocate_from_node_uuids))
301 1d870e0d Thomas Thrainer
    elif self.op.mode == constants.IALLOCATOR_MODE_CHG_GROUP:
302 1d870e0d Thomas Thrainer
      req = iallocator.IAReqGroupChange(instances=self.op.instances,
303 1d870e0d Thomas Thrainer
                                        target_groups=self.op.target_groups)
304 1d870e0d Thomas Thrainer
    elif self.op.mode == constants.IALLOCATOR_MODE_NODE_EVAC:
305 1d870e0d Thomas Thrainer
      req = iallocator.IAReqNodeEvac(instances=self.op.instances,
306 1d870e0d Thomas Thrainer
                                     evac_mode=self.op.evac_mode)
307 1d870e0d Thomas Thrainer
    elif self.op.mode == constants.IALLOCATOR_MODE_MULTI_ALLOC:
308 1d870e0d Thomas Thrainer
      disk_template = self.op.disk_template
309 1d870e0d Thomas Thrainer
      insts = [iallocator.IAReqInstanceAlloc(name="%s%s" % (self.op.name, idx),
310 1d870e0d Thomas Thrainer
                                             memory=self.op.memory,
311 1d870e0d Thomas Thrainer
                                             disks=self.op.disks,
312 1d870e0d Thomas Thrainer
                                             disk_template=disk_template,
313 1d870e0d Thomas Thrainer
                                             os=self.op.os,
314 1d870e0d Thomas Thrainer
                                             tags=self.op.tags,
315 1d870e0d Thomas Thrainer
                                             nics=self.op.nics,
316 1d870e0d Thomas Thrainer
                                             vcpus=self.op.vcpus,
317 1d870e0d Thomas Thrainer
                                             spindle_use=self.op.spindle_use,
318 e969a81f Thomas Thrainer
                                             hypervisor=self.op.hypervisor,
319 e969a81f Thomas Thrainer
                                             node_whitelist=None)
320 1d870e0d Thomas Thrainer
               for idx in range(self.op.count)]
321 1d870e0d Thomas Thrainer
      req = iallocator.IAReqMultiInstanceAlloc(instances=insts)
322 1d870e0d Thomas Thrainer
    else:
323 1d870e0d Thomas Thrainer
      raise errors.ProgrammerError("Uncatched mode %s in"
324 1d870e0d Thomas Thrainer
                                   " LUTestAllocator.Exec", self.op.mode)
325 1d870e0d Thomas Thrainer
326 1d870e0d Thomas Thrainer
    ial = iallocator.IAllocator(self.cfg, self.rpc, req)
327 1d870e0d Thomas Thrainer
    if self.op.direction == constants.IALLOCATOR_DIR_IN:
328 1d870e0d Thomas Thrainer
      result = ial.in_text
329 1d870e0d Thomas Thrainer
    else:
330 1d870e0d Thomas Thrainer
      ial.Run(self.op.iallocator, validate=False)
331 1d870e0d Thomas Thrainer
      result = ial.out_text
332 1d870e0d Thomas Thrainer
    return result