Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 156681c1

History | View | Annotate | Download (75.8 kB)

1
#
2
#
3

    
4
# Copyright (C) 2008, 2009, 2010, 2011, 2012 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

    
21

    
22
"""KVM hypervisor
23

24
"""
25

    
26
import errno
27
import os
28
import os.path
29
import re
30
import tempfile
31
import time
32
import logging
33
import pwd
34
import struct
35
import fcntl
36
import shutil
37
import socket
38
import stat
39
import StringIO
40
try:
41
  import affinity   # pylint: disable=F0401
42
except ImportError:
43
  affinity = None
44

    
45
from ganeti import utils
46
from ganeti import constants
47
from ganeti import errors
48
from ganeti import serializer
49
from ganeti import objects
50
from ganeti import uidpool
51
from ganeti import ssconf
52
from ganeti import netutils
53
from ganeti import pathutils
54
from ganeti.hypervisor import hv_base
55
from ganeti.utils import wrapper as utils_wrapper
56

    
57

    
58
_KVM_NETWORK_SCRIPT = pathutils.CONF_DIR + "/kvm-vif-bridge"
59
_KVM_START_PAUSED_FLAG = "-S"
60

    
61
# TUN/TAP driver constants, taken from <linux/if_tun.h>
62
# They are architecture-independent and already hardcoded in qemu-kvm source,
63
# so we can safely include them here.
64
TUNSETIFF = 0x400454ca
65
TUNGETIFF = 0x800454d2
66
TUNGETFEATURES = 0x800454cf
67
IFF_TAP = 0x0002
68
IFF_NO_PI = 0x1000
69
IFF_VNET_HDR = 0x4000
70

    
71
#: SPICE parameters which depend on L{constants.HV_KVM_SPICE_BIND}
72
_SPICE_ADDITIONAL_PARAMS = frozenset([
73
  constants.HV_KVM_SPICE_IP_VERSION,
74
  constants.HV_KVM_SPICE_PASSWORD_FILE,
75
  constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR,
76
  constants.HV_KVM_SPICE_JPEG_IMG_COMPR,
77
  constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR,
78
  constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION,
79
  constants.HV_KVM_SPICE_USE_TLS,
80
  ])
81

    
82

    
83
def _ProbeTapVnetHdr(fd):
84
  """Check whether to enable the IFF_VNET_HDR flag.
85

86
  To do this, _all_ of the following conditions must be met:
87
   1. TUNGETFEATURES ioctl() *must* be implemented
88
   2. TUNGETFEATURES ioctl() result *must* contain the IFF_VNET_HDR flag
89
   3. TUNGETIFF ioctl() *must* be implemented; reading the kernel code in
90
      drivers/net/tun.c there is no way to test this until after the tap device
91
      has been created using TUNSETIFF, and there is no way to change the
92
      IFF_VNET_HDR flag after creating the interface, catch-22! However both
93
      TUNGETIFF and TUNGETFEATURES were introduced in kernel version 2.6.27,
94
      thus we can expect TUNGETIFF to be present if TUNGETFEATURES is.
95

96
   @type fd: int
97
   @param fd: the file descriptor of /dev/net/tun
98

99
  """
100
  req = struct.pack("I", 0)
101
  try:
102
    res = fcntl.ioctl(fd, TUNGETFEATURES, req)
103
  except EnvironmentError:
104
    logging.warning("TUNGETFEATURES ioctl() not implemented")
105
    return False
106

    
107
  tunflags = struct.unpack("I", res)[0]
108
  if tunflags & IFF_VNET_HDR:
109
    return True
110
  else:
111
    logging.warning("Host does not support IFF_VNET_HDR, not enabling")
112
    return False
113

    
114

    
115
def _OpenTap(vnet_hdr=True):
116
  """Open a new tap device and return its file descriptor.
117

118
  This is intended to be used by a qemu-type hypervisor together with the -net
119
  tap,fd=<fd> command line parameter.
120

121
  @type vnet_hdr: boolean
122
  @param vnet_hdr: Enable the VNET Header
123
  @return: (ifname, tapfd)
124
  @rtype: tuple
125

126
  """
127
  try:
128
    tapfd = os.open("/dev/net/tun", os.O_RDWR)
129
  except EnvironmentError:
130
    raise errors.HypervisorError("Failed to open /dev/net/tun")
131

    
132
  flags = IFF_TAP | IFF_NO_PI
133

    
134
  if vnet_hdr and _ProbeTapVnetHdr(tapfd):
135
    flags |= IFF_VNET_HDR
136

    
137
  # The struct ifreq ioctl request (see netdevice(7))
138
  ifr = struct.pack("16sh", "", flags)
139

    
140
  try:
141
    res = fcntl.ioctl(tapfd, TUNSETIFF, ifr)
142
  except EnvironmentError:
143
    raise errors.HypervisorError("Failed to allocate a new TAP device")
144

    
145
  # Get the interface name from the ioctl
146
  ifname = struct.unpack("16sh", res)[0].strip("\x00")
147
  return (ifname, tapfd)
148

    
149

    
150
def _BuildNetworkEnv(name, network, gateway, network6, gateway6,
151
                     network_type, mac_prefix, tags, env):
152
  """Build environment variables concerning a Network.
153

154
  """
155
  if name:
156
    env["NETWORK_NAME"] = name
157
  if network:
158
    env["NETWORK_SUBNET"] = network
159
  if gateway:
160
    env["NETWORK_GATEWAY"] = gateway
161
  if network6:
162
    env["NETWORK_SUBNET6"] = network6
163
  if gateway6:
164
    env["NETWORK_GATEWAY6"] = gateway6
165
  if mac_prefix:
166
    env["NETWORK_MAC_PREFIX"] = mac_prefix
167
  if network_type:
168
    env["NETWORK_TYPE"] = network_type
169
  if tags:
170
    env["NETWORK_TAGS"] = " ".join(tags)
171

    
172
  return env
173

    
174

    
175
class QmpMessage:
176
  """QEMU Messaging Protocol (QMP) message.
177

178
  """
179
  def __init__(self, data):
180
    """Creates a new QMP message based on the passed data.
181

182
    """
183
    if not isinstance(data, dict):
184
      raise TypeError("QmpMessage must be initialized with a dict")
185

    
186
    self.data = data
187

    
188
  def __getitem__(self, field_name):
189
    """Get the value of the required field if present, or None.
190

191
    Overrides the [] operator to provide access to the message data,
192
    returning None if the required item is not in the message
193
    @return: the value of the field_name field, or None if field_name
194
             is not contained in the message
195

196
    """
197
    return self.data.get(field_name, None)
198

    
199
  def __setitem__(self, field_name, field_value):
200
    """Set the value of the required field_name to field_value.
201

202
    """
203
    self.data[field_name] = field_value
204

    
205
  @staticmethod
206
  def BuildFromJsonString(json_string):
207
    """Build a QmpMessage from a JSON encoded string.
208

209
    @type json_string: str
210
    @param json_string: JSON string representing the message
211
    @rtype: L{QmpMessage}
212
    @return: a L{QmpMessage} built from json_string
213

214
    """
215
    # Parse the string
216
    data = serializer.LoadJson(json_string)
217
    return QmpMessage(data)
218

    
219
  def __str__(self):
220
    # The protocol expects the JSON object to be sent as a single line.
221
    return serializer.DumpJson(self.data)
222

    
223
  def __eq__(self, other):
224
    # When comparing two QmpMessages, we are interested in comparing
225
    # their internal representation of the message data
226
    return self.data == other.data
227

    
228

    
229
class QmpConnection:
230
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
231

232
  """
233
  _FIRST_MESSAGE_KEY = "QMP"
234
  _EVENT_KEY = "event"
235
  _ERROR_KEY = "error"
236
  _RETURN_KEY = RETURN_KEY = "return"
237
  _ACTUAL_KEY = ACTUAL_KEY = "actual"
238
  _ERROR_CLASS_KEY = "class"
239
  _ERROR_DATA_KEY = "data"
240
  _ERROR_DESC_KEY = "desc"
241
  _EXECUTE_KEY = "execute"
242
  _ARGUMENTS_KEY = "arguments"
243
  _CAPABILITIES_COMMAND = "qmp_capabilities"
244
  _MESSAGE_END_TOKEN = "\r\n"
245
  _SOCKET_TIMEOUT = 5
246

    
247
  def __init__(self, monitor_filename):
248
    """Instantiates the QmpConnection object.
249

250
    @type monitor_filename: string
251
    @param monitor_filename: the filename of the UNIX raw socket on which the
252
                             QMP monitor is listening
253

254
    """
255
    self.monitor_filename = monitor_filename
256
    self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
257
    # We want to fail if the server doesn't send a complete message
258
    # in a reasonable amount of time
259
    self.sock.settimeout(self._SOCKET_TIMEOUT)
260
    self._connected = False
261
    self._buf = ""
262

    
263
  def _check_socket(self):
264
    sock_stat = None
265
    try:
266
      sock_stat = os.stat(self.monitor_filename)
267
    except EnvironmentError, err:
268
      if err.errno == errno.ENOENT:
269
        raise errors.HypervisorError("No qmp socket found")
270
      else:
271
        raise errors.HypervisorError("Error checking qmp socket: %s",
272
                                     utils.ErrnoOrStr(err))
273
    if not stat.S_ISSOCK(sock_stat.st_mode):
274
      raise errors.HypervisorError("Qmp socket is not a socket")
275

    
276
  def _check_connection(self):
277
    """Make sure that the connection is established.
278

279
    """
280
    if not self._connected:
281
      raise errors.ProgrammerError("To use a QmpConnection you need to first"
282
                                   " invoke connect() on it")
283

    
284
  def connect(self):
285
    """Connects to the QMP monitor.
286

287
    Connects to the UNIX socket and makes sure that we can actually send and
288
    receive data to the kvm instance via QMP.
289

290
    @raise errors.HypervisorError: when there are communication errors
291
    @raise errors.ProgrammerError: when there are data serialization errors
292

293
    """
294
    if self._connected:
295
      raise errors.ProgrammerError("Cannot connect twice")
296

    
297
    self._check_socket()
298

    
299
    # Check file existance/stuff
300
    try:
301
      self.sock.connect(self.monitor_filename)
302
    except EnvironmentError:
303
      raise errors.HypervisorError("Can't connect to qmp socket")
304
    self._connected = True
305

    
306
    # Check if we receive a correct greeting message from the server
307
    # (As per the QEMU Protocol Specification 0.1 - section 2.2)
308
    greeting = self._Recv()
309
    if not greeting[self._FIRST_MESSAGE_KEY]:
310
      self._connected = False
311
      raise errors.HypervisorError("kvm: qmp communication error (wrong"
312
                                   " server greeting")
313

    
314
    # Let's put the monitor in command mode using the qmp_capabilities
315
    # command, or else no command will be executable.
316
    # (As per the QEMU Protocol Specification 0.1 - section 4)
317
    self.Execute(self._CAPABILITIES_COMMAND)
318

    
319
  def _ParseMessage(self, buf):
320
    """Extract and parse a QMP message from the given buffer.
321

322
    Seeks for a QMP message in the given buf. If found, it parses it and
323
    returns it together with the rest of the characters in the buf.
324
    If no message is found, returns None and the whole buffer.
325

326
    @raise errors.ProgrammerError: when there are data serialization errors
327

328
    """
329
    message = None
330
    # Check if we got the message end token (CRLF, as per the QEMU Protocol
331
    # Specification 0.1 - Section 2.1.1)
332
    pos = buf.find(self._MESSAGE_END_TOKEN)
333
    if pos >= 0:
334
      try:
335
        message = QmpMessage.BuildFromJsonString(buf[:pos + 1])
336
      except Exception, err:
337
        raise errors.ProgrammerError("QMP data serialization error: %s" % err)
338
      buf = buf[pos + 1:]
339

    
340
    return (message, buf)
341

    
342
  def _Recv(self):
343
    """Receives a message from QMP and decodes the received JSON object.
344

345
    @rtype: QmpMessage
346
    @return: the received message
347
    @raise errors.HypervisorError: when there are communication errors
348
    @raise errors.ProgrammerError: when there are data serialization errors
349

350
    """
351
    self._check_connection()
352

    
353
    # Check if there is already a message in the buffer
354
    (message, self._buf) = self._ParseMessage(self._buf)
355
    if message:
356
      return message
357

    
358
    recv_buffer = StringIO.StringIO(self._buf)
359
    recv_buffer.seek(len(self._buf))
360
    try:
361
      while True:
362
        data = self.sock.recv(4096)
363
        if not data:
364
          break
365
        recv_buffer.write(data)
366

    
367
        (message, self._buf) = self._ParseMessage(recv_buffer.getvalue())
368
        if message:
369
          return message
370

    
371
    except socket.timeout, err:
372
      raise errors.HypervisorError("Timeout while receiving a QMP message: "
373
                                   "%s" % (err))
374
    except socket.error, err:
375
      raise errors.HypervisorError("Unable to receive data from KVM using the"
376
                                   " QMP protocol: %s" % err)
377

    
378
  def _Send(self, message):
379
    """Encodes and sends a message to KVM using QMP.
380

381
    @type message: QmpMessage
382
    @param message: message to send to KVM
383
    @raise errors.HypervisorError: when there are communication errors
384
    @raise errors.ProgrammerError: when there are data serialization errors
385

386
    """
387
    self._check_connection()
388
    try:
389
      message_str = str(message)
390
    except Exception, err:
391
      raise errors.ProgrammerError("QMP data deserialization error: %s" % err)
392

    
393
    try:
394
      self.sock.sendall(message_str)
395
    except socket.timeout, err:
396
      raise errors.HypervisorError("Timeout while sending a QMP message: "
397
                                   "%s (%s)" % (err.string, err.errno))
398
    except socket.error, err:
399
      raise errors.HypervisorError("Unable to send data from KVM using the"
400
                                   " QMP protocol: %s" % err)
401

    
402
  def Execute(self, command, arguments=None):
403
    """Executes a QMP command and returns the response of the server.
404

405
    @type command: str
406
    @param command: the command to execute
407
    @type arguments: dict
408
    @param arguments: dictionary of arguments to be passed to the command
409
    @rtype: dict
410
    @return: dictionary representing the received JSON object
411
    @raise errors.HypervisorError: when there are communication errors
412
    @raise errors.ProgrammerError: when there are data serialization errors
413

414
    """
415
    self._check_connection()
416
    message = QmpMessage({self._EXECUTE_KEY: command})
417
    if arguments:
418
      message[self._ARGUMENTS_KEY] = arguments
419
    self._Send(message)
420

    
421
    # Events can occur between the sending of the command and the reception
422
    # of the response, so we need to filter out messages with the event key.
423
    while True:
424
      response = self._Recv()
425
      err = response[self._ERROR_KEY]
426
      if err:
427
        raise errors.HypervisorError("kvm: error executing the %s"
428
                                     " command: %s (%s, %s):" %
429
                                     (command,
430
                                      err[self._ERROR_DESC_KEY],
431
                                      err[self._ERROR_CLASS_KEY],
432
                                      err[self._ERROR_DATA_KEY]))
433

    
434
      elif not response[self._EVENT_KEY]:
435
        return response
436

    
437

    
438
class KVMHypervisor(hv_base.BaseHypervisor):
439
  """KVM hypervisor interface
440

441
  """
442
  CAN_MIGRATE = True
443

    
444
  _ROOT_DIR = pathutils.RUN_DIR + "/kvm-hypervisor"
445
  _PIDS_DIR = _ROOT_DIR + "/pid" # contains live instances pids
446
  _UIDS_DIR = _ROOT_DIR + "/uid" # contains instances reserved uids
447
  _CTRL_DIR = _ROOT_DIR + "/ctrl" # contains instances control sockets
448
  _CONF_DIR = _ROOT_DIR + "/conf" # contains instances startup data
449
  _NICS_DIR = _ROOT_DIR + "/nic" # contains instances nic <-> tap associations
450
  _KEYMAP_DIR = _ROOT_DIR + "/keymap" # contains instances keymaps
451
  # KVM instances with chroot enabled are started in empty chroot directories.
452
  _CHROOT_DIR = _ROOT_DIR + "/chroot" # for empty chroot directories
453
  # After an instance is stopped, its chroot directory is removed.
454
  # If the chroot directory is not empty, it can't be removed.
455
  # A non-empty chroot directory indicates a possible security incident.
456
  # To support forensics, the non-empty chroot directory is quarantined in
457
  # a separate directory, called 'chroot-quarantine'.
458
  _CHROOT_QUARANTINE_DIR = _ROOT_DIR + "/chroot-quarantine"
459
  _DIRS = [_ROOT_DIR, _PIDS_DIR, _UIDS_DIR, _CTRL_DIR, _CONF_DIR, _NICS_DIR,
460
           _CHROOT_DIR, _CHROOT_QUARANTINE_DIR, _KEYMAP_DIR]
461

    
462
  PARAMETERS = {
463
    constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK,
464
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
465
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
466
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
467
    constants.HV_ACPI: hv_base.NO_CHECK,
468
    constants.HV_SERIAL_CONSOLE: hv_base.NO_CHECK,
469
    constants.HV_SERIAL_SPEED: hv_base.NO_CHECK,
470
    constants.HV_VNC_BIND_ADDRESS:
471
      (False, lambda x: (netutils.IP4Address.IsValid(x) or
472
                         utils.IsNormAbsPath(x)),
473
       "the VNC bind address must be either a valid IP address or an absolute"
474
       " pathname", None, None),
475
    constants.HV_VNC_TLS: hv_base.NO_CHECK,
476
    constants.HV_VNC_X509: hv_base.OPT_DIR_CHECK,
477
    constants.HV_VNC_X509_VERIFY: hv_base.NO_CHECK,
478
    constants.HV_VNC_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
479
    constants.HV_KVM_SPICE_BIND: hv_base.NO_CHECK, # will be checked later
480
    constants.HV_KVM_SPICE_IP_VERSION:
481
      (False, lambda x: (x == constants.IFACE_NO_IP_VERSION_SPECIFIED or
482
                         x in constants.VALID_IP_VERSIONS),
483
       "the SPICE IP version should be 4 or 6",
484
       None, None),
485
    constants.HV_KVM_SPICE_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
486
    constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR:
487
      hv_base.ParamInSet(
488
        False, constants.HT_KVM_SPICE_VALID_LOSSLESS_IMG_COMPR_OPTIONS),
489
    constants.HV_KVM_SPICE_JPEG_IMG_COMPR:
490
      hv_base.ParamInSet(
491
        False, constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
492
    constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR:
493
      hv_base.ParamInSet(
494
        False, constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
495
    constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION:
496
      hv_base.ParamInSet(
497
        False, constants.HT_KVM_SPICE_VALID_VIDEO_STREAM_DETECTION_OPTIONS),
498
    constants.HV_KVM_SPICE_AUDIO_COMPR: hv_base.NO_CHECK,
499
    constants.HV_KVM_SPICE_USE_TLS: hv_base.NO_CHECK,
500
    constants.HV_KVM_SPICE_TLS_CIPHERS: hv_base.NO_CHECK,
501
    constants.HV_KVM_SPICE_USE_VDAGENT: hv_base.NO_CHECK,
502
    constants.HV_KVM_FLOPPY_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
503
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
504
    constants.HV_KVM_CDROM2_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
505
    constants.HV_BOOT_ORDER:
506
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
507
    constants.HV_NIC_TYPE:
508
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
509
    constants.HV_DISK_TYPE:
510
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
511
    constants.HV_KVM_CDROM_DISK_TYPE:
512
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_DISK_TYPES),
513
    constants.HV_USB_MOUSE:
514
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
515
    constants.HV_KEYMAP: hv_base.NO_CHECK,
516
    constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
517
    constants.HV_MIGRATION_BANDWIDTH: hv_base.REQ_NONNEGATIVE_INT_CHECK,
518
    constants.HV_MIGRATION_DOWNTIME: hv_base.REQ_NONNEGATIVE_INT_CHECK,
519
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
520
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
521
    constants.HV_DISK_CACHE:
522
      hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
523
    constants.HV_SECURITY_MODEL:
524
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_SM_TYPES),
525
    constants.HV_SECURITY_DOMAIN: hv_base.NO_CHECK,
526
    constants.HV_KVM_FLAG:
527
      hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES),
528
    constants.HV_VHOST_NET: hv_base.NO_CHECK,
529
    constants.HV_KVM_USE_CHROOT: hv_base.NO_CHECK,
530
    constants.HV_MEM_PATH: hv_base.OPT_DIR_CHECK,
531
    constants.HV_REBOOT_BEHAVIOR:
532
      hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
533
    constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
534
    constants.HV_CPU_TYPE: hv_base.NO_CHECK,
535
    constants.HV_CPU_CORES: hv_base.OPT_NONNEGATIVE_INT_CHECK,
536
    constants.HV_CPU_THREADS: hv_base.OPT_NONNEGATIVE_INT_CHECK,
537
    constants.HV_CPU_SOCKETS: hv_base.OPT_NONNEGATIVE_INT_CHECK,
538
    constants.HV_SOUNDHW: hv_base.NO_CHECK,
539
    constants.HV_USB_DEVICES: hv_base.NO_CHECK,
540
    }
541

    
542
  _MIGRATION_STATUS_RE = re.compile("Migration\s+status:\s+(\w+)",
543
                                    re.M | re.I)
544
  _MIGRATION_PROGRESS_RE = \
545
    re.compile(r"\s*transferred\s+ram:\s+(?P<transferred>\d+)\s+kbytes\s*\n"
546
               r"\s*remaining\s+ram:\s+(?P<remaining>\d+)\s+kbytes\s*\n"
547
               r"\s*total\s+ram:\s+(?P<total>\d+)\s+kbytes\s*\n", re.I)
548

    
549
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
550
  _MIGRATION_INFO_RETRY_DELAY = 2
551

    
552
  _VERSION_RE = re.compile(r"\b(\d+)\.(\d+)(\.(\d+))?\b")
553

    
554
  _CPU_INFO_RE = re.compile(r"cpu\s+\#(\d+).*thread_id\s*=\s*(\d+)", re.I)
555
  _CPU_INFO_CMD = "info cpus"
556
  _CONT_CMD = "cont"
557

    
558
  _DEFAULT_MACHINE_VERSION_RE = re.compile(r"^(\S+).*\(default\)", re.M)
559

    
560
  _QMP_RE = re.compile(r"^-qmp\s", re.M)
561
  _SPICE_RE = re.compile(r"^-spice\s", re.M)
562
  _VHOST_RE = re.compile(r"^-net\s.*,vhost=on|off", re.M)
563
  _ENABLE_KVM_RE = re.compile(r"^-enable-kvm\s", re.M)
564
  _DISABLE_KVM_RE = re.compile(r"^-disable-kvm\s", re.M)
565
  _NETDEV_RE = re.compile(r"^-netdev\s", re.M)
566
  # match  -drive.*boot=on|off on different lines, but in between accept only
567
  # dashes not preceeded by a new line (which would mean another option
568
  # different than -drive is starting)
569
  _BOOT_RE = re.compile(r"^-drive\s([^-]|(?<!^)-)*,boot=on\|off", re.M | re.S)
570

    
571
  ANCILLARY_FILES = [
572
    _KVM_NETWORK_SCRIPT,
573
    ]
574
  ANCILLARY_FILES_OPT = [
575
    _KVM_NETWORK_SCRIPT,
576
    ]
577

    
578
  def __init__(self):
579
    hv_base.BaseHypervisor.__init__(self)
580
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
581
    # in a tmpfs filesystem or has been otherwise wiped out.
582
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
583
    utils.EnsureDirs(dirs)
584

    
585
  @classmethod
586
  def _InstancePidFile(cls, instance_name):
587
    """Returns the instance pidfile.
588

589
    """
590
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
591

    
592
  @classmethod
593
  def _InstanceUidFile(cls, instance_name):
594
    """Returns the instance uidfile.
595

596
    """
597
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
598

    
599
  @classmethod
600
  def _InstancePidInfo(cls, pid):
601
    """Check pid file for instance information.
602

603
    Check that a pid file is associated with an instance, and retrieve
604
    information from its command line.
605

606
    @type pid: string or int
607
    @param pid: process id of the instance to check
608
    @rtype: tuple
609
    @return: (instance_name, memory, vcpus)
610
    @raise errors.HypervisorError: when an instance cannot be found
611

612
    """
613
    alive = utils.IsProcessAlive(pid)
614
    if not alive:
615
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
616

    
617
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
618
    try:
619
      cmdline = utils.ReadFile(cmdline_file)
620
    except EnvironmentError, err:
621
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
622
                                   (pid, err))
623

    
624
    instance = None
625
    memory = 0
626
    vcpus = 0
627

    
628
    arg_list = cmdline.split("\x00")
629
    while arg_list:
630
      arg = arg_list.pop(0)
631
      if arg == "-name":
632
        instance = arg_list.pop(0)
633
      elif arg == "-m":
634
        memory = int(arg_list.pop(0))
635
      elif arg == "-smp":
636
        vcpus = int(arg_list.pop(0).split(",")[0])
637

    
638
    if instance is None:
639
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
640
                                   " instance" % pid)
641

    
642
    return (instance, memory, vcpus)
643

    
644
  def _InstancePidAlive(self, instance_name):
645
    """Returns the instance pidfile, pid, and liveness.
646

647
    @type instance_name: string
648
    @param instance_name: instance name
649
    @rtype: tuple
650
    @return: (pid file name, pid, liveness)
651

652
    """
653
    pidfile = self._InstancePidFile(instance_name)
654
    pid = utils.ReadPidFile(pidfile)
655

    
656
    alive = False
657
    try:
658
      cmd_instance = self._InstancePidInfo(pid)[0]
659
      alive = (cmd_instance == instance_name)
660
    except errors.HypervisorError:
661
      pass
662

    
663
    return (pidfile, pid, alive)
664

    
665
  def _CheckDown(self, instance_name):
666
    """Raises an error unless the given instance is down.
667

668
    """
669
    alive = self._InstancePidAlive(instance_name)[2]
670
    if alive:
671
      raise errors.HypervisorError("Failed to start instance %s: %s" %
672
                                   (instance_name, "already running"))
673

    
674
  @classmethod
675
  def _InstanceMonitor(cls, instance_name):
676
    """Returns the instance monitor socket name
677

678
    """
679
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
680

    
681
  @classmethod
682
  def _InstanceSerial(cls, instance_name):
683
    """Returns the instance serial socket name
684

685
    """
686
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
687

    
688
  @classmethod
689
  def _InstanceQmpMonitor(cls, instance_name):
690
    """Returns the instance serial QMP socket name
691

692
    """
693
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
694

    
695
  @staticmethod
696
  def _SocatUnixConsoleParams():
697
    """Returns the correct parameters for socat
698

699
    If we have a new-enough socat we can use raw mode with an escape character.
700

701
    """
702
    if constants.SOCAT_USE_ESCAPE:
703
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
704
    else:
705
      return "echo=0,icanon=0"
706

    
707
  @classmethod
708
  def _InstanceKVMRuntime(cls, instance_name):
709
    """Returns the instance KVM runtime filename
710

711
    """
712
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
713

    
714
  @classmethod
715
  def _InstanceChrootDir(cls, instance_name):
716
    """Returns the name of the KVM chroot dir of the instance
717

718
    """
719
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
720

    
721
  @classmethod
722
  def _InstanceNICDir(cls, instance_name):
723
    """Returns the name of the directory holding the tap device files for a
724
    given instance.
725

726
    """
727
    return utils.PathJoin(cls._NICS_DIR, instance_name)
728

    
729
  @classmethod
730
  def _InstanceNICFile(cls, instance_name, seq):
731
    """Returns the name of the file containing the tap device for a given NIC
732

733
    """
734
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
735

    
736
  @classmethod
737
  def _InstanceKeymapFile(cls, instance_name):
738
    """Returns the name of the file containing the keymap for a given instance
739

740
    """
741
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
742

    
743
  @classmethod
744
  def _TryReadUidFile(cls, uid_file):
745
    """Try to read a uid file
746

747
    """
748
    if os.path.exists(uid_file):
749
      try:
750
        uid = int(utils.ReadOneLineFile(uid_file))
751
        return uid
752
      except EnvironmentError:
753
        logging.warning("Can't read uid file", exc_info=True)
754
      except (TypeError, ValueError):
755
        logging.warning("Can't parse uid file contents", exc_info=True)
756
    return None
757

    
758
  @classmethod
759
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
760
    """Removes an instance's rutime sockets/files/dirs.
761

762
    """
763
    utils.RemoveFile(pidfile)
764
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
765
    utils.RemoveFile(cls._InstanceSerial(instance_name))
766
    utils.RemoveFile(cls._InstanceQmpMonitor(instance_name))
767
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
768
    utils.RemoveFile(cls._InstanceKeymapFile(instance_name))
769
    uid_file = cls._InstanceUidFile(instance_name)
770
    uid = cls._TryReadUidFile(uid_file)
771
    utils.RemoveFile(uid_file)
772
    if uid is not None:
773
      uidpool.ReleaseUid(uid)
774
    try:
775
      shutil.rmtree(cls._InstanceNICDir(instance_name))
776
    except OSError, err:
777
      if err.errno != errno.ENOENT:
778
        raise
779
    try:
780
      chroot_dir = cls._InstanceChrootDir(instance_name)
781
      utils.RemoveDir(chroot_dir)
782
    except OSError, err:
783
      if err.errno == errno.ENOTEMPTY:
784
        # The chroot directory is expected to be empty, but it isn't.
785
        new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
786
                                          prefix="%s-%s-" %
787
                                          (instance_name,
788
                                           utils.TimestampForFilename()))
789
        logging.warning("The chroot directory of instance %s can not be"
790
                        " removed as it is not empty. Moving it to the"
791
                        " quarantine instead. Please investigate the"
792
                        " contents (%s) and clean up manually",
793
                        instance_name, new_chroot_dir)
794
        utils.RenameFile(chroot_dir, new_chroot_dir)
795
      else:
796
        raise
797

    
798
  @staticmethod
799
  def _ConfigureNIC(instance, seq, nic, tap):
800
    """Run the network configuration script for a specified NIC
801

802
    @param instance: instance we're acting on
803
    @type instance: instance object
804
    @param seq: nic sequence number
805
    @type seq: int
806
    @param nic: nic we're acting on
807
    @type nic: nic object
808
    @param tap: the host's tap interface this NIC corresponds to
809
    @type tap: str
810

811
    """
812
    if instance.tags:
813
      tags = " ".join(instance.tags)
814
    else:
815
      tags = ""
816

    
817
    env = {
818
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
819
      "INSTANCE": instance.name,
820
      "MAC": nic.mac,
821
      "MODE": nic.nicparams[constants.NIC_MODE],
822
      "INTERFACE": tap,
823
      "INTERFACE_INDEX": str(seq),
824
      "TAGS": tags,
825
    }
826

    
827
    if nic.ip:
828
      env["IP"] = nic.ip
829

    
830
    if nic.nicparams[constants.NIC_LINK]:
831
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
832

    
833
    if nic.network:
834
      n = objects.Network.FromDict(nic.netinfo)
835
      _BuildNetworkEnv(nic.network, n.network, n.gateway,
836
                       n.network6, n.gateway6, n.network_type,
837
                       n.mac_prefix, n.tags, env)
838

    
839
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
840
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
841

    
842
    result = utils.RunCmd([pathutils.KVM_IFUP, tap], env=env)
843
    if result.failed:
844
      raise errors.HypervisorError("Failed to configure interface %s: %s."
845
                                   " Network configuration script output: %s" %
846
                                   (tap, result.fail_reason, result.output))
847

    
848
  @staticmethod
849
  def _VerifyAffinityPackage():
850
    if affinity is None:
851
      raise errors.HypervisorError("affinity Python package not"
852
                                   " found; cannot use CPU pinning under KVM")
853

    
854
  @staticmethod
855
  def _BuildAffinityCpuMask(cpu_list):
856
    """Create a CPU mask suitable for sched_setaffinity from a list of
857
    CPUs.
858

859
    See man taskset for more info on sched_setaffinity masks.
860
    For example: [ 0, 2, 5, 6 ] will return 101 (0x65, 0..01100101).
861

862
    @type cpu_list: list of int
863
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
864
    @rtype: int
865
    @return: a bit mask of CPU affinities
866

867
    """
868
    if cpu_list == constants.CPU_PINNING_OFF:
869
      return constants.CPU_PINNING_ALL_KVM
870
    else:
871
      return sum(2 ** cpu for cpu in cpu_list)
872

    
873
  @classmethod
874
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
875
    """Change CPU affinity for running VM according to given CPU mask.
876

877
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
878
    @type cpu_mask: string
879
    @param process_id: process ID of KVM process. Used to pin entire VM
880
                       to physical CPUs.
881
    @type process_id: int
882
    @param thread_dict: map of virtual CPUs to KVM thread IDs
883
    @type thread_dict: dict int:int
884

885
    """
886
    # Convert the string CPU mask to a list of list of int's
887
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
888

    
889
    if len(cpu_list) == 1:
890
      all_cpu_mapping = cpu_list[0]
891
      if all_cpu_mapping == constants.CPU_PINNING_OFF:
892
        # If CPU pinning has 1 entry that's "all", then do nothing
893
        pass
894
      else:
895
        # If CPU pinning has one non-all entry, map the entire VM to
896
        # one set of physical CPUs
897
        cls._VerifyAffinityPackage()
898
        affinity.set_process_affinity_mask(
899
          process_id, cls._BuildAffinityCpuMask(all_cpu_mapping))
900
    else:
901
      # The number of vCPUs mapped should match the number of vCPUs
902
      # reported by KVM. This was already verified earlier, so
903
      # here only as a sanity check.
904
      assert len(thread_dict) == len(cpu_list)
905
      cls._VerifyAffinityPackage()
906

    
907
      # For each vCPU, map it to the proper list of physical CPUs
908
      for vcpu, i in zip(cpu_list, range(len(cpu_list))):
909
        affinity.set_process_affinity_mask(thread_dict[i],
910
                                           cls._BuildAffinityCpuMask(vcpu))
911

    
912
  def _GetVcpuThreadIds(self, instance_name):
913
    """Get a mapping of vCPU no. to thread IDs for the instance
914

915
    @type instance_name: string
916
    @param instance_name: instance in question
917
    @rtype: dictionary of int:int
918
    @return: a dictionary mapping vCPU numbers to thread IDs
919

920
    """
921
    result = {}
922
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
923
    for line in output.stdout.splitlines():
924
      match = self._CPU_INFO_RE.search(line)
925
      if not match:
926
        continue
927
      grp = map(int, match.groups())
928
      result[grp[0]] = grp[1]
929

    
930
    return result
931

    
932
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
933
    """Complete CPU pinning.
934

935
    @type instance_name: string
936
    @param instance_name: name of instance
937
    @type cpu_mask: string
938
    @param cpu_mask: CPU pinning mask as entered by user
939

940
    """
941
    # Get KVM process ID, to be used if need to pin entire VM
942
    _, pid, _ = self._InstancePidAlive(instance_name)
943
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
944
    thread_dict = self._GetVcpuThreadIds(instance_name)
945
    # Run CPU pinning, based on configured mask
946
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
947

    
948
  def ListInstances(self):
949
    """Get the list of running instances.
950

951
    We can do this by listing our live instances directory and
952
    checking whether the associated kvm process is still alive.
953

954
    """
955
    result = []
956
    for name in os.listdir(self._PIDS_DIR):
957
      if self._InstancePidAlive(name)[2]:
958
        result.append(name)
959
    return result
960

    
961
  def GetInstanceInfo(self, instance_name):
962
    """Get instance properties.
963

964
    @type instance_name: string
965
    @param instance_name: the instance name
966
    @rtype: tuple of strings
967
    @return: (name, id, memory, vcpus, stat, times)
968

969
    """
970
    _, pid, alive = self._InstancePidAlive(instance_name)
971
    if not alive:
972
      return None
973

    
974
    _, memory, vcpus = self._InstancePidInfo(pid)
975
    istat = "---b-"
976
    times = "0"
977

    
978
    try:
979
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
980
      qmp.connect()
981
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
982
      # Will fail if ballooning is not enabled, but we can then just resort to
983
      # the value above.
984
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
985
      memory = mem_bytes / 1048576
986
    except errors.HypervisorError:
987
      pass
988

    
989
    return (instance_name, pid, memory, vcpus, istat, times)
990

    
991
  def GetAllInstancesInfo(self):
992
    """Get properties of all instances.
993

994
    @return: list of tuples (name, id, memory, vcpus, stat, times)
995

996
    """
997
    data = []
998
    for name in os.listdir(self._PIDS_DIR):
999
      try:
1000
        info = self.GetInstanceInfo(name)
1001
      except errors.HypervisorError:
1002
        # Ignore exceptions due to instances being shut down
1003
        continue
1004
      if info:
1005
        data.append(info)
1006
    return data
1007

    
1008
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused):
1009
    """Generate KVM information to start an instance.
1010

1011
    @attention: this function must not have any side-effects; for
1012
        example, it must not write to the filesystem, or read values
1013
        from the current system the are expected to differ between
1014
        nodes, since it is only run once at instance startup;
1015
        actions/kvm arguments that can vary between systems should be
1016
        done in L{_ExecuteKVMRuntime}
1017

1018
    """
1019
    # pylint: disable=R0912,R0914,R0915
1020
    kvmhelp = self._GetKVMHelpOutput()
1021
    hvp = instance.hvparams
1022

    
1023
    pidfile = self._InstancePidFile(instance.name)
1024
    kvm = constants.KVM_PATH
1025
    kvm_cmd = [kvm]
1026
    kvm_cmd.extend(["-M", self._GetDefaultMachineVersion()])
1027
    # used just by the vnc server, if enabled
1028
    kvm_cmd.extend(["-name", instance.name])
1029
    kvm_cmd.extend(["-m", instance.beparams[constants.BE_MAXMEM]])
1030

    
1031
    smp_list = ["%s" % instance.beparams[constants.BE_VCPUS]]
1032
    if hvp[constants.HV_CPU_CORES]:
1033
      smp_list.append("cores=%s" % hvp[constants.HV_CPU_CORES])
1034
    if hvp[constants.HV_CPU_THREADS]:
1035
      smp_list.append("threads=%s" % hvp[constants.HV_CPU_THREADS])
1036
    if hvp[constants.HV_CPU_SOCKETS]:
1037
      smp_list.append("sockets=%s" % hvp[constants.HV_CPU_SOCKETS])
1038

    
1039
    kvm_cmd.extend(["-smp", ",".join(smp_list)])
1040

    
1041
    kvm_cmd.extend(["-pidfile", pidfile])
1042
    kvm_cmd.extend(["-balloon", "virtio"])
1043
    kvm_cmd.extend(["-daemonize"])
1044
    if not instance.hvparams[constants.HV_ACPI]:
1045
      kvm_cmd.extend(["-no-acpi"])
1046
    if instance.hvparams[constants.HV_REBOOT_BEHAVIOR] == \
1047
        constants.INSTANCE_REBOOT_EXIT:
1048
      kvm_cmd.extend(["-no-reboot"])
1049

    
1050
    kernel_path = hvp[constants.HV_KERNEL_PATH]
1051
    if kernel_path:
1052
      boot_disk = boot_cdrom = boot_floppy = boot_network = False
1053
    else:
1054
      boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
1055
      boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
1056
      boot_floppy = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_FLOPPY
1057
      boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
1058

    
1059
    self.ValidateParameters(hvp)
1060

    
1061
    if startup_paused:
1062
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1063

    
1064
    if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED and
1065
        self._ENABLE_KVM_RE.search(kvmhelp)):
1066
      kvm_cmd.extend(["-enable-kvm"])
1067
    elif (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED and
1068
          self._DISABLE_KVM_RE.search(kvmhelp)):
1069
      kvm_cmd.extend(["-disable-kvm"])
1070

    
1071
    if boot_network:
1072
      kvm_cmd.extend(["-boot", "n"])
1073

    
1074
    # whether this is an older KVM version that uses the boot=on flag
1075
    # on devices
1076
    needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1077

    
1078
    disk_type = hvp[constants.HV_DISK_TYPE]
1079
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
1080
      if_val = ",if=virtio"
1081
    else:
1082
      if_val = ",if=%s" % disk_type
1083
    # Cache mode
1084
    disk_cache = hvp[constants.HV_DISK_CACHE]
1085
    if instance.disk_template in constants.DTS_EXT_MIRROR:
1086
      if disk_cache != "none":
1087
        # TODO: make this a hard error, instead of a silent overwrite
1088
        logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
1089
                        " to prevent shared storage corruption on migration",
1090
                        disk_cache)
1091
      cache_val = ",cache=none"
1092
    elif disk_cache != constants.HT_CACHE_DEFAULT:
1093
      cache_val = ",cache=%s" % disk_cache
1094
    else:
1095
      cache_val = ""
1096
    for cfdev, dev_path in block_devices:
1097
      if cfdev.mode != constants.DISK_RDWR:
1098
        raise errors.HypervisorError("Instance has read-only disks which"
1099
                                     " are not supported by KVM")
1100
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
1101
      boot_val = ""
1102
      if boot_disk:
1103
        kvm_cmd.extend(["-boot", "c"])
1104
        boot_disk = False
1105
        if needs_boot_flag and disk_type != constants.HT_DISK_IDE:
1106
          boot_val = ",boot=on"
1107

    
1108
      drive_val = "file=%s,format=raw%s%s%s" % (dev_path, if_val, boot_val,
1109
                                                cache_val)
1110
      kvm_cmd.extend(["-drive", drive_val])
1111

    
1112
    #Now we can specify a different device type for CDROM devices.
1113
    cdrom_disk_type = hvp[constants.HV_KVM_CDROM_DISK_TYPE]
1114
    if not cdrom_disk_type:
1115
      cdrom_disk_type = disk_type
1116

    
1117
    iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
1118
    if iso_image:
1119
      options = ",format=raw,media=cdrom"
1120
      # set cdrom 'if' type
1121
      if boot_cdrom:
1122
        actual_cdrom_type = constants.HT_DISK_IDE
1123
      elif cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1124
        actual_cdrom_type = "virtio"
1125
      else:
1126
        actual_cdrom_type = cdrom_disk_type
1127
      if_val = ",if=%s" % actual_cdrom_type
1128
      # set boot flag, if needed
1129
      boot_val = ""
1130
      if boot_cdrom:
1131
        kvm_cmd.extend(["-boot", "d"])
1132
        if needs_boot_flag:
1133
          boot_val = ",boot=on"
1134
      # and finally build the entire '-drive' value
1135
      drive_val = "file=%s%s%s%s" % (iso_image, options, if_val, boot_val)
1136
      kvm_cmd.extend(["-drive", drive_val])
1137

    
1138
    iso_image2 = hvp[constants.HV_KVM_CDROM2_IMAGE_PATH]
1139
    if iso_image2:
1140
      options = ",format=raw,media=cdrom"
1141
      if cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1142
        if_val = ",if=virtio"
1143
      else:
1144
        if_val = ",if=%s" % cdrom_disk_type
1145
      drive_val = "file=%s%s%s" % (iso_image2, options, if_val)
1146
      kvm_cmd.extend(["-drive", drive_val])
1147

    
1148
    floppy_image = hvp[constants.HV_KVM_FLOPPY_IMAGE_PATH]
1149
    if floppy_image:
1150
      options = ",format=raw,media=disk"
1151
      if boot_floppy:
1152
        kvm_cmd.extend(["-boot", "a"])
1153
        options = "%s,boot=on" % options
1154
      if_val = ",if=floppy"
1155
      options = "%s%s" % (options, if_val)
1156
      drive_val = "file=%s%s" % (floppy_image, options)
1157
      kvm_cmd.extend(["-drive", drive_val])
1158

    
1159
    if kernel_path:
1160
      kvm_cmd.extend(["-kernel", kernel_path])
1161
      initrd_path = hvp[constants.HV_INITRD_PATH]
1162
      if initrd_path:
1163
        kvm_cmd.extend(["-initrd", initrd_path])
1164
      root_append = ["root=%s" % hvp[constants.HV_ROOT_PATH],
1165
                     hvp[constants.HV_KERNEL_ARGS]]
1166
      if hvp[constants.HV_SERIAL_CONSOLE]:
1167
        serial_speed = hvp[constants.HV_SERIAL_SPEED]
1168
        root_append.append("console=ttyS0,%s" % serial_speed)
1169
      kvm_cmd.extend(["-append", " ".join(root_append)])
1170

    
1171
    mem_path = hvp[constants.HV_MEM_PATH]
1172
    if mem_path:
1173
      kvm_cmd.extend(["-mem-path", mem_path, "-mem-prealloc"])
1174

    
1175
    monitor_dev = ("unix:%s,server,nowait" %
1176
                   self._InstanceMonitor(instance.name))
1177
    kvm_cmd.extend(["-monitor", monitor_dev])
1178
    if hvp[constants.HV_SERIAL_CONSOLE]:
1179
      serial_dev = ("unix:%s,server,nowait" %
1180
                    self._InstanceSerial(instance.name))
1181
      kvm_cmd.extend(["-serial", serial_dev])
1182
    else:
1183
      kvm_cmd.extend(["-serial", "none"])
1184

    
1185
    mouse_type = hvp[constants.HV_USB_MOUSE]
1186
    vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
1187
    spice_bind = hvp[constants.HV_KVM_SPICE_BIND]
1188
    spice_ip_version = None
1189

    
1190
    kvm_cmd.extend(["-usb"])
1191

    
1192
    if mouse_type:
1193
      kvm_cmd.extend(["-usbdevice", mouse_type])
1194
    elif vnc_bind_address:
1195
      kvm_cmd.extend(["-usbdevice", constants.HT_MOUSE_TABLET])
1196

    
1197
    if vnc_bind_address:
1198
      if netutils.IP4Address.IsValid(vnc_bind_address):
1199
        if instance.network_port > constants.VNC_BASE_PORT:
1200
          display = instance.network_port - constants.VNC_BASE_PORT
1201
          if vnc_bind_address == constants.IP4_ADDRESS_ANY:
1202
            vnc_arg = ":%d" % (display)
1203
          else:
1204
            vnc_arg = "%s:%d" % (vnc_bind_address, display)
1205
        else:
1206
          logging.error("Network port is not a valid VNC display (%d < %d)."
1207
                        " Not starting VNC", instance.network_port,
1208
                        constants.VNC_BASE_PORT)
1209
          vnc_arg = "none"
1210

    
1211
        # Only allow tls and other option when not binding to a file, for now.
1212
        # kvm/qemu gets confused otherwise about the filename to use.
1213
        vnc_append = ""
1214
        if hvp[constants.HV_VNC_TLS]:
1215
          vnc_append = "%s,tls" % vnc_append
1216
          if hvp[constants.HV_VNC_X509_VERIFY]:
1217
            vnc_append = "%s,x509verify=%s" % (vnc_append,
1218
                                               hvp[constants.HV_VNC_X509])
1219
          elif hvp[constants.HV_VNC_X509]:
1220
            vnc_append = "%s,x509=%s" % (vnc_append,
1221
                                         hvp[constants.HV_VNC_X509])
1222
        if hvp[constants.HV_VNC_PASSWORD_FILE]:
1223
          vnc_append = "%s,password" % vnc_append
1224

    
1225
        vnc_arg = "%s%s" % (vnc_arg, vnc_append)
1226

    
1227
      else:
1228
        vnc_arg = "unix:%s/%s.vnc" % (vnc_bind_address, instance.name)
1229

    
1230
      kvm_cmd.extend(["-vnc", vnc_arg])
1231
    elif spice_bind:
1232
      # FIXME: this is wrong here; the iface ip address differs
1233
      # between systems, so it should be done in _ExecuteKVMRuntime
1234
      if netutils.IsValidInterface(spice_bind):
1235
        # The user specified a network interface, we have to figure out the IP
1236
        # address.
1237
        addresses = netutils.GetInterfaceIpAddresses(spice_bind)
1238
        spice_ip_version = hvp[constants.HV_KVM_SPICE_IP_VERSION]
1239

    
1240
        # if the user specified an IP version and the interface does not
1241
        # have that kind of IP addresses, throw an exception
1242
        if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1243
          if not addresses[spice_ip_version]:
1244
            raise errors.HypervisorError("spice: unable to get an IPv%s address"
1245
                                         " for %s" % (spice_ip_version,
1246
                                                      spice_bind))
1247

    
1248
        # the user did not specify an IP version, we have to figure it out
1249
        elif (addresses[constants.IP4_VERSION] and
1250
              addresses[constants.IP6_VERSION]):
1251
          # we have both ipv4 and ipv6, let's use the cluster default IP
1252
          # version
1253
          cluster_family = ssconf.SimpleStore().GetPrimaryIPFamily()
1254
          spice_ip_version = \
1255
            netutils.IPAddress.GetVersionFromAddressFamily(cluster_family)
1256
        elif addresses[constants.IP4_VERSION]:
1257
          spice_ip_version = constants.IP4_VERSION
1258
        elif addresses[constants.IP6_VERSION]:
1259
          spice_ip_version = constants.IP6_VERSION
1260
        else:
1261
          raise errors.HypervisorError("spice: unable to get an IP address"
1262
                                       " for %s" % (spice_bind))
1263

    
1264
        spice_address = addresses[spice_ip_version][0]
1265

    
1266
      else:
1267
        # spice_bind is known to be a valid IP address, because
1268
        # ValidateParameters checked it.
1269
        spice_address = spice_bind
1270

    
1271
      spice_arg = "addr=%s" % spice_address
1272
      if hvp[constants.HV_KVM_SPICE_USE_TLS]:
1273
        spice_arg = ("%s,tls-port=%s,x509-cacert-file=%s" %
1274
                     (spice_arg, instance.network_port,
1275
                      pathutils.SPICE_CACERT_FILE))
1276
        spice_arg = ("%s,x509-key-file=%s,x509-cert-file=%s" %
1277
                     (spice_arg, pathutils.SPICE_CERT_FILE,
1278
                      pathutils.SPICE_CERT_FILE))
1279
        tls_ciphers = hvp[constants.HV_KVM_SPICE_TLS_CIPHERS]
1280
        if tls_ciphers:
1281
          spice_arg = "%s,tls-ciphers=%s" % (spice_arg, tls_ciphers)
1282
      else:
1283
        spice_arg = "%s,port=%s" % (spice_arg, instance.network_port)
1284

    
1285
      if not hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]:
1286
        spice_arg = "%s,disable-ticketing" % spice_arg
1287

    
1288
      if spice_ip_version:
1289
        spice_arg = "%s,ipv%s" % (spice_arg, spice_ip_version)
1290

    
1291
      # Image compression options
1292
      img_lossless = hvp[constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR]
1293
      img_jpeg = hvp[constants.HV_KVM_SPICE_JPEG_IMG_COMPR]
1294
      img_zlib_glz = hvp[constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR]
1295
      if img_lossless:
1296
        spice_arg = "%s,image-compression=%s" % (spice_arg, img_lossless)
1297
      if img_jpeg:
1298
        spice_arg = "%s,jpeg-wan-compression=%s" % (spice_arg, img_jpeg)
1299
      if img_zlib_glz:
1300
        spice_arg = "%s,zlib-glz-wan-compression=%s" % (spice_arg, img_zlib_glz)
1301

    
1302
      # Video stream detection
1303
      video_streaming = hvp[constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION]
1304
      if video_streaming:
1305
        spice_arg = "%s,streaming-video=%s" % (spice_arg, video_streaming)
1306

    
1307
      # Audio compression, by default in qemu-kvm it is on
1308
      if not hvp[constants.HV_KVM_SPICE_AUDIO_COMPR]:
1309
        spice_arg = "%s,playback-compression=off" % spice_arg
1310
      if not hvp[constants.HV_KVM_SPICE_USE_VDAGENT]:
1311
        spice_arg = "%s,agent-mouse=off" % spice_arg
1312
      else:
1313
        # Enable the spice agent communication channel between the host and the
1314
        # agent.
1315
        kvm_cmd.extend(["-device", "virtio-serial-pci"])
1316
        kvm_cmd.extend(["-device", "virtserialport,chardev=spicechannel0,"
1317
                                                   "name=com.redhat.spice.0"])
1318
        kvm_cmd.extend(["-chardev", "spicevmc,id=spicechannel0,name=vdagent"])
1319

    
1320
      logging.info("KVM: SPICE will listen on port %s", instance.network_port)
1321
      kvm_cmd.extend(["-spice", spice_arg])
1322

    
1323
      # Tell kvm to use the paravirtualized graphic card, optimized for SPICE
1324
      kvm_cmd.extend(["-vga", "qxl"])
1325

    
1326
    else:
1327
      kvm_cmd.extend(["-nographic"])
1328

    
1329
    if hvp[constants.HV_USE_LOCALTIME]:
1330
      kvm_cmd.extend(["-localtime"])
1331

    
1332
    if hvp[constants.HV_KVM_USE_CHROOT]:
1333
      kvm_cmd.extend(["-chroot", self._InstanceChrootDir(instance.name)])
1334

    
1335
    # Add qemu-KVM -cpu param
1336
    if hvp[constants.HV_CPU_TYPE]:
1337
      kvm_cmd.extend(["-cpu", hvp[constants.HV_CPU_TYPE]])
1338

    
1339
    # As requested by music lovers
1340
    if hvp[constants.HV_SOUNDHW]:
1341
      kvm_cmd.extend(["-soundhw", hvp[constants.HV_SOUNDHW]])
1342

    
1343
    # Various types of usb devices, comma separated
1344
    if hvp[constants.HV_USB_DEVICES]:
1345
      for dev in hvp[constants.HV_USB_DEVICES].split(","):
1346
        kvm_cmd.extend(["-usbdevice", dev])
1347

    
1348
    # Save the current instance nics, but defer their expansion as parameters,
1349
    # as we'll need to generate executable temp files for them.
1350
    kvm_nics = instance.nics
1351
    hvparams = hvp
1352

    
1353
    return (kvm_cmd, kvm_nics, hvparams)
1354

    
1355
  def _WriteKVMRuntime(self, instance_name, data):
1356
    """Write an instance's KVM runtime
1357

1358
    """
1359
    try:
1360
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1361
                      data=data)
1362
    except EnvironmentError, err:
1363
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1364

    
1365
  def _ReadKVMRuntime(self, instance_name):
1366
    """Read an instance's KVM runtime
1367

1368
    """
1369
    try:
1370
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1371
    except EnvironmentError, err:
1372
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1373
    return file_content
1374

    
1375
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1376
    """Save an instance's KVM runtime
1377

1378
    """
1379
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
1380
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1381
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
1382
    self._WriteKVMRuntime(instance.name, serialized_form)
1383

    
1384
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1385
    """Load an instance's KVM runtime
1386

1387
    """
1388
    if not serialized_runtime:
1389
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1390
    loaded_runtime = serializer.Load(serialized_runtime)
1391
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
1392
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
1393
    return (kvm_cmd, kvm_nics, hvparams)
1394

    
1395
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1396
    """Run the KVM cmd and check for errors
1397

1398
    @type name: string
1399
    @param name: instance name
1400
    @type kvm_cmd: list of strings
1401
    @param kvm_cmd: runcmd input for kvm
1402
    @type tap_fds: list of int
1403
    @param tap_fds: fds of tap devices opened by Ganeti
1404

1405
    """
1406
    try:
1407
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1408
    finally:
1409
      for fd in tap_fds:
1410
        utils_wrapper.CloseFdNoError(fd)
1411

    
1412
    if result.failed:
1413
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1414
                                   (name, result.fail_reason, result.output))
1415
    if not self._InstancePidAlive(name)[2]:
1416
      raise errors.HypervisorError("Failed to start instance %s" % name)
1417

    
1418
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
1419
    """Execute a KVM cmd, after completing it with some last minute data.
1420

1421
    @type incoming: tuple of strings
1422
    @param incoming: (target_host_ip, port)
1423

1424
    """
1425
    # Small _ExecuteKVMRuntime hv parameters programming howto:
1426
    #  - conf_hvp contains the parameters as configured on ganeti. they might
1427
    #    have changed since the instance started; only use them if the change
1428
    #    won't affect the inside of the instance (which hasn't been rebooted).
1429
    #  - up_hvp contains the parameters as they were when the instance was
1430
    #    started, plus any new parameter which has been added between ganeti
1431
    #    versions: it is paramount that those default to a value which won't
1432
    #    affect the inside of the instance as well.
1433
    conf_hvp = instance.hvparams
1434
    name = instance.name
1435
    self._CheckDown(name)
1436

    
1437
    temp_files = []
1438

    
1439
    kvm_cmd, kvm_nics, up_hvp = kvm_runtime
1440
    up_hvp = objects.FillDict(conf_hvp, up_hvp)
1441

    
1442
    kvmhelp = self._GetKVMHelpOutput()
1443
    _, v_major, v_min, _ = self._ParseKVMVersion(kvmhelp)
1444

    
1445
    # We know it's safe to run as a different user upon migration, so we'll use
1446
    # the latest conf, from conf_hvp.
1447
    security_model = conf_hvp[constants.HV_SECURITY_MODEL]
1448
    if security_model == constants.HT_SM_USER:
1449
      kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
1450

    
1451
    keymap = conf_hvp[constants.HV_KEYMAP]
1452
    if keymap:
1453
      keymap_path = self._InstanceKeymapFile(name)
1454
      # If a keymap file is specified, KVM won't use its internal defaults. By
1455
      # first including the "en-us" layout, an error on loading the actual
1456
      # layout (e.g. because it can't be found) won't lead to a non-functional
1457
      # keyboard. A keyboard with incorrect keys is still better than none.
1458
      utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
1459
      kvm_cmd.extend(["-k", keymap_path])
1460

    
1461
    # We have reasons to believe changing something like the nic driver/type
1462
    # upon migration won't exactly fly with the instance kernel, so for nic
1463
    # related parameters we'll use up_hvp
1464
    tapfds = []
1465
    taps = []
1466
    if not kvm_nics:
1467
      kvm_cmd.extend(["-net", "none"])
1468
    else:
1469
      vnet_hdr = False
1470
      tap_extra = ""
1471
      nic_type = up_hvp[constants.HV_NIC_TYPE]
1472
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
1473
        # From version 0.12.0, kvm uses a new sintax for network configuration.
1474
        if (v_major, v_min) >= (0, 12):
1475
          nic_model = "virtio-net-pci"
1476
          vnet_hdr = True
1477
        else:
1478
          nic_model = "virtio"
1479

    
1480
        if up_hvp[constants.HV_VHOST_NET]:
1481
          # vhost_net is only available from version 0.13.0 or newer
1482
          if self._VHOST_RE.search(kvmhelp):
1483
            tap_extra = ",vhost=on"
1484
          else:
1485
            raise errors.HypervisorError("vhost_net is configured"
1486
                                         " but it is not available")
1487
      else:
1488
        nic_model = nic_type
1489

    
1490
      for nic_seq, nic in enumerate(kvm_nics):
1491
        tapname, tapfd = _OpenTap(vnet_hdr)
1492
        tapfds.append(tapfd)
1493
        taps.append(tapname)
1494
        if self._NETDEV_RE.search(kvmhelp):
1495
          nic_val = "%s,mac=%s,netdev=netdev%s" % (nic_model, nic.mac, nic_seq)
1496
          tap_val = "type=tap,id=netdev%s,fd=%d%s" % (nic_seq, tapfd, tap_extra)
1497
          kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
1498
        else:
1499
          nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq,
1500
                                                         nic.mac, nic_model)
1501
          tap_val = "tap,vlan=%s,fd=%d" % (nic_seq, tapfd)
1502
          kvm_cmd.extend(["-net", tap_val, "-net", nic_val])
1503

    
1504
    if incoming:
1505
      target, port = incoming
1506
      kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])
1507

    
1508
    # Changing the vnc password doesn't bother the guest that much. At most it
1509
    # will surprise people who connect to it. Whether positively or negatively
1510
    # it's debatable.
1511
    vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
1512
    vnc_pwd = None
1513
    if vnc_pwd_file:
1514
      try:
1515
        vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
1516
      except EnvironmentError, err:
1517
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
1518
                                     % (vnc_pwd_file, err))
1519

    
1520
    if conf_hvp[constants.HV_KVM_USE_CHROOT]:
1521
      utils.EnsureDirs([(self._InstanceChrootDir(name),
1522
                         constants.SECURE_DIR_MODE)])
1523

    
1524
    # Automatically enable QMP if version is >= 0.14
1525
    if self._QMP_RE.search(kvmhelp):
1526
      logging.debug("Enabling QMP")
1527
      kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
1528
                      self._InstanceQmpMonitor(instance.name)])
1529

    
1530
    # Configure the network now for starting instances and bridged interfaces,
1531
    # during FinalizeMigration for incoming instances' routed interfaces
1532
    for nic_seq, nic in enumerate(kvm_nics):
1533
      if (incoming and
1534
          nic.nicparams[constants.NIC_MODE] != constants.NIC_MODE_BRIDGED):
1535
        continue
1536
      self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
1537

    
1538
    # CPU affinity requires kvm to start paused, so we set this flag if the
1539
    # instance is not already paused and if we are not going to accept a
1540
    # migrating instance. In the latter case, pausing is not needed.
1541
    start_kvm_paused = not (_KVM_START_PAUSED_FLAG in kvm_cmd) and not incoming
1542
    if start_kvm_paused:
1543
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1544

    
1545
    # Note: CPU pinning is using up_hvp since changes take effect
1546
    # during instance startup anyway, and to avoid problems when soft
1547
    # rebooting the instance.
1548
    cpu_pinning = False
1549
    if up_hvp.get(constants.HV_CPU_MASK, None):
1550
      cpu_pinning = True
1551

    
1552
    if security_model == constants.HT_SM_POOL:
1553
      ss = ssconf.SimpleStore()
1554
      uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
1555
      all_uids = set(uidpool.ExpandUidPool(uid_pool))
1556
      uid = uidpool.RequestUnusedUid(all_uids)
1557
      try:
1558
        username = pwd.getpwuid(uid.GetUid()).pw_name
1559
        kvm_cmd.extend(["-runas", username])
1560
        self._RunKVMCmd(name, kvm_cmd, tapfds)
1561
      except:
1562
        uidpool.ReleaseUid(uid)
1563
        raise
1564
      else:
1565
        uid.Unlock()
1566
        utils.WriteFile(self._InstanceUidFile(name), data=uid.AsStr())
1567
    else:
1568
      self._RunKVMCmd(name, kvm_cmd, tapfds)
1569

    
1570
    utils.EnsureDirs([(self._InstanceNICDir(instance.name),
1571
                     constants.RUN_DIRS_MODE)])
1572
    for nic_seq, tap in enumerate(taps):
1573
      utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
1574
                      data=tap)
1575

    
1576
    if vnc_pwd:
1577
      change_cmd = "change vnc password %s" % vnc_pwd
1578
      self._CallMonitorCommand(instance.name, change_cmd)
1579

    
1580
    # Setting SPICE password. We are not vulnerable to malicious passwordless
1581
    # connection attempts because SPICE by default does not allow connections
1582
    # if neither a password nor the "disable_ticketing" options are specified.
1583
    # As soon as we send the password via QMP, that password is a valid ticket
1584
    # for connection.
1585
    spice_password_file = conf_hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]
1586
    if spice_password_file:
1587
      spice_pwd = ""
1588
      try:
1589
        spice_pwd = utils.ReadOneLineFile(spice_password_file, strict=True)
1590
      except EnvironmentError, err:
1591
        raise errors.HypervisorError("Failed to open SPICE password file %s: %s"
1592
                                     % (spice_password_file, err))
1593

    
1594
      qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
1595
      qmp.connect()
1596
      arguments = {
1597
          "protocol": "spice",
1598
          "password": spice_pwd,
1599
      }
1600
      qmp.Execute("set_password", arguments)
1601

    
1602
    for filename in temp_files:
1603
      utils.RemoveFile(filename)
1604

    
1605
    # If requested, set CPU affinity and resume instance execution
1606
    if cpu_pinning:
1607
      self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK])
1608

    
1609
    start_memory = self._InstanceStartupMemory(instance)
1610
    if start_memory < instance.beparams[constants.BE_MAXMEM]:
1611
      self.BalloonInstanceMemory(instance, start_memory)
1612

    
1613
    if start_kvm_paused:
1614
      # To control CPU pinning, ballooning, and vnc/spice passwords
1615
      # the VM was started in a frozen state. If freezing was not
1616
      # explicitly requested resume the vm status.
1617
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1618

    
1619
  def StartInstance(self, instance, block_devices, startup_paused):
1620
    """Start an instance.
1621

1622
    """
1623
    self._CheckDown(instance.name)
1624
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1625
                                           startup_paused)
1626
    self._SaveKVMRuntime(instance, kvm_runtime)
1627
    self._ExecuteKVMRuntime(instance, kvm_runtime)
1628

    
1629
  def _CallMonitorCommand(self, instance_name, command):
1630
    """Invoke a command on the instance monitor.
1631

1632
    """
1633
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1634
             (utils.ShellQuote(command),
1635
              constants.SOCAT_PATH,
1636
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1637
    result = utils.RunCmd(socat)
1638
    if result.failed:
1639
      msg = ("Failed to send command '%s' to instance %s."
1640
             " output: %s, error: %s, fail_reason: %s" %
1641
             (command, instance_name,
1642
              result.stdout, result.stderr, result.fail_reason))
1643
      raise errors.HypervisorError(msg)
1644

    
1645
    return result
1646

    
1647
  @classmethod
1648
  def _ParseKVMVersion(cls, text):
1649
    """Parse the KVM version from the --help output.
1650

1651
    @type text: string
1652
    @param text: output of kvm --help
1653
    @return: (version, v_maj, v_min, v_rev)
1654
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1655

1656
    """
1657
    match = cls._VERSION_RE.search(text.splitlines()[0])
1658
    if not match:
1659
      raise errors.HypervisorError("Unable to get KVM version")
1660

    
1661
    v_all = match.group(0)
1662
    v_maj = int(match.group(1))
1663
    v_min = int(match.group(2))
1664
    if match.group(4):
1665
      v_rev = int(match.group(4))
1666
    else:
1667
      v_rev = 0
1668
    return (v_all, v_maj, v_min, v_rev)
1669

    
1670
  @classmethod
1671
  def _GetKVMHelpOutput(cls):
1672
    """Return the KVM help output.
1673

1674
    @return: output of kvm --help
1675
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
1676

1677
    """
1678
    result = utils.RunCmd([constants.KVM_PATH, "--help"])
1679
    if result.failed:
1680
      raise errors.HypervisorError("Unable to get KVM help output")
1681
    return result.output
1682

    
1683
  @classmethod
1684
  def _GetKVMVersion(cls):
1685
    """Return the installed KVM version.
1686

1687
    @return: (version, v_maj, v_min, v_rev)
1688
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1689

1690
    """
1691
    return cls._ParseKVMVersion(cls._GetKVMHelpOutput())
1692

    
1693
  def StopInstance(self, instance, force=False, retry=False, name=None):
1694
    """Stop an instance.
1695

1696
    """
1697
    if name is not None and not force:
1698
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
1699
    if name is None:
1700
      name = instance.name
1701
      acpi = instance.hvparams[constants.HV_ACPI]
1702
    else:
1703
      acpi = False
1704
    _, pid, alive = self._InstancePidAlive(name)
1705
    if pid > 0 and alive:
1706
      if force or not acpi:
1707
        utils.KillProcess(pid)
1708
      else:
1709
        self._CallMonitorCommand(name, "system_powerdown")
1710

    
1711
  @classmethod
1712
  def _GetDefaultMachineVersion(cls):
1713
    """Return the default hardware revision (e.g. pc-1.1)
1714

1715
    """
1716
    result = utils.RunCmd([constants.KVM_PATH, "-M", "?"])
1717
    if result.failed:
1718
      raise errors.HypervisorError("Unable to get default hardware revision")
1719
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(result.output)
1720
    if match:
1721
      return match.group(1)
1722
    else:
1723
      return "pc"
1724

    
1725
  def CleanupInstance(self, instance_name):
1726
    """Cleanup after a stopped instance
1727

1728
    """
1729
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1730
    if pid > 0 and alive:
1731
      raise errors.HypervisorError("Cannot cleanup a live instance")
1732
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1733

    
1734
  def RebootInstance(self, instance):
1735
    """Reboot an instance.
1736

1737
    """
1738
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
1739
    # socket the instance will stop, but now power up again. So we'll resort
1740
    # to shutdown and restart.
1741
    _, _, alive = self._InstancePidAlive(instance.name)
1742
    if not alive:
1743
      raise errors.HypervisorError("Failed to reboot instance %s:"
1744
                                   " not running" % instance.name)
1745
    # StopInstance will delete the saved KVM runtime so:
1746
    # ...first load it...
1747
    kvm_runtime = self._LoadKVMRuntime(instance)
1748
    # ...now we can safely call StopInstance...
1749
    if not self.StopInstance(instance):
1750
      self.StopInstance(instance, force=True)
1751
    # ...and finally we can save it again, and execute it...
1752
    self._SaveKVMRuntime(instance, kvm_runtime)
1753
    self._ExecuteKVMRuntime(instance, kvm_runtime)
1754

    
1755
  def MigrationInfo(self, instance):
1756
    """Get instance information to perform a migration.
1757

1758
    @type instance: L{objects.Instance}
1759
    @param instance: instance to be migrated
1760
    @rtype: string
1761
    @return: content of the KVM runtime file
1762

1763
    """
1764
    return self._ReadKVMRuntime(instance.name)
1765

    
1766
  def AcceptInstance(self, instance, info, target):
1767
    """Prepare to accept an instance.
1768

1769
    @type instance: L{objects.Instance}
1770
    @param instance: instance to be accepted
1771
    @type info: string
1772
    @param info: content of the KVM runtime file on the source node
1773
    @type target: string
1774
    @param target: target host (usually ip), on this node
1775

1776
    """
1777
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1778
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1779
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
1780

    
1781
  def FinalizeMigrationDst(self, instance, info, success):
1782
    """Finalize the instance migration on the target node.
1783

1784
    Stop the incoming mode KVM.
1785

1786
    @type instance: L{objects.Instance}
1787
    @param instance: instance whose migration is being finalized
1788

1789
    """
1790
    if success:
1791
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1792
      kvm_nics = kvm_runtime[1]
1793

    
1794
      for nic_seq, nic in enumerate(kvm_nics):
1795
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1796
          # Bridged interfaces have already been configured
1797
          continue
1798
        try:
1799
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
1800
        except EnvironmentError, err:
1801
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
1802
                          instance.name, nic_seq, str(err))
1803
          continue
1804
        try:
1805
          self._ConfigureNIC(instance, nic_seq, nic, tap)
1806
        except errors.HypervisorError, err:
1807
          logging.warning(str(err))
1808

    
1809
      self._WriteKVMRuntime(instance.name, info)
1810
    else:
1811
      self.StopInstance(instance, force=True)
1812

    
1813
  def MigrateInstance(self, instance, target, live):
1814
    """Migrate an instance to a target node.
1815

1816
    The migration will not be attempted if the instance is not
1817
    currently running.
1818

1819
    @type instance: L{objects.Instance}
1820
    @param instance: the instance to be migrated
1821
    @type target: string
1822
    @param target: ip address of the target node
1823
    @type live: boolean
1824
    @param live: perform a live migration
1825

1826
    """
1827
    instance_name = instance.name
1828
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
1829
    _, _, alive = self._InstancePidAlive(instance_name)
1830
    if not alive:
1831
      raise errors.HypervisorError("Instance not running, cannot migrate")
1832

    
1833
    if not live:
1834
      self._CallMonitorCommand(instance_name, "stop")
1835

    
1836
    migrate_command = ("migrate_set_speed %dm" %
1837
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1838
    self._CallMonitorCommand(instance_name, migrate_command)
1839

    
1840
    migrate_command = ("migrate_set_downtime %dms" %
1841
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
1842
    self._CallMonitorCommand(instance_name, migrate_command)
1843

    
1844
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
1845
    self._CallMonitorCommand(instance_name, migrate_command)
1846

    
1847
  def FinalizeMigrationSource(self, instance, success, live):
1848
    """Finalize the instance migration on the source node.
1849

1850
    @type instance: L{objects.Instance}
1851
    @param instance: the instance that was migrated
1852
    @type success: bool
1853
    @param success: whether the migration succeeded or not
1854
    @type live: bool
1855
    @param live: whether the user requested a live migration or not
1856

1857
    """
1858
    if success:
1859
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
1860
      utils.KillProcess(pid)
1861
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
1862
    elif live:
1863
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1864

    
1865
  def GetMigrationStatus(self, instance):
1866
    """Get the migration status
1867

1868
    @type instance: L{objects.Instance}
1869
    @param instance: the instance that is being migrated
1870
    @rtype: L{objects.MigrationStatus}
1871
    @return: the status of the current migration (one of
1872
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
1873
             progress info that can be retrieved from the hypervisor
1874

1875
    """
1876
    info_command = "info migrate"
1877
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
1878
      result = self._CallMonitorCommand(instance.name, info_command)
1879
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
1880
      if not match:
1881
        if not result.stdout:
1882
          logging.info("KVM: empty 'info migrate' result")
1883
        else:
1884
          logging.warning("KVM: unknown 'info migrate' result: %s",
1885
                          result.stdout)
1886
      else:
1887
        status = match.group(1)
1888
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
1889
          migration_status = objects.MigrationStatus(status=status)
1890
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
1891
          if match:
1892
            migration_status.transferred_ram = match.group("transferred")
1893
            migration_status.total_ram = match.group("total")
1894

    
1895
          return migration_status
1896

    
1897
        logging.warning("KVM: unknown migration status '%s'", status)
1898

    
1899
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1900

    
1901
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
1902

    
1903
  def BalloonInstanceMemory(self, instance, mem):
1904
    """Balloon an instance memory to a certain value.
1905

1906
    @type instance: L{objects.Instance}
1907
    @param instance: instance to be accepted
1908
    @type mem: int
1909
    @param mem: actual memory size to use for instance runtime
1910

1911
    """
1912
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
1913

    
1914
  def GetNodeInfo(self):
1915
    """Return information about the node.
1916

1917
    @return: a dict with the following keys (values in MiB):
1918
          - memory_total: the total memory size on the node
1919
          - memory_free: the available memory on the node for instances
1920
          - memory_dom0: the memory used by the node itself, if available
1921
          - hv_version: the hypervisor version in the form (major, minor,
1922
                        revision)
1923

1924
    """
1925
    result = self.GetLinuxNodeInfo()
1926
    _, v_major, v_min, v_rev = self._GetKVMVersion()
1927
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
1928
    return result
1929

    
1930
  @classmethod
1931
  def GetInstanceConsole(cls, instance, hvparams, beparams):
1932
    """Return a command for connecting to the console of an instance.
1933

1934
    """
1935
    if hvparams[constants.HV_SERIAL_CONSOLE]:
1936
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
1937
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
1938
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
1939
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
1940
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
1941
      return objects.InstanceConsole(instance=instance.name,
1942
                                     kind=constants.CONS_SSH,
1943
                                     host=instance.primary_node,
1944
                                     user=constants.SSH_CONSOLE_USER,
1945
                                     command=cmd)
1946

    
1947
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
1948
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
1949
      display = instance.network_port - constants.VNC_BASE_PORT
1950
      return objects.InstanceConsole(instance=instance.name,
1951
                                     kind=constants.CONS_VNC,
1952
                                     host=vnc_bind_address,
1953
                                     port=instance.network_port,
1954
                                     display=display)
1955

    
1956
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
1957
    if spice_bind:
1958
      return objects.InstanceConsole(instance=instance.name,
1959
                                     kind=constants.CONS_SPICE,
1960
                                     host=spice_bind,
1961
                                     port=instance.network_port)
1962

    
1963
    return objects.InstanceConsole(instance=instance.name,
1964
                                   kind=constants.CONS_MESSAGE,
1965
                                   message=("No serial shell for instance %s" %
1966
                                            instance.name))
1967

    
1968
  def Verify(self):
1969
    """Verify the hypervisor.
1970

1971
    Check that the binary exists.
1972

1973
    """
1974
    if not os.path.exists(constants.KVM_PATH):
1975
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
1976
    if not os.path.exists(constants.SOCAT_PATH):
1977
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
1978

    
1979
  @classmethod
1980
  def CheckParameterSyntax(cls, hvparams):
1981
    """Check the given parameters for validity.
1982

1983
    @type hvparams:  dict
1984
    @param hvparams: dictionary with parameter names/value
1985
    @raise errors.HypervisorError: when a parameter is not valid
1986

1987
    """
1988
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
1989

    
1990
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
1991
    if kernel_path:
1992
      if not hvparams[constants.HV_ROOT_PATH]:
1993
        raise errors.HypervisorError("Need a root partition for the instance,"
1994
                                     " if a kernel is defined")
1995

    
1996
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
1997
        not hvparams[constants.HV_VNC_X509]):
1998
      raise errors.HypervisorError("%s must be defined, if %s is" %
1999
                                   (constants.HV_VNC_X509,
2000
                                    constants.HV_VNC_X509_VERIFY))
2001

    
2002
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2003
      serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2004
      valid_speeds = constants.VALID_SERIAL_SPEEDS
2005
      if not serial_speed or serial_speed not in valid_speeds:
2006
        raise errors.HypervisorError("Invalid serial console speed, must be"
2007
                                     " one of: %s" %
2008
                                     utils.CommaJoin(valid_speeds))
2009

    
2010
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2011
    if (boot_order == constants.HT_BO_CDROM and
2012
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2013
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2014
                                   " ISO path")
2015

    
2016
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2017
    if security_model == constants.HT_SM_USER:
2018
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
2019
        raise errors.HypervisorError("A security domain (user to run kvm as)"
2020
                                     " must be specified")
2021
    elif (security_model == constants.HT_SM_NONE or
2022
          security_model == constants.HT_SM_POOL):
2023
      if hvparams[constants.HV_SECURITY_DOMAIN]:
2024
        raise errors.HypervisorError("Cannot have a security domain when the"
2025
                                     " security model is 'none' or 'pool'")
2026

    
2027
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2028
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2029
    if spice_bind:
2030
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2031
        # if an IP version is specified, the spice_bind parameter must be an
2032
        # IP of that family
2033
        if (netutils.IP4Address.IsValid(spice_bind) and
2034
            spice_ip_version != constants.IP4_VERSION):
2035
          raise errors.HypervisorError("spice: got an IPv4 address (%s), but"
2036
                                       " the specified IP version is %s" %
2037
                                       (spice_bind, spice_ip_version))
2038

    
2039
        if (netutils.IP6Address.IsValid(spice_bind) and
2040
            spice_ip_version != constants.IP6_VERSION):
2041
          raise errors.HypervisorError("spice: got an IPv6 address (%s), but"
2042
                                       " the specified IP version is %s" %
2043
                                       (spice_bind, spice_ip_version))
2044
    else:
2045
      # All the other SPICE parameters depend on spice_bind being set. Raise an
2046
      # error if any of them is set without it.
2047
      for param in _SPICE_ADDITIONAL_PARAMS:
2048
        if hvparams[param]:
2049
          raise errors.HypervisorError("spice: %s requires %s to be set" %
2050
                                       (param, constants.HV_KVM_SPICE_BIND))
2051

    
2052
  @classmethod
2053
  def ValidateParameters(cls, hvparams):
2054
    """Check the given parameters for validity.
2055

2056
    @type hvparams:  dict
2057
    @param hvparams: dictionary with parameter names/value
2058
    @raise errors.HypervisorError: when a parameter is not valid
2059

2060
    """
2061
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2062

    
2063
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2064
    if security_model == constants.HT_SM_USER:
2065
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2066
      try:
2067
        pwd.getpwnam(username)
2068
      except KeyError:
2069
        raise errors.HypervisorError("Unknown security domain user %s"
2070
                                     % username)
2071

    
2072
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2073
    if spice_bind:
2074
      # only one of VNC and SPICE can be used currently.
2075
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2076
        raise errors.HypervisorError("both SPICE and VNC are configured, but"
2077
                                     " only one of them can be used at a"
2078
                                     " given time.")
2079

    
2080
      # KVM version should be >= 0.14.0
2081
      kvmhelp = cls._GetKVMHelpOutput()
2082
      if not cls._SPICE_RE.search(kvmhelp):
2083
        raise errors.HypervisorError("spice is configured, but it is not"
2084
                                     " supported according to kvm --help")
2085

    
2086
      # if spice_bind is not an IP address, it must be a valid interface
2087
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind)
2088
                       or netutils.IP6Address.IsValid(spice_bind))
2089
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2090
        raise errors.HypervisorError("spice: the %s parameter must be either"
2091
                                     " a valid IP address or interface name" %
2092
                                     constants.HV_KVM_SPICE_BIND)
2093

    
2094
  @classmethod
2095
  def PowercycleNode(cls):
2096
    """KVM powercycle, just a wrapper over Linux powercycle.
2097

2098
    """
2099
    cls.LinuxPowercycle()