Statistics
| Branch: | Tag: | Revision:

root / lib / cmdlib / test.py @ 76e2e6f6

History | View | Annotate | Download (12.2 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 5eacbcae Thomas Thrainer
from ganeti.cmdlib.common import ExpandInstanceName, 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 5eacbcae Thomas Thrainer
      self.op.on_nodes = GetWantedNodes(self, self.op.on_nodes)
65 054a9d17 Hrvoje Ribicic
      self.needed_locks[locking.LEVEL_NODE].extend(self.op.on_nodes)
66 054a9d17 Hrvoje Ribicic
67 054a9d17 Hrvoje Ribicic
    if self.op.on_master:
68 054a9d17 Hrvoje Ribicic
      # The node lock should be acquired for the master as well.
69 054a9d17 Hrvoje Ribicic
      self.needed_locks[locking.LEVEL_NODE].append(self.cfg.GetMasterNode())
70 1d870e0d Thomas Thrainer
71 1d870e0d Thomas Thrainer
  def _TestDelay(self):
72 1d870e0d Thomas Thrainer
    """Do the actual sleep.
73 1d870e0d Thomas Thrainer

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

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

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

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

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

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

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

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

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

235 1d870e0d Thomas Thrainer
  This LU runs the allocator tests
236 1d870e0d Thomas Thrainer

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

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

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

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