Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 4b9638dc

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

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

    
553
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
554
  _MIGRATION_INFO_RETRY_DELAY = 2
555

    
556
  _VERSION_RE = re.compile(r"\b(\d+)\.(\d+)(\.(\d+))?\b")
557

    
558
  _CPU_INFO_RE = re.compile(r"cpu\s+\#(\d+).*thread_id\s*=\s*(\d+)", re.I)
559
  _CPU_INFO_CMD = "info cpus"
560
  _CONT_CMD = "cont"
561

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

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

    
575
  ANCILLARY_FILES = [
576
    _KVM_NETWORK_SCRIPT,
577
    ]
578
  ANCILLARY_FILES_OPT = [
579
    _KVM_NETWORK_SCRIPT,
580
    ]
581

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

    
589
  @classmethod
590
  def _InstancePidFile(cls, instance_name):
591
    """Returns the instance pidfile.
592

593
    """
594
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
595

    
596
  @classmethod
597
  def _InstanceUidFile(cls, instance_name):
598
    """Returns the instance uidfile.
599

600
    """
601
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
602

    
603
  @classmethod
604
  def _InstancePidInfo(cls, pid):
605
    """Check pid file for instance information.
606

607
    Check that a pid file is associated with an instance, and retrieve
608
    information from its command line.
609

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

616
    """
617
    alive = utils.IsProcessAlive(pid)
618
    if not alive:
619
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
620

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

    
628
    instance = None
629
    memory = 0
630
    vcpus = 0
631

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

    
642
    if instance is None:
643
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
644
                                   " instance" % pid)
645

    
646
    return (instance, memory, vcpus)
647

    
648
  def _InstancePidAlive(self, instance_name):
649
    """Returns the instance pidfile, pid, and liveness.
650

651
    @type instance_name: string
652
    @param instance_name: instance name
653
    @rtype: tuple
654
    @return: (pid file name, pid, liveness)
655

656
    """
657
    pidfile = self._InstancePidFile(instance_name)
658
    pid = utils.ReadPidFile(pidfile)
659

    
660
    alive = False
661
    try:
662
      cmd_instance = self._InstancePidInfo(pid)[0]
663
      alive = (cmd_instance == instance_name)
664
    except errors.HypervisorError:
665
      pass
666

    
667
    return (pidfile, pid, alive)
668

    
669
  def _CheckDown(self, instance_name):
670
    """Raises an error unless the given instance is down.
671

672
    """
673
    alive = self._InstancePidAlive(instance_name)[2]
674
    if alive:
675
      raise errors.HypervisorError("Failed to start instance %s: %s" %
676
                                   (instance_name, "already running"))
677

    
678
  @classmethod
679
  def _InstanceMonitor(cls, instance_name):
680
    """Returns the instance monitor socket name
681

682
    """
683
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
684

    
685
  @classmethod
686
  def _InstanceSerial(cls, instance_name):
687
    """Returns the instance serial socket name
688

689
    """
690
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
691

    
692
  @classmethod
693
  def _InstanceQmpMonitor(cls, instance_name):
694
    """Returns the instance serial QMP socket name
695

696
    """
697
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
698

    
699
  @staticmethod
700
  def _SocatUnixConsoleParams():
701
    """Returns the correct parameters for socat
702

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

705
    """
706
    if constants.SOCAT_USE_ESCAPE:
707
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
708
    else:
709
      return "echo=0,icanon=0"
710

    
711
  @classmethod
712
  def _InstanceKVMRuntime(cls, instance_name):
713
    """Returns the instance KVM runtime filename
714

715
    """
716
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
717

    
718
  @classmethod
719
  def _InstanceChrootDir(cls, instance_name):
720
    """Returns the name of the KVM chroot dir of the instance
721

722
    """
723
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
724

    
725
  @classmethod
726
  def _InstanceNICDir(cls, instance_name):
727
    """Returns the name of the directory holding the tap device files for a
728
    given instance.
729

730
    """
731
    return utils.PathJoin(cls._NICS_DIR, instance_name)
732

    
733
  @classmethod
734
  def _InstanceNICFile(cls, instance_name, seq):
735
    """Returns the name of the file containing the tap device for a given NIC
736

737
    """
738
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
739

    
740
  @classmethod
741
  def _InstanceKeymapFile(cls, instance_name):
742
    """Returns the name of the file containing the keymap for a given instance
743

744
    """
745
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
746

    
747
  @classmethod
748
  def _TryReadUidFile(cls, uid_file):
749
    """Try to read a uid file
750

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

    
762
  @classmethod
763
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
764
    """Removes an instance's rutime sockets/files/dirs.
765

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

    
802
  @staticmethod
803
  def _ConfigureNIC(instance, seq, nic, tap):
804
    """Run the network configuration script for a specified NIC
805

806
    @param instance: instance we're acting on
807
    @type instance: instance object
808
    @param seq: nic sequence number
809
    @type seq: int
810
    @param nic: nic we're acting on
811
    @type nic: nic object
812
    @param tap: the host's tap interface this NIC corresponds to
813
    @type tap: str
814

815
    """
816
    if instance.tags:
817
      tags = " ".join(instance.tags)
818
    else:
819
      tags = ""
820

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

    
831
    if nic.ip:
832
      env["IP"] = nic.ip
833

    
834
    if nic.nicparams[constants.NIC_LINK]:
835
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
836

    
837
    if nic.network:
838
      n = objects.Network.FromDict(nic.netinfo)
839
      _BuildNetworkEnv(nic.network, n.network, n.gateway,
840
                       n.network6, n.gateway6, n.network_type,
841
                       n.mac_prefix, n.tags, env)
842

    
843
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
844
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
845

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

    
852
  @staticmethod
853
  def _VerifyAffinityPackage():
854
    if affinity is None:
855
      raise errors.HypervisorError("affinity Python package not"
856
                                   " found; cannot use CPU pinning under KVM")
857

    
858
  @staticmethod
859
  def _BuildAffinityCpuMask(cpu_list):
860
    """Create a CPU mask suitable for sched_setaffinity from a list of
861
    CPUs.
862

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

866
    @type cpu_list: list of int
867
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
868
    @rtype: int
869
    @return: a bit mask of CPU affinities
870

871
    """
872
    if cpu_list == constants.CPU_PINNING_OFF:
873
      return constants.CPU_PINNING_ALL_KVM
874
    else:
875
      return sum(2 ** cpu for cpu in cpu_list)
876

    
877
  @classmethod
878
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
879
    """Change CPU affinity for running VM according to given CPU mask.
880

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

889
    """
890
    # Convert the string CPU mask to a list of list of int's
891
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
892

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

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

    
916
  def _GetVcpuThreadIds(self, instance_name):
917
    """Get a mapping of vCPU no. to thread IDs for the instance
918

919
    @type instance_name: string
920
    @param instance_name: instance in question
921
    @rtype: dictionary of int:int
922
    @return: a dictionary mapping vCPU numbers to thread IDs
923

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

    
934
    return result
935

    
936
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
937
    """Complete CPU pinning.
938

939
    @type instance_name: string
940
    @param instance_name: name of instance
941
    @type cpu_mask: string
942
    @param cpu_mask: CPU pinning mask as entered by user
943

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

    
952
  def ListInstances(self):
953
    """Get the list of running instances.
954

955
    We can do this by listing our live instances directory and
956
    checking whether the associated kvm process is still alive.
957

958
    """
959
    result = []
960
    for name in os.listdir(self._PIDS_DIR):
961
      if self._InstancePidAlive(name)[2]:
962
        result.append(name)
963
    return result
964

    
965
  def GetInstanceInfo(self, instance_name):
966
    """Get instance properties.
967

968
    @type instance_name: string
969
    @param instance_name: the instance name
970
    @rtype: tuple of strings
971
    @return: (name, id, memory, vcpus, stat, times)
972

973
    """
974
    _, pid, alive = self._InstancePidAlive(instance_name)
975
    if not alive:
976
      return None
977

    
978
    _, memory, vcpus = self._InstancePidInfo(pid)
979
    istat = "---b-"
980
    times = "0"
981

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

    
993
    return (instance_name, pid, memory, vcpus, istat, times)
994

    
995
  def GetAllInstancesInfo(self):
996
    """Get properties of all instances.
997

998
    @return: list of tuples (name, id, memory, vcpus, stat, times)
999

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

    
1012
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused,
1013
                          kvmhelp):
1014
    """Generate KVM information to start an instance.
1015

1016
    @type kvmhelp: string
1017
    @param kvmhelp: output of kvm --help
1018
    @attention: this function must not have any side-effects; for
1019
        example, it must not write to the filesystem, or read values
1020
        from the current system the are expected to differ between
1021
        nodes, since it is only run once at instance startup;
1022
        actions/kvm arguments that can vary between systems should be
1023
        done in L{_ExecuteKVMRuntime}
1024

1025
    """
1026
    # pylint: disable=R0912,R0914,R0915
1027
    hvp = instance.hvparams
1028

    
1029
    pidfile = self._InstancePidFile(instance.name)
1030
    kvm = hvp[constants.HV_KVM_PATH]
1031
    kvm_cmd = [kvm]
1032
    # used just by the vnc server, if enabled
1033
    kvm_cmd.extend(["-name", instance.name])
1034
    kvm_cmd.extend(["-m", instance.beparams[constants.BE_MAXMEM]])
1035

    
1036
    smp_list = ["%s" % instance.beparams[constants.BE_VCPUS]]
1037
    if hvp[constants.HV_CPU_CORES]:
1038
      smp_list.append("cores=%s" % hvp[constants.HV_CPU_CORES])
1039
    if hvp[constants.HV_CPU_THREADS]:
1040
      smp_list.append("threads=%s" % hvp[constants.HV_CPU_THREADS])
1041
    if hvp[constants.HV_CPU_SOCKETS]:
1042
      smp_list.append("sockets=%s" % hvp[constants.HV_CPU_SOCKETS])
1043

    
1044
    kvm_cmd.extend(["-smp", ",".join(smp_list)])
1045

    
1046
    kvm_cmd.extend(["-pidfile", pidfile])
1047
    kvm_cmd.extend(["-balloon", "virtio"])
1048
    kvm_cmd.extend(["-daemonize"])
1049
    if not instance.hvparams[constants.HV_ACPI]:
1050
      kvm_cmd.extend(["-no-acpi"])
1051
    if instance.hvparams[constants.HV_REBOOT_BEHAVIOR] == \
1052
        constants.INSTANCE_REBOOT_EXIT:
1053
      kvm_cmd.extend(["-no-reboot"])
1054

    
1055
    mversion = hvp[constants.HV_KVM_MACHINE_VERSION]
1056
    if not mversion:
1057
      mversion = self._GetDefaultMachineVersion(kvm)
1058
    kvm_cmd.extend(["-M", mversion])
1059

    
1060
    kernel_path = hvp[constants.HV_KERNEL_PATH]
1061
    if kernel_path:
1062
      boot_disk = boot_cdrom = boot_floppy = boot_network = False
1063
    else:
1064
      boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
1065
      boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
1066
      boot_floppy = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_FLOPPY
1067
      boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
1068

    
1069
    self.ValidateParameters(hvp)
1070

    
1071
    if startup_paused:
1072
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1073

    
1074
    if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED and
1075
        self._ENABLE_KVM_RE.search(kvmhelp)):
1076
      kvm_cmd.extend(["-enable-kvm"])
1077
    elif (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED and
1078
          self._DISABLE_KVM_RE.search(kvmhelp)):
1079
      kvm_cmd.extend(["-disable-kvm"])
1080

    
1081
    if boot_network:
1082
      kvm_cmd.extend(["-boot", "n"])
1083

    
1084
    # whether this is an older KVM version that uses the boot=on flag
1085
    # on devices
1086
    needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1087

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

    
1118
      drive_val = "file=%s,format=raw%s%s%s" % (dev_path, if_val, boot_val,
1119
                                                cache_val)
1120
      kvm_cmd.extend(["-drive", drive_val])
1121

    
1122
    #Now we can specify a different device type for CDROM devices.
1123
    cdrom_disk_type = hvp[constants.HV_KVM_CDROM_DISK_TYPE]
1124
    if not cdrom_disk_type:
1125
      cdrom_disk_type = disk_type
1126

    
1127
    iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
1128
    if iso_image:
1129
      options = ",format=raw,media=cdrom"
1130
      # set cdrom 'if' type
1131
      if boot_cdrom:
1132
        actual_cdrom_type = constants.HT_DISK_IDE
1133
      elif cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1134
        actual_cdrom_type = "virtio"
1135
      else:
1136
        actual_cdrom_type = cdrom_disk_type
1137
      if_val = ",if=%s" % actual_cdrom_type
1138
      # set boot flag, if needed
1139
      boot_val = ""
1140
      if boot_cdrom:
1141
        kvm_cmd.extend(["-boot", "d"])
1142
        if needs_boot_flag:
1143
          boot_val = ",boot=on"
1144
      # and finally build the entire '-drive' value
1145
      drive_val = "file=%s%s%s%s" % (iso_image, options, if_val, boot_val)
1146
      kvm_cmd.extend(["-drive", drive_val])
1147

    
1148
    iso_image2 = hvp[constants.HV_KVM_CDROM2_IMAGE_PATH]
1149
    if iso_image2:
1150
      options = ",format=raw,media=cdrom"
1151
      if cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1152
        if_val = ",if=virtio"
1153
      else:
1154
        if_val = ",if=%s" % cdrom_disk_type
1155
      drive_val = "file=%s%s%s" % (iso_image2, options, if_val)
1156
      kvm_cmd.extend(["-drive", drive_val])
1157

    
1158
    floppy_image = hvp[constants.HV_KVM_FLOPPY_IMAGE_PATH]
1159
    if floppy_image:
1160
      options = ",format=raw,media=disk"
1161
      if boot_floppy:
1162
        kvm_cmd.extend(["-boot", "a"])
1163
        options = "%s,boot=on" % options
1164
      if_val = ",if=floppy"
1165
      options = "%s%s" % (options, if_val)
1166
      drive_val = "file=%s%s" % (floppy_image, options)
1167
      kvm_cmd.extend(["-drive", drive_val])
1168

    
1169
    if kernel_path:
1170
      kvm_cmd.extend(["-kernel", kernel_path])
1171
      initrd_path = hvp[constants.HV_INITRD_PATH]
1172
      if initrd_path:
1173
        kvm_cmd.extend(["-initrd", initrd_path])
1174
      root_append = ["root=%s" % hvp[constants.HV_ROOT_PATH],
1175
                     hvp[constants.HV_KERNEL_ARGS]]
1176
      if hvp[constants.HV_SERIAL_CONSOLE]:
1177
        serial_speed = hvp[constants.HV_SERIAL_SPEED]
1178
        root_append.append("console=ttyS0,%s" % serial_speed)
1179
      kvm_cmd.extend(["-append", " ".join(root_append)])
1180

    
1181
    mem_path = hvp[constants.HV_MEM_PATH]
1182
    if mem_path:
1183
      kvm_cmd.extend(["-mem-path", mem_path, "-mem-prealloc"])
1184

    
1185
    monitor_dev = ("unix:%s,server,nowait" %
1186
                   self._InstanceMonitor(instance.name))
1187
    kvm_cmd.extend(["-monitor", monitor_dev])
1188
    if hvp[constants.HV_SERIAL_CONSOLE]:
1189
      serial_dev = ("unix:%s,server,nowait" %
1190
                    self._InstanceSerial(instance.name))
1191
      kvm_cmd.extend(["-serial", serial_dev])
1192
    else:
1193
      kvm_cmd.extend(["-serial", "none"])
1194

    
1195
    mouse_type = hvp[constants.HV_USB_MOUSE]
1196
    vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
1197
    spice_bind = hvp[constants.HV_KVM_SPICE_BIND]
1198
    spice_ip_version = None
1199

    
1200
    kvm_cmd.extend(["-usb"])
1201

    
1202
    if mouse_type:
1203
      kvm_cmd.extend(["-usbdevice", mouse_type])
1204
    elif vnc_bind_address:
1205
      kvm_cmd.extend(["-usbdevice", constants.HT_MOUSE_TABLET])
1206

    
1207
    if vnc_bind_address:
1208
      if netutils.IP4Address.IsValid(vnc_bind_address):
1209
        if instance.network_port > constants.VNC_BASE_PORT:
1210
          display = instance.network_port - constants.VNC_BASE_PORT
1211
          if vnc_bind_address == constants.IP4_ADDRESS_ANY:
1212
            vnc_arg = ":%d" % (display)
1213
          else:
1214
            vnc_arg = "%s:%d" % (vnc_bind_address, display)
1215
        else:
1216
          logging.error("Network port is not a valid VNC display (%d < %d)."
1217
                        " Not starting VNC", instance.network_port,
1218
                        constants.VNC_BASE_PORT)
1219
          vnc_arg = "none"
1220

    
1221
        # Only allow tls and other option when not binding to a file, for now.
1222
        # kvm/qemu gets confused otherwise about the filename to use.
1223
        vnc_append = ""
1224
        if hvp[constants.HV_VNC_TLS]:
1225
          vnc_append = "%s,tls" % vnc_append
1226
          if hvp[constants.HV_VNC_X509_VERIFY]:
1227
            vnc_append = "%s,x509verify=%s" % (vnc_append,
1228
                                               hvp[constants.HV_VNC_X509])
1229
          elif hvp[constants.HV_VNC_X509]:
1230
            vnc_append = "%s,x509=%s" % (vnc_append,
1231
                                         hvp[constants.HV_VNC_X509])
1232
        if hvp[constants.HV_VNC_PASSWORD_FILE]:
1233
          vnc_append = "%s,password" % vnc_append
1234

    
1235
        vnc_arg = "%s%s" % (vnc_arg, vnc_append)
1236

    
1237
      else:
1238
        vnc_arg = "unix:%s/%s.vnc" % (vnc_bind_address, instance.name)
1239

    
1240
      kvm_cmd.extend(["-vnc", vnc_arg])
1241
    elif spice_bind:
1242
      # FIXME: this is wrong here; the iface ip address differs
1243
      # between systems, so it should be done in _ExecuteKVMRuntime
1244
      if netutils.IsValidInterface(spice_bind):
1245
        # The user specified a network interface, we have to figure out the IP
1246
        # address.
1247
        addresses = netutils.GetInterfaceIpAddresses(spice_bind)
1248
        spice_ip_version = hvp[constants.HV_KVM_SPICE_IP_VERSION]
1249

    
1250
        # if the user specified an IP version and the interface does not
1251
        # have that kind of IP addresses, throw an exception
1252
        if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1253
          if not addresses[spice_ip_version]:
1254
            raise errors.HypervisorError("spice: unable to get an IPv%s address"
1255
                                         " for %s" % (spice_ip_version,
1256
                                                      spice_bind))
1257

    
1258
        # the user did not specify an IP version, we have to figure it out
1259
        elif (addresses[constants.IP4_VERSION] and
1260
              addresses[constants.IP6_VERSION]):
1261
          # we have both ipv4 and ipv6, let's use the cluster default IP
1262
          # version
1263
          cluster_family = ssconf.SimpleStore().GetPrimaryIPFamily()
1264
          spice_ip_version = \
1265
            netutils.IPAddress.GetVersionFromAddressFamily(cluster_family)
1266
        elif addresses[constants.IP4_VERSION]:
1267
          spice_ip_version = constants.IP4_VERSION
1268
        elif addresses[constants.IP6_VERSION]:
1269
          spice_ip_version = constants.IP6_VERSION
1270
        else:
1271
          raise errors.HypervisorError("spice: unable to get an IP address"
1272
                                       " for %s" % (spice_bind))
1273

    
1274
        spice_address = addresses[spice_ip_version][0]
1275

    
1276
      else:
1277
        # spice_bind is known to be a valid IP address, because
1278
        # ValidateParameters checked it.
1279
        spice_address = spice_bind
1280

    
1281
      spice_arg = "addr=%s" % spice_address
1282
      if hvp[constants.HV_KVM_SPICE_USE_TLS]:
1283
        spice_arg = ("%s,tls-port=%s,x509-cacert-file=%s" %
1284
                     (spice_arg, instance.network_port,
1285
                      pathutils.SPICE_CACERT_FILE))
1286
        spice_arg = ("%s,x509-key-file=%s,x509-cert-file=%s" %
1287
                     (spice_arg, pathutils.SPICE_CERT_FILE,
1288
                      pathutils.SPICE_CERT_FILE))
1289
        tls_ciphers = hvp[constants.HV_KVM_SPICE_TLS_CIPHERS]
1290
        if tls_ciphers:
1291
          spice_arg = "%s,tls-ciphers=%s" % (spice_arg, tls_ciphers)
1292
      else:
1293
        spice_arg = "%s,port=%s" % (spice_arg, instance.network_port)
1294

    
1295
      if not hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]:
1296
        spice_arg = "%s,disable-ticketing" % spice_arg
1297

    
1298
      if spice_ip_version:
1299
        spice_arg = "%s,ipv%s" % (spice_arg, spice_ip_version)
1300

    
1301
      # Image compression options
1302
      img_lossless = hvp[constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR]
1303
      img_jpeg = hvp[constants.HV_KVM_SPICE_JPEG_IMG_COMPR]
1304
      img_zlib_glz = hvp[constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR]
1305
      if img_lossless:
1306
        spice_arg = "%s,image-compression=%s" % (spice_arg, img_lossless)
1307
      if img_jpeg:
1308
        spice_arg = "%s,jpeg-wan-compression=%s" % (spice_arg, img_jpeg)
1309
      if img_zlib_glz:
1310
        spice_arg = "%s,zlib-glz-wan-compression=%s" % (spice_arg, img_zlib_glz)
1311

    
1312
      # Video stream detection
1313
      video_streaming = hvp[constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION]
1314
      if video_streaming:
1315
        spice_arg = "%s,streaming-video=%s" % (spice_arg, video_streaming)
1316

    
1317
      # Audio compression, by default in qemu-kvm it is on
1318
      if not hvp[constants.HV_KVM_SPICE_AUDIO_COMPR]:
1319
        spice_arg = "%s,playback-compression=off" % spice_arg
1320
      if not hvp[constants.HV_KVM_SPICE_USE_VDAGENT]:
1321
        spice_arg = "%s,agent-mouse=off" % spice_arg
1322
      else:
1323
        # Enable the spice agent communication channel between the host and the
1324
        # agent.
1325
        kvm_cmd.extend(["-device", "virtio-serial-pci"])
1326
        kvm_cmd.extend(["-device", "virtserialport,chardev=spicechannel0,"
1327
                                                   "name=com.redhat.spice.0"])
1328
        kvm_cmd.extend(["-chardev", "spicevmc,id=spicechannel0,name=vdagent"])
1329

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

    
1333
    else:
1334
      kvm_cmd.extend(["-nographic"])
1335

    
1336
    if hvp[constants.HV_USE_LOCALTIME]:
1337
      kvm_cmd.extend(["-localtime"])
1338

    
1339
    if hvp[constants.HV_KVM_USE_CHROOT]:
1340
      kvm_cmd.extend(["-chroot", self._InstanceChrootDir(instance.name)])
1341

    
1342
    # Add qemu-KVM -cpu param
1343
    if hvp[constants.HV_CPU_TYPE]:
1344
      kvm_cmd.extend(["-cpu", hvp[constants.HV_CPU_TYPE]])
1345

    
1346
    # As requested by music lovers
1347
    if hvp[constants.HV_SOUNDHW]:
1348
      kvm_cmd.extend(["-soundhw", hvp[constants.HV_SOUNDHW]])
1349

    
1350
    # Pass a -vga option if requested, or if spice is used, for backwards
1351
    # compatibility.
1352
    if hvp[constants.HV_VGA]:
1353
      kvm_cmd.extend(["-vga", hvp[constants.HV_VGA]])
1354
    elif spice_bind:
1355
      kvm_cmd.extend(["-vga", "qxl"])
1356

    
1357
    # Various types of usb devices, comma separated
1358
    if hvp[constants.HV_USB_DEVICES]:
1359
      for dev in hvp[constants.HV_USB_DEVICES].split(","):
1360
        kvm_cmd.extend(["-usbdevice", dev])
1361

    
1362
    if hvp[constants.HV_KVM_EXTRA]:
1363
      kvm_cmd.extend([hvp[constants.HV_KVM_EXTRA]])
1364

    
1365
    # Save the current instance nics, but defer their expansion as parameters,
1366
    # as we'll need to generate executable temp files for them.
1367
    kvm_nics = instance.nics
1368
    hvparams = hvp
1369

    
1370
    return (kvm_cmd, kvm_nics, hvparams)
1371

    
1372
  def _WriteKVMRuntime(self, instance_name, data):
1373
    """Write an instance's KVM runtime
1374

1375
    """
1376
    try:
1377
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1378
                      data=data)
1379
    except EnvironmentError, err:
1380
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1381

    
1382
  def _ReadKVMRuntime(self, instance_name):
1383
    """Read an instance's KVM runtime
1384

1385
    """
1386
    try:
1387
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1388
    except EnvironmentError, err:
1389
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1390
    return file_content
1391

    
1392
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1393
    """Save an instance's KVM runtime
1394

1395
    """
1396
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
1397
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1398
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
1399
    self._WriteKVMRuntime(instance.name, serialized_form)
1400

    
1401
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1402
    """Load an instance's KVM runtime
1403

1404
    """
1405
    if not serialized_runtime:
1406
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1407
    loaded_runtime = serializer.Load(serialized_runtime)
1408
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
1409
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
1410
    return (kvm_cmd, kvm_nics, hvparams)
1411

    
1412
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1413
    """Run the KVM cmd and check for errors
1414

1415
    @type name: string
1416
    @param name: instance name
1417
    @type kvm_cmd: list of strings
1418
    @param kvm_cmd: runcmd input for kvm
1419
    @type tap_fds: list of int
1420
    @param tap_fds: fds of tap devices opened by Ganeti
1421

1422
    """
1423
    try:
1424
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1425
    finally:
1426
      for fd in tap_fds:
1427
        utils_wrapper.CloseFdNoError(fd)
1428

    
1429
    if result.failed:
1430
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1431
                                   (name, result.fail_reason, result.output))
1432
    if not self._InstancePidAlive(name)[2]:
1433
      raise errors.HypervisorError("Failed to start instance %s" % name)
1434

    
1435
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1436
    """Execute a KVM cmd, after completing it with some last minute data.
1437

1438
    @type incoming: tuple of strings
1439
    @param incoming: (target_host_ip, port)
1440
    @type kvmhelp: string
1441
    @param kvmhelp: output of kvm --help
1442

1443
    """
1444
    # Small _ExecuteKVMRuntime hv parameters programming howto:
1445
    #  - conf_hvp contains the parameters as configured on ganeti. they might
1446
    #    have changed since the instance started; only use them if the change
1447
    #    won't affect the inside of the instance (which hasn't been rebooted).
1448
    #  - up_hvp contains the parameters as they were when the instance was
1449
    #    started, plus any new parameter which has been added between ganeti
1450
    #    versions: it is paramount that those default to a value which won't
1451
    #    affect the inside of the instance as well.
1452
    conf_hvp = instance.hvparams
1453
    name = instance.name
1454
    self._CheckDown(name)
1455

    
1456
    temp_files = []
1457

    
1458
    kvm_cmd, kvm_nics, up_hvp = kvm_runtime
1459
    up_hvp = objects.FillDict(conf_hvp, up_hvp)
1460

    
1461
    _, v_major, v_min, _ = self._ParseKVMVersion(kvmhelp)
1462

    
1463
    # We know it's safe to run as a different user upon migration, so we'll use
1464
    # the latest conf, from conf_hvp.
1465
    security_model = conf_hvp[constants.HV_SECURITY_MODEL]
1466
    if security_model == constants.HT_SM_USER:
1467
      kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
1468

    
1469
    keymap = conf_hvp[constants.HV_KEYMAP]
1470
    if keymap:
1471
      keymap_path = self._InstanceKeymapFile(name)
1472
      # If a keymap file is specified, KVM won't use its internal defaults. By
1473
      # first including the "en-us" layout, an error on loading the actual
1474
      # layout (e.g. because it can't be found) won't lead to a non-functional
1475
      # keyboard. A keyboard with incorrect keys is still better than none.
1476
      utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
1477
      kvm_cmd.extend(["-k", keymap_path])
1478

    
1479
    # We have reasons to believe changing something like the nic driver/type
1480
    # upon migration won't exactly fly with the instance kernel, so for nic
1481
    # related parameters we'll use up_hvp
1482
    tapfds = []
1483
    taps = []
1484
    if not kvm_nics:
1485
      kvm_cmd.extend(["-net", "none"])
1486
    else:
1487
      vnet_hdr = False
1488
      tap_extra = ""
1489
      nic_type = up_hvp[constants.HV_NIC_TYPE]
1490
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
1491
        # From version 0.12.0, kvm uses a new sintax for network configuration.
1492
        if (v_major, v_min) >= (0, 12):
1493
          nic_model = "virtio-net-pci"
1494
          vnet_hdr = True
1495
        else:
1496
          nic_model = "virtio"
1497

    
1498
        if up_hvp[constants.HV_VHOST_NET]:
1499
          # check for vhost_net support
1500
          if self._VHOST_RE.search(kvmhelp):
1501
            tap_extra = ",vhost=on"
1502
          else:
1503
            raise errors.HypervisorError("vhost_net is configured"
1504
                                         " but it is not available")
1505
      else:
1506
        nic_model = nic_type
1507

    
1508
      for nic_seq, nic in enumerate(kvm_nics):
1509
        tapname, tapfd = _OpenTap(vnet_hdr)
1510
        tapfds.append(tapfd)
1511
        taps.append(tapname)
1512
        if self._NETDEV_RE.search(kvmhelp):
1513
          nic_val = "%s,mac=%s,netdev=netdev%s" % (nic_model, nic.mac, nic_seq)
1514
          tap_val = "type=tap,id=netdev%s,fd=%d%s" % (nic_seq, tapfd, tap_extra)
1515
          kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
1516
        else:
1517
          nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq,
1518
                                                         nic.mac, nic_model)
1519
          tap_val = "tap,vlan=%s,fd=%d" % (nic_seq, tapfd)
1520
          kvm_cmd.extend(["-net", tap_val, "-net", nic_val])
1521

    
1522
    if incoming:
1523
      target, port = incoming
1524
      kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])
1525

    
1526
    # Changing the vnc password doesn't bother the guest that much. At most it
1527
    # will surprise people who connect to it. Whether positively or negatively
1528
    # it's debatable.
1529
    vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
1530
    vnc_pwd = None
1531
    if vnc_pwd_file:
1532
      try:
1533
        vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
1534
      except EnvironmentError, err:
1535
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
1536
                                     % (vnc_pwd_file, err))
1537

    
1538
    if conf_hvp[constants.HV_KVM_USE_CHROOT]:
1539
      utils.EnsureDirs([(self._InstanceChrootDir(name),
1540
                         constants.SECURE_DIR_MODE)])
1541

    
1542
    # Automatically enable QMP if version is >= 0.14
1543
    if self._QMP_RE.search(kvmhelp):
1544
      logging.debug("Enabling QMP")
1545
      kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
1546
                      self._InstanceQmpMonitor(instance.name)])
1547

    
1548
    # Configure the network now for starting instances and bridged interfaces,
1549
    # during FinalizeMigration for incoming instances' routed interfaces
1550
    for nic_seq, nic in enumerate(kvm_nics):
1551
      if (incoming and
1552
          nic.nicparams[constants.NIC_MODE] != constants.NIC_MODE_BRIDGED):
1553
        continue
1554
      self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
1555

    
1556
    # CPU affinity requires kvm to start paused, so we set this flag if the
1557
    # instance is not already paused and if we are not going to accept a
1558
    # migrating instance. In the latter case, pausing is not needed.
1559
    start_kvm_paused = not (_KVM_START_PAUSED_FLAG in kvm_cmd) and not incoming
1560
    if start_kvm_paused:
1561
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1562

    
1563
    # Note: CPU pinning is using up_hvp since changes take effect
1564
    # during instance startup anyway, and to avoid problems when soft
1565
    # rebooting the instance.
1566
    cpu_pinning = False
1567
    if up_hvp.get(constants.HV_CPU_MASK, None):
1568
      cpu_pinning = True
1569

    
1570
    if security_model == constants.HT_SM_POOL:
1571
      ss = ssconf.SimpleStore()
1572
      uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
1573
      all_uids = set(uidpool.ExpandUidPool(uid_pool))
1574
      uid = uidpool.RequestUnusedUid(all_uids)
1575
      try:
1576
        username = pwd.getpwuid(uid.GetUid()).pw_name
1577
        kvm_cmd.extend(["-runas", username])
1578
        self._RunKVMCmd(name, kvm_cmd, tapfds)
1579
      except:
1580
        uidpool.ReleaseUid(uid)
1581
        raise
1582
      else:
1583
        uid.Unlock()
1584
        utils.WriteFile(self._InstanceUidFile(name), data=uid.AsStr())
1585
    else:
1586
      self._RunKVMCmd(name, kvm_cmd, tapfds)
1587

    
1588
    utils.EnsureDirs([(self._InstanceNICDir(instance.name),
1589
                     constants.RUN_DIRS_MODE)])
1590
    for nic_seq, tap in enumerate(taps):
1591
      utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
1592
                      data=tap)
1593

    
1594
    if vnc_pwd:
1595
      change_cmd = "change vnc password %s" % vnc_pwd
1596
      self._CallMonitorCommand(instance.name, change_cmd)
1597

    
1598
    # Setting SPICE password. We are not vulnerable to malicious passwordless
1599
    # connection attempts because SPICE by default does not allow connections
1600
    # if neither a password nor the "disable_ticketing" options are specified.
1601
    # As soon as we send the password via QMP, that password is a valid ticket
1602
    # for connection.
1603
    spice_password_file = conf_hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]
1604
    if spice_password_file:
1605
      spice_pwd = ""
1606
      try:
1607
        spice_pwd = utils.ReadOneLineFile(spice_password_file, strict=True)
1608
      except EnvironmentError, err:
1609
        raise errors.HypervisorError("Failed to open SPICE password file %s: %s"
1610
                                     % (spice_password_file, err))
1611

    
1612
      qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
1613
      qmp.connect()
1614
      arguments = {
1615
          "protocol": "spice",
1616
          "password": spice_pwd,
1617
      }
1618
      qmp.Execute("set_password", arguments)
1619

    
1620
    for filename in temp_files:
1621
      utils.RemoveFile(filename)
1622

    
1623
    # If requested, set CPU affinity and resume instance execution
1624
    if cpu_pinning:
1625
      self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK])
1626

    
1627
    start_memory = self._InstanceStartupMemory(instance)
1628
    if start_memory < instance.beparams[constants.BE_MAXMEM]:
1629
      self.BalloonInstanceMemory(instance, start_memory)
1630

    
1631
    if start_kvm_paused:
1632
      # To control CPU pinning, ballooning, and vnc/spice passwords
1633
      # the VM was started in a frozen state. If freezing was not
1634
      # explicitly requested resume the vm status.
1635
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1636

    
1637
  def StartInstance(self, instance, block_devices, startup_paused):
1638
    """Start an instance.
1639

1640
    """
1641
    self._CheckDown(instance.name)
1642
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1643
    kvmhelp = self._GetKVMHelpOutput(kvmpath)
1644
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1645
                                           startup_paused, kvmhelp)
1646
    self._SaveKVMRuntime(instance, kvm_runtime)
1647
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1648

    
1649
  def _CallMonitorCommand(self, instance_name, command):
1650
    """Invoke a command on the instance monitor.
1651

1652
    """
1653
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1654
             (utils.ShellQuote(command),
1655
              constants.SOCAT_PATH,
1656
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1657
    result = utils.RunCmd(socat)
1658
    if result.failed:
1659
      msg = ("Failed to send command '%s' to instance %s."
1660
             " output: %s, error: %s, fail_reason: %s" %
1661
             (command, instance_name,
1662
              result.stdout, result.stderr, result.fail_reason))
1663
      raise errors.HypervisorError(msg)
1664

    
1665
    return result
1666

    
1667
  @classmethod
1668
  def _ParseKVMVersion(cls, text):
1669
    """Parse the KVM version from the --help output.
1670

1671
    @type text: string
1672
    @param text: output of kvm --help
1673
    @return: (version, v_maj, v_min, v_rev)
1674
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1675

1676
    """
1677
    match = cls._VERSION_RE.search(text.splitlines()[0])
1678
    if not match:
1679
      raise errors.HypervisorError("Unable to get KVM version")
1680

    
1681
    v_all = match.group(0)
1682
    v_maj = int(match.group(1))
1683
    v_min = int(match.group(2))
1684
    if match.group(4):
1685
      v_rev = int(match.group(4))
1686
    else:
1687
      v_rev = 0
1688
    return (v_all, v_maj, v_min, v_rev)
1689

    
1690
  @classmethod
1691
  def _GetKVMHelpOutput(cls, kvm_path):
1692
    """Return the KVM help output.
1693

1694
    @return: output of kvm --help
1695
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
1696

1697
    """
1698
    result = utils.RunCmd([kvm_path, "--help"])
1699
    if result.failed:
1700
      raise errors.HypervisorError("Unable to get KVM help output")
1701
    return result.output
1702

    
1703
  @classmethod
1704
  def _GetKVMVersion(cls, kvm_path):
1705
    """Return the installed KVM version.
1706

1707
    @return: (version, v_maj, v_min, v_rev)
1708
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1709

1710
    """
1711
    return cls._ParseKVMVersion(cls._GetKVMHelpOutput(kvm_path))
1712

    
1713
  def StopInstance(self, instance, force=False, retry=False, name=None):
1714
    """Stop an instance.
1715

1716
    """
1717
    if name is not None and not force:
1718
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
1719
    if name is None:
1720
      name = instance.name
1721
      acpi = instance.hvparams[constants.HV_ACPI]
1722
    else:
1723
      acpi = False
1724
    _, pid, alive = self._InstancePidAlive(name)
1725
    if pid > 0 and alive:
1726
      if force or not acpi:
1727
        utils.KillProcess(pid)
1728
      else:
1729
        self._CallMonitorCommand(name, "system_powerdown")
1730

    
1731
  @classmethod
1732
  def _GetDefaultMachineVersion(cls, kvm_path):
1733
    """Return the default hardware revision (e.g. pc-1.1)
1734

1735
    """
1736
    result = utils.RunCmd([kvm_path, "-M", "?"])
1737
    if result.failed:
1738
      raise errors.HypervisorError("Unable to get default hardware revision")
1739
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(result.output)
1740
    if match:
1741
      return match.group(1)
1742
    else:
1743
      return "pc"
1744

    
1745
  def CleanupInstance(self, instance_name):
1746
    """Cleanup after a stopped instance
1747

1748
    """
1749
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1750
    if pid > 0 and alive:
1751
      raise errors.HypervisorError("Cannot cleanup a live instance")
1752
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1753

    
1754
  def RebootInstance(self, instance):
1755
    """Reboot an instance.
1756

1757
    """
1758
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
1759
    # socket the instance will stop, but now power up again. So we'll resort
1760
    # to shutdown and restart.
1761
    _, _, alive = self._InstancePidAlive(instance.name)
1762
    if not alive:
1763
      raise errors.HypervisorError("Failed to reboot instance %s:"
1764
                                   " not running" % instance.name)
1765
    # StopInstance will delete the saved KVM runtime so:
1766
    # ...first load it...
1767
    kvm_runtime = self._LoadKVMRuntime(instance)
1768
    # ...now we can safely call StopInstance...
1769
    if not self.StopInstance(instance):
1770
      self.StopInstance(instance, force=True)
1771
    # ...and finally we can save it again, and execute it...
1772
    self._SaveKVMRuntime(instance, kvm_runtime)
1773
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1774
    kvmhelp = self._GetKVMHelpOutput(kvmpath)
1775
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1776

    
1777
  def MigrationInfo(self, instance):
1778
    """Get instance information to perform a migration.
1779

1780
    @type instance: L{objects.Instance}
1781
    @param instance: instance to be migrated
1782
    @rtype: string
1783
    @return: content of the KVM runtime file
1784

1785
    """
1786
    return self._ReadKVMRuntime(instance.name)
1787

    
1788
  def AcceptInstance(self, instance, info, target):
1789
    """Prepare to accept an instance.
1790

1791
    @type instance: L{objects.Instance}
1792
    @param instance: instance to be accepted
1793
    @type info: string
1794
    @param info: content of the KVM runtime file on the source node
1795
    @type target: string
1796
    @param target: target host (usually ip), on this node
1797

1798
    """
1799
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1800
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1801
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1802
    kvmhelp = self._GetKVMHelpOutput(kvmpath)
1803
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
1804
                            incoming=incoming_address)
1805

    
1806
  def FinalizeMigrationDst(self, instance, info, success):
1807
    """Finalize the instance migration on the target node.
1808

1809
    Stop the incoming mode KVM.
1810

1811
    @type instance: L{objects.Instance}
1812
    @param instance: instance whose migration is being finalized
1813

1814
    """
1815
    if success:
1816
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1817
      kvm_nics = kvm_runtime[1]
1818

    
1819
      for nic_seq, nic in enumerate(kvm_nics):
1820
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1821
          # Bridged interfaces have already been configured
1822
          continue
1823
        try:
1824
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
1825
        except EnvironmentError, err:
1826
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
1827
                          instance.name, nic_seq, str(err))
1828
          continue
1829
        try:
1830
          self._ConfigureNIC(instance, nic_seq, nic, tap)
1831
        except errors.HypervisorError, err:
1832
          logging.warning(str(err))
1833

    
1834
      self._WriteKVMRuntime(instance.name, info)
1835
    else:
1836
      self.StopInstance(instance, force=True)
1837

    
1838
  def MigrateInstance(self, instance, target, live):
1839
    """Migrate an instance to a target node.
1840

1841
    The migration will not be attempted if the instance is not
1842
    currently running.
1843

1844
    @type instance: L{objects.Instance}
1845
    @param instance: the instance to be migrated
1846
    @type target: string
1847
    @param target: ip address of the target node
1848
    @type live: boolean
1849
    @param live: perform a live migration
1850

1851
    """
1852
    instance_name = instance.name
1853
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
1854
    _, _, alive = self._InstancePidAlive(instance_name)
1855
    if not alive:
1856
      raise errors.HypervisorError("Instance not running, cannot migrate")
1857

    
1858
    if not live:
1859
      self._CallMonitorCommand(instance_name, "stop")
1860

    
1861
    migrate_command = ("migrate_set_speed %dm" %
1862
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1863
    self._CallMonitorCommand(instance_name, migrate_command)
1864

    
1865
    migrate_command = ("migrate_set_downtime %dms" %
1866
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
1867
    self._CallMonitorCommand(instance_name, migrate_command)
1868

    
1869
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
1870
    self._CallMonitorCommand(instance_name, migrate_command)
1871

    
1872
  def FinalizeMigrationSource(self, instance, success, live):
1873
    """Finalize the instance migration on the source node.
1874

1875
    @type instance: L{objects.Instance}
1876
    @param instance: the instance that was migrated
1877
    @type success: bool
1878
    @param success: whether the migration succeeded or not
1879
    @type live: bool
1880
    @param live: whether the user requested a live migration or not
1881

1882
    """
1883
    if success:
1884
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
1885
      utils.KillProcess(pid)
1886
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
1887
    elif live:
1888
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1889

    
1890
  def GetMigrationStatus(self, instance):
1891
    """Get the migration status
1892

1893
    @type instance: L{objects.Instance}
1894
    @param instance: the instance that is being migrated
1895
    @rtype: L{objects.MigrationStatus}
1896
    @return: the status of the current migration (one of
1897
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
1898
             progress info that can be retrieved from the hypervisor
1899

1900
    """
1901
    info_command = "info migrate"
1902
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
1903
      result = self._CallMonitorCommand(instance.name, info_command)
1904
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
1905
      if not match:
1906
        if not result.stdout:
1907
          logging.info("KVM: empty 'info migrate' result")
1908
        else:
1909
          logging.warning("KVM: unknown 'info migrate' result: %s",
1910
                          result.stdout)
1911
      else:
1912
        status = match.group(1)
1913
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
1914
          migration_status = objects.MigrationStatus(status=status)
1915
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
1916
          if match:
1917
            migration_status.transferred_ram = match.group("transferred")
1918
            migration_status.total_ram = match.group("total")
1919

    
1920
          return migration_status
1921

    
1922
        logging.warning("KVM: unknown migration status '%s'", status)
1923

    
1924
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1925

    
1926
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
1927

    
1928
  def BalloonInstanceMemory(self, instance, mem):
1929
    """Balloon an instance memory to a certain value.
1930

1931
    @type instance: L{objects.Instance}
1932
    @param instance: instance to be accepted
1933
    @type mem: int
1934
    @param mem: actual memory size to use for instance runtime
1935

1936
    """
1937
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
1938

    
1939
  def GetNodeInfo(self):
1940
    """Return information about the node.
1941

1942
    @return: a dict with the following keys (values in MiB):
1943
          - memory_total: the total memory size on the node
1944
          - memory_free: the available memory on the node for instances
1945
          - memory_dom0: the memory used by the node itself, if available
1946
          - hv_version: the hypervisor version in the form (major, minor,
1947
                        revision)
1948

1949
    """
1950
    result = self.GetLinuxNodeInfo()
1951
    # FIXME: this is the global kvm version, but the actual version can be
1952
    # customized as an hv parameter. we should use the nodegroup's default kvm
1953
    # path parameter here.
1954
    _, v_major, v_min, v_rev = self._GetKVMVersion(constants.KVM_PATH)
1955
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
1956
    return result
1957

    
1958
  @classmethod
1959
  def GetInstanceConsole(cls, instance, hvparams, beparams):
1960
    """Return a command for connecting to the console of an instance.
1961

1962
    """
1963
    if hvparams[constants.HV_SERIAL_CONSOLE]:
1964
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
1965
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
1966
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
1967
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
1968
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
1969
      return objects.InstanceConsole(instance=instance.name,
1970
                                     kind=constants.CONS_SSH,
1971
                                     host=instance.primary_node,
1972
                                     user=constants.SSH_CONSOLE_USER,
1973
                                     command=cmd)
1974

    
1975
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
1976
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
1977
      display = instance.network_port - constants.VNC_BASE_PORT
1978
      return objects.InstanceConsole(instance=instance.name,
1979
                                     kind=constants.CONS_VNC,
1980
                                     host=vnc_bind_address,
1981
                                     port=instance.network_port,
1982
                                     display=display)
1983

    
1984
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
1985
    if spice_bind:
1986
      return objects.InstanceConsole(instance=instance.name,
1987
                                     kind=constants.CONS_SPICE,
1988
                                     host=spice_bind,
1989
                                     port=instance.network_port)
1990

    
1991
    return objects.InstanceConsole(instance=instance.name,
1992
                                   kind=constants.CONS_MESSAGE,
1993
                                   message=("No serial shell for instance %s" %
1994
                                            instance.name))
1995

    
1996
  def Verify(self):
1997
    """Verify the hypervisor.
1998

1999
    Check that the binary exists.
2000

2001
    """
2002
    # FIXME: this is the global kvm version, but the actual version can be
2003
    # customized as an hv parameter. we should use the nodegroup's default kvm
2004
    # path parameter here.
2005
    if not os.path.exists(constants.KVM_PATH):
2006
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
2007
    if not os.path.exists(constants.SOCAT_PATH):
2008
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
2009

    
2010
  @classmethod
2011
  def CheckParameterSyntax(cls, hvparams):
2012
    """Check the given parameters for validity.
2013

2014
    @type hvparams:  dict
2015
    @param hvparams: dictionary with parameter names/value
2016
    @raise errors.HypervisorError: when a parameter is not valid
2017

2018
    """
2019
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2020

    
2021
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
2022
    if kernel_path:
2023
      if not hvparams[constants.HV_ROOT_PATH]:
2024
        raise errors.HypervisorError("Need a root partition for the instance,"
2025
                                     " if a kernel is defined")
2026

    
2027
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
2028
        not hvparams[constants.HV_VNC_X509]):
2029
      raise errors.HypervisorError("%s must be defined, if %s is" %
2030
                                   (constants.HV_VNC_X509,
2031
                                    constants.HV_VNC_X509_VERIFY))
2032

    
2033
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2034
      serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2035
      valid_speeds = constants.VALID_SERIAL_SPEEDS
2036
      if not serial_speed or serial_speed not in valid_speeds:
2037
        raise errors.HypervisorError("Invalid serial console speed, must be"
2038
                                     " one of: %s" %
2039
                                     utils.CommaJoin(valid_speeds))
2040

    
2041
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2042
    if (boot_order == constants.HT_BO_CDROM and
2043
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2044
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2045
                                   " ISO path")
2046

    
2047
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2048
    if security_model == constants.HT_SM_USER:
2049
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
2050
        raise errors.HypervisorError("A security domain (user to run kvm as)"
2051
                                     " must be specified")
2052
    elif (security_model == constants.HT_SM_NONE or
2053
          security_model == constants.HT_SM_POOL):
2054
      if hvparams[constants.HV_SECURITY_DOMAIN]:
2055
        raise errors.HypervisorError("Cannot have a security domain when the"
2056
                                     " security model is 'none' or 'pool'")
2057

    
2058
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2059
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2060
    if spice_bind:
2061
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2062
        # if an IP version is specified, the spice_bind parameter must be an
2063
        # IP of that family
2064
        if (netutils.IP4Address.IsValid(spice_bind) and
2065
            spice_ip_version != constants.IP4_VERSION):
2066
          raise errors.HypervisorError("spice: got an IPv4 address (%s), but"
2067
                                       " the specified IP version is %s" %
2068
                                       (spice_bind, spice_ip_version))
2069

    
2070
        if (netutils.IP6Address.IsValid(spice_bind) and
2071
            spice_ip_version != constants.IP6_VERSION):
2072
          raise errors.HypervisorError("spice: got an IPv6 address (%s), but"
2073
                                       " the specified IP version is %s" %
2074
                                       (spice_bind, spice_ip_version))
2075
    else:
2076
      # All the other SPICE parameters depend on spice_bind being set. Raise an
2077
      # error if any of them is set without it.
2078
      for param in _SPICE_ADDITIONAL_PARAMS:
2079
        if hvparams[param]:
2080
          raise errors.HypervisorError("spice: %s requires %s to be set" %
2081
                                       (param, constants.HV_KVM_SPICE_BIND))
2082

    
2083
  @classmethod
2084
  def ValidateParameters(cls, hvparams):
2085
    """Check the given parameters for validity.
2086

2087
    @type hvparams:  dict
2088
    @param hvparams: dictionary with parameter names/value
2089
    @raise errors.HypervisorError: when a parameter is not valid
2090

2091
    """
2092
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2093

    
2094
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2095
    if security_model == constants.HT_SM_USER:
2096
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2097
      try:
2098
        pwd.getpwnam(username)
2099
      except KeyError:
2100
        raise errors.HypervisorError("Unknown security domain user %s"
2101
                                     % username)
2102

    
2103
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2104
    if spice_bind:
2105
      # only one of VNC and SPICE can be used currently.
2106
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2107
        raise errors.HypervisorError("both SPICE and VNC are configured, but"
2108
                                     " only one of them can be used at a"
2109
                                     " given time.")
2110

    
2111
      # check that KVM supports SPICE
2112
      kvmhelp = cls._GetKVMHelpOutput(hvparams[constants.HV_KVM_PATH])
2113
      if not cls._SPICE_RE.search(kvmhelp):
2114
        raise errors.HypervisorError("spice is configured, but it is not"
2115
                                     " supported according to kvm --help")
2116

    
2117
      # if spice_bind is not an IP address, it must be a valid interface
2118
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind)
2119
                       or netutils.IP6Address.IsValid(spice_bind))
2120
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2121
        raise errors.HypervisorError("spice: the %s parameter must be either"
2122
                                     " a valid IP address or interface name" %
2123
                                     constants.HV_KVM_SPICE_BIND)
2124

    
2125
  @classmethod
2126
  def PowercycleNode(cls):
2127
    """KVM powercycle, just a wrapper over Linux powercycle.
2128

2129
    """
2130
    cls.LinuxPowercycle()