Statistics
| Branch: | Tag: | Revision:

root / lib / cmdlib / test.py @ f380d53c

History | View | Annotate | Download (11.9 kB)

1 1d870e0d Thomas Thrainer
#
2 1d870e0d Thomas Thrainer
#
3 1d870e0d Thomas Thrainer
4 1d870e0d Thomas Thrainer
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 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 1d870e0d Thomas Thrainer
from ganeti.cmdlib.common import _ExpandInstanceName, _GetWantedNodes, \
37 1d870e0d 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 1d870e0d Thomas Thrainer
    if self.op.on_nodes:
57 1d870e0d Thomas Thrainer
      # _GetWantedNodes can be used here, but is not always appropriate to use
58 1d870e0d Thomas Thrainer
      # this way in ExpandNames. Check LogicalUnit.ExpandNames docstring for
59 1d870e0d Thomas Thrainer
      # more information.
60 1d870e0d Thomas Thrainer
      self.op.on_nodes = _GetWantedNodes(self, self.op.on_nodes)
61 1d870e0d Thomas Thrainer
      self.needed_locks[locking.LEVEL_NODE] = self.op.on_nodes
62 1d870e0d Thomas Thrainer
63 1d870e0d Thomas Thrainer
  def _TestDelay(self):
64 1d870e0d Thomas Thrainer
    """Do the actual sleep.
65 1d870e0d Thomas Thrainer

66 1d870e0d Thomas Thrainer
    """
67 1d870e0d Thomas Thrainer
    if self.op.on_master:
68 1d870e0d Thomas Thrainer
      if not utils.TestDelay(self.op.duration):
69 1d870e0d Thomas Thrainer
        raise errors.OpExecError("Error during master delay test")
70 1d870e0d Thomas Thrainer
    if self.op.on_nodes:
71 1d870e0d Thomas Thrainer
      result = self.rpc.call_test_delay(self.op.on_nodes, self.op.duration)
72 1d870e0d Thomas Thrainer
      for node, node_result in result.items():
73 1d870e0d Thomas Thrainer
        node_result.Raise("Failure during rpc call to node %s" % node)
74 1d870e0d Thomas Thrainer
75 1d870e0d Thomas Thrainer
  def Exec(self, feedback_fn):
76 1d870e0d Thomas Thrainer
    """Execute the test delay opcode, with the wanted repetitions.
77 1d870e0d Thomas Thrainer

78 1d870e0d Thomas Thrainer
    """
79 1d870e0d Thomas Thrainer
    if self.op.repeat == 0:
80 1d870e0d Thomas Thrainer
      self._TestDelay()
81 1d870e0d Thomas Thrainer
    else:
82 1d870e0d Thomas Thrainer
      top_value = self.op.repeat - 1
83 1d870e0d Thomas Thrainer
      for i in range(self.op.repeat):
84 1d870e0d Thomas Thrainer
        self.LogInfo("Test delay iteration %d/%d", i, top_value)
85 1d870e0d Thomas Thrainer
        self._TestDelay()
86 1d870e0d Thomas Thrainer
87 1d870e0d Thomas Thrainer
88 1d870e0d Thomas Thrainer
class LUTestJqueue(NoHooksLU):
89 1d870e0d Thomas Thrainer
  """Utility LU to test some aspects of the job queue.
90 1d870e0d Thomas Thrainer

91 1d870e0d Thomas Thrainer
  """
92 1d870e0d Thomas Thrainer
  REQ_BGL = False
93 1d870e0d Thomas Thrainer
94 1d870e0d Thomas Thrainer
  # Must be lower than default timeout for WaitForJobChange to see whether it
95 1d870e0d Thomas Thrainer
  # notices changed jobs
96 1d870e0d Thomas Thrainer
  _CLIENT_CONNECT_TIMEOUT = 20.0
97 1d870e0d Thomas Thrainer
  _CLIENT_CONFIRM_TIMEOUT = 60.0
98 1d870e0d Thomas Thrainer
99 1d870e0d Thomas Thrainer
  @classmethod
100 1d870e0d Thomas Thrainer
  def _NotifyUsingSocket(cls, cb, errcls):
101 1d870e0d Thomas Thrainer
    """Opens a Unix socket and waits for another program to connect.
102 1d870e0d Thomas Thrainer

103 1d870e0d Thomas Thrainer
    @type cb: callable
104 1d870e0d Thomas Thrainer
    @param cb: Callback to send socket name to client
105 1d870e0d Thomas Thrainer
    @type errcls: class
106 1d870e0d Thomas Thrainer
    @param errcls: Exception class to use for errors
107 1d870e0d Thomas Thrainer

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

152 1d870e0d Thomas Thrainer
    @type test: string
153 1d870e0d Thomas Thrainer
    @param test: Test name
154 1d870e0d Thomas Thrainer
    @param arg: Test argument (depends on test)
155 1d870e0d Thomas Thrainer
    @type sockname: string
156 1d870e0d Thomas Thrainer
    @param sockname: Socket path
157 1d870e0d Thomas Thrainer

158 1d870e0d Thomas Thrainer
    """
159 1d870e0d Thomas Thrainer
    self.Log(constants.ELOG_JQUEUE_TEST, (sockname, test, arg))
160 1d870e0d Thomas Thrainer
161 1d870e0d Thomas Thrainer
  def _Notify(self, prereq, test, arg):
162 1d870e0d Thomas Thrainer
    """Notifies the client of a test.
163 1d870e0d Thomas Thrainer

164 1d870e0d Thomas Thrainer
    @type prereq: bool
165 1d870e0d Thomas Thrainer
    @param prereq: Whether this is a prereq-phase test
166 1d870e0d Thomas Thrainer
    @type test: string
167 1d870e0d Thomas Thrainer
    @param test: Test name
168 1d870e0d Thomas Thrainer
    @param arg: Test argument (depends on test)
169 1d870e0d Thomas Thrainer

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

227 1d870e0d Thomas Thrainer
  This LU runs the allocator tests
228 1d870e0d Thomas Thrainer

229 1d870e0d Thomas Thrainer
  """
230 1d870e0d Thomas Thrainer
  def CheckPrereq(self):
231 1d870e0d Thomas Thrainer
    """Check prerequisites.
232 1d870e0d Thomas Thrainer

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

235 1d870e0d Thomas Thrainer
    """
236 1d870e0d Thomas Thrainer
    if self.op.mode in (constants.IALLOCATOR_MODE_ALLOC,
237 1d870e0d Thomas Thrainer
                        constants.IALLOCATOR_MODE_MULTI_ALLOC):
238 1d870e0d Thomas Thrainer
      for attr in ["memory", "disks", "disk_template",
239 1d870e0d Thomas Thrainer
                   "os", "tags", "nics", "vcpus"]:
240 1d870e0d Thomas Thrainer
        if not hasattr(self.op, attr):
241 1d870e0d Thomas Thrainer
          raise errors.OpPrereqError("Missing attribute '%s' on opcode input" %
242 1d870e0d Thomas Thrainer
                                     attr, errors.ECODE_INVAL)
243 1d870e0d Thomas Thrainer
      iname = self.cfg.ExpandInstanceName(self.op.name)
244 1d870e0d Thomas Thrainer
      if iname is not None:
245 1d870e0d Thomas Thrainer
        raise errors.OpPrereqError("Instance '%s' already in the cluster" %
246 1d870e0d Thomas Thrainer
                                   iname, errors.ECODE_EXISTS)
247 1d870e0d Thomas Thrainer
      if not isinstance(self.op.nics, list):
248 1d870e0d Thomas Thrainer
        raise errors.OpPrereqError("Invalid parameter 'nics'",
249 1d870e0d Thomas Thrainer
                                   errors.ECODE_INVAL)
250 1d870e0d Thomas Thrainer
      if not isinstance(self.op.disks, list):
251 1d870e0d Thomas Thrainer
        raise errors.OpPrereqError("Invalid parameter 'disks'",
252 1d870e0d Thomas Thrainer
                                   errors.ECODE_INVAL)
253 1d870e0d Thomas Thrainer
      for row in self.op.disks:
254 1d870e0d Thomas Thrainer
        if (not isinstance(row, dict) or
255 1d870e0d Thomas Thrainer
            constants.IDISK_SIZE not in row or
256 1d870e0d Thomas Thrainer
            not isinstance(row[constants.IDISK_SIZE], int) or
257 1d870e0d Thomas Thrainer
            constants.IDISK_MODE not in row or
258 1d870e0d Thomas Thrainer
            row[constants.IDISK_MODE] not in constants.DISK_ACCESS_SET):
259 1d870e0d Thomas Thrainer
          raise errors.OpPrereqError("Invalid contents of the 'disks'"
260 1d870e0d Thomas Thrainer
                                     " parameter", errors.ECODE_INVAL)
261 1d870e0d Thomas Thrainer
      if self.op.hypervisor is None:
262 1d870e0d Thomas Thrainer
        self.op.hypervisor = self.cfg.GetHypervisorType()
263 1d870e0d Thomas Thrainer
    elif self.op.mode == constants.IALLOCATOR_MODE_RELOC:
264 1d870e0d Thomas Thrainer
      fname = _ExpandInstanceName(self.cfg, self.op.name)
265 1d870e0d Thomas Thrainer
      self.op.name = fname
266 1d870e0d Thomas Thrainer
      self.relocate_from = \
267 1d870e0d Thomas Thrainer
          list(self.cfg.GetInstanceInfo(fname).secondary_nodes)
268 1d870e0d Thomas Thrainer
    elif self.op.mode in (constants.IALLOCATOR_MODE_CHG_GROUP,
269 1d870e0d Thomas Thrainer
                          constants.IALLOCATOR_MODE_NODE_EVAC):
270 1d870e0d Thomas Thrainer
      if not self.op.instances:
271 1d870e0d Thomas Thrainer
        raise errors.OpPrereqError("Missing instances", errors.ECODE_INVAL)
272 1d870e0d Thomas Thrainer
      self.op.instances = _GetWantedInstances(self, self.op.instances)
273 1d870e0d Thomas Thrainer
    else:
274 1d870e0d Thomas Thrainer
      raise errors.OpPrereqError("Invalid test allocator mode '%s'" %
275 1d870e0d Thomas Thrainer
                                 self.op.mode, errors.ECODE_INVAL)
276 1d870e0d Thomas Thrainer
277 1d870e0d Thomas Thrainer
    if self.op.direction == constants.IALLOCATOR_DIR_OUT:
278 1d870e0d Thomas Thrainer
      if self.op.iallocator is None:
279 1d870e0d Thomas Thrainer
        raise errors.OpPrereqError("Missing allocator name",
280 1d870e0d Thomas Thrainer
                                   errors.ECODE_INVAL)
281 1d870e0d Thomas Thrainer
    elif self.op.direction != constants.IALLOCATOR_DIR_IN:
282 1d870e0d Thomas Thrainer
      raise errors.OpPrereqError("Wrong allocator test '%s'" %
283 1d870e0d Thomas Thrainer
                                 self.op.direction, errors.ECODE_INVAL)
284 1d870e0d Thomas Thrainer
285 1d870e0d Thomas Thrainer
  def Exec(self, feedback_fn):
286 1d870e0d Thomas Thrainer
    """Run the allocator test.
287 1d870e0d Thomas Thrainer

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