Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ b73f1c59

History | View | Annotate | Download (76.6 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
    constants.HV_VGA: hv_base.NO_CHECK,
541
    constants.HV_KVM_EXTRA: hv_base.NO_CHECK,
542
    constants.HV_KVM_MACHINE_VERSION: hv_base.NO_CHECK,
543
    }
544

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

    
552
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
553
  _MIGRATION_INFO_RETRY_DELAY = 2
554

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
645
    return (instance, memory, vcpus)
646

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

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

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

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

    
666
    return (pidfile, pid, alive)
667

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
933
    return result
934

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1068
    self.ValidateParameters(hvp)
1069

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1273
        spice_address = addresses[spice_ip_version][0]
1274

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1369
    return (kvm_cmd, kvm_nics, hvparams)
1370

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1455
    temp_files = []
1456

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1639
    """
1640
    self._CheckDown(instance.name)
1641
    kvmhelp = self._GetKVMHelpOutput(constants.KVM_PATH)
1642
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1643
                                           startup_paused, kvmhelp)
1644
    self._SaveKVMRuntime(instance, kvm_runtime)
1645
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1646

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

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

    
1663
    return result
1664

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

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

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

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

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

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

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

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

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

1708
    """
1709
    return cls._ParseKVMVersion(cls._GetKVMHelpOutput(kvm_path))
1710

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

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

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

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

    
1743
  def CleanupInstance(self, instance_name):
1744
    """Cleanup after a stopped instance
1745

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

    
1752
  def RebootInstance(self, instance):
1753
    """Reboot an instance.
1754

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

    
1774
  def MigrationInfo(self, instance):
1775
    """Get instance information to perform a migration.
1776

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

1782
    """
1783
    return self._ReadKVMRuntime(instance.name)
1784

    
1785
  def AcceptInstance(self, instance, info, target):
1786
    """Prepare to accept an instance.
1787

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

1795
    """
1796
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1797
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1798
    kvmhelp = self._GetKVMHelpOutput(constants.KVM_PATH)
1799
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
1800
                            incoming=incoming_address)
1801

    
1802
  def FinalizeMigrationDst(self, instance, info, success):
1803
    """Finalize the instance migration on the target node.
1804

1805
    Stop the incoming mode KVM.
1806

1807
    @type instance: L{objects.Instance}
1808
    @param instance: instance whose migration is being finalized
1809

1810
    """
1811
    if success:
1812
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1813
      kvm_nics = kvm_runtime[1]
1814

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

    
1830
      self._WriteKVMRuntime(instance.name, info)
1831
    else:
1832
      self.StopInstance(instance, force=True)
1833

    
1834
  def MigrateInstance(self, instance, target, live):
1835
    """Migrate an instance to a target node.
1836

1837
    The migration will not be attempted if the instance is not
1838
    currently running.
1839

1840
    @type instance: L{objects.Instance}
1841
    @param instance: the instance to be migrated
1842
    @type target: string
1843
    @param target: ip address of the target node
1844
    @type live: boolean
1845
    @param live: perform a live migration
1846

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

    
1854
    if not live:
1855
      self._CallMonitorCommand(instance_name, "stop")
1856

    
1857
    migrate_command = ("migrate_set_speed %dm" %
1858
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1859
    self._CallMonitorCommand(instance_name, migrate_command)
1860

    
1861
    migrate_command = ("migrate_set_downtime %dms" %
1862
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
1863
    self._CallMonitorCommand(instance_name, migrate_command)
1864

    
1865
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
1866
    self._CallMonitorCommand(instance_name, migrate_command)
1867

    
1868
  def FinalizeMigrationSource(self, instance, success, live):
1869
    """Finalize the instance migration on the source node.
1870

1871
    @type instance: L{objects.Instance}
1872
    @param instance: the instance that was migrated
1873
    @type success: bool
1874
    @param success: whether the migration succeeded or not
1875
    @type live: bool
1876
    @param live: whether the user requested a live migration or not
1877

1878
    """
1879
    if success:
1880
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
1881
      utils.KillProcess(pid)
1882
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
1883
    elif live:
1884
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1885

    
1886
  def GetMigrationStatus(self, instance):
1887
    """Get the migration status
1888

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

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

    
1916
          return migration_status
1917

    
1918
        logging.warning("KVM: unknown migration status '%s'", status)
1919

    
1920
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1921

    
1922
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
1923

    
1924
  def BalloonInstanceMemory(self, instance, mem):
1925
    """Balloon an instance memory to a certain value.
1926

1927
    @type instance: L{objects.Instance}
1928
    @param instance: instance to be accepted
1929
    @type mem: int
1930
    @param mem: actual memory size to use for instance runtime
1931

1932
    """
1933
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
1934

    
1935
  def GetNodeInfo(self):
1936
    """Return information about the node.
1937

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

1945
    """
1946
    result = self.GetLinuxNodeInfo()
1947
    _, v_major, v_min, v_rev = self._GetKVMVersion(constants.KVM_PATH)
1948
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
1949
    return result
1950

    
1951
  @classmethod
1952
  def GetInstanceConsole(cls, instance, hvparams, beparams):
1953
    """Return a command for connecting to the console of an instance.
1954

1955
    """
1956
    if hvparams[constants.HV_SERIAL_CONSOLE]:
1957
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
1958
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
1959
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
1960
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
1961
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
1962
      return objects.InstanceConsole(instance=instance.name,
1963
                                     kind=constants.CONS_SSH,
1964
                                     host=instance.primary_node,
1965
                                     user=constants.SSH_CONSOLE_USER,
1966
                                     command=cmd)
1967

    
1968
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
1969
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
1970
      display = instance.network_port - constants.VNC_BASE_PORT
1971
      return objects.InstanceConsole(instance=instance.name,
1972
                                     kind=constants.CONS_VNC,
1973
                                     host=vnc_bind_address,
1974
                                     port=instance.network_port,
1975
                                     display=display)
1976

    
1977
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
1978
    if spice_bind:
1979
      return objects.InstanceConsole(instance=instance.name,
1980
                                     kind=constants.CONS_SPICE,
1981
                                     host=spice_bind,
1982
                                     port=instance.network_port)
1983

    
1984
    return objects.InstanceConsole(instance=instance.name,
1985
                                   kind=constants.CONS_MESSAGE,
1986
                                   message=("No serial shell for instance %s" %
1987
                                            instance.name))
1988

    
1989
  def Verify(self):
1990
    """Verify the hypervisor.
1991

1992
    Check that the binary exists.
1993

1994
    """
1995
    if not os.path.exists(constants.KVM_PATH):
1996
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
1997
    if not os.path.exists(constants.SOCAT_PATH):
1998
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
1999

    
2000
  @classmethod
2001
  def CheckParameterSyntax(cls, hvparams):
2002
    """Check the given parameters for validity.
2003

2004
    @type hvparams:  dict
2005
    @param hvparams: dictionary with parameter names/value
2006
    @raise errors.HypervisorError: when a parameter is not valid
2007

2008
    """
2009
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2010

    
2011
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
2012
    if kernel_path:
2013
      if not hvparams[constants.HV_ROOT_PATH]:
2014
        raise errors.HypervisorError("Need a root partition for the instance,"
2015
                                     " if a kernel is defined")
2016

    
2017
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
2018
        not hvparams[constants.HV_VNC_X509]):
2019
      raise errors.HypervisorError("%s must be defined, if %s is" %
2020
                                   (constants.HV_VNC_X509,
2021
                                    constants.HV_VNC_X509_VERIFY))
2022

    
2023
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2024
      serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2025
      valid_speeds = constants.VALID_SERIAL_SPEEDS
2026
      if not serial_speed or serial_speed not in valid_speeds:
2027
        raise errors.HypervisorError("Invalid serial console speed, must be"
2028
                                     " one of: %s" %
2029
                                     utils.CommaJoin(valid_speeds))
2030

    
2031
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2032
    if (boot_order == constants.HT_BO_CDROM and
2033
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2034
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2035
                                   " ISO path")
2036

    
2037
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2038
    if security_model == constants.HT_SM_USER:
2039
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
2040
        raise errors.HypervisorError("A security domain (user to run kvm as)"
2041
                                     " must be specified")
2042
    elif (security_model == constants.HT_SM_NONE or
2043
          security_model == constants.HT_SM_POOL):
2044
      if hvparams[constants.HV_SECURITY_DOMAIN]:
2045
        raise errors.HypervisorError("Cannot have a security domain when the"
2046
                                     " security model is 'none' or 'pool'")
2047

    
2048
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2049
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2050
    if spice_bind:
2051
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2052
        # if an IP version is specified, the spice_bind parameter must be an
2053
        # IP of that family
2054
        if (netutils.IP4Address.IsValid(spice_bind) and
2055
            spice_ip_version != constants.IP4_VERSION):
2056
          raise errors.HypervisorError("spice: got an IPv4 address (%s), but"
2057
                                       " the specified IP version is %s" %
2058
                                       (spice_bind, spice_ip_version))
2059

    
2060
        if (netutils.IP6Address.IsValid(spice_bind) and
2061
            spice_ip_version != constants.IP6_VERSION):
2062
          raise errors.HypervisorError("spice: got an IPv6 address (%s), but"
2063
                                       " the specified IP version is %s" %
2064
                                       (spice_bind, spice_ip_version))
2065
    else:
2066
      # All the other SPICE parameters depend on spice_bind being set. Raise an
2067
      # error if any of them is set without it.
2068
      for param in _SPICE_ADDITIONAL_PARAMS:
2069
        if hvparams[param]:
2070
          raise errors.HypervisorError("spice: %s requires %s to be set" %
2071
                                       (param, constants.HV_KVM_SPICE_BIND))
2072

    
2073
  @classmethod
2074
  def ValidateParameters(cls, hvparams):
2075
    """Check the given parameters for validity.
2076

2077
    @type hvparams:  dict
2078
    @param hvparams: dictionary with parameter names/value
2079
    @raise errors.HypervisorError: when a parameter is not valid
2080

2081
    """
2082
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2083

    
2084
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2085
    if security_model == constants.HT_SM_USER:
2086
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2087
      try:
2088
        pwd.getpwnam(username)
2089
      except KeyError:
2090
        raise errors.HypervisorError("Unknown security domain user %s"
2091
                                     % username)
2092

    
2093
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2094
    if spice_bind:
2095
      # only one of VNC and SPICE can be used currently.
2096
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2097
        raise errors.HypervisorError("both SPICE and VNC are configured, but"
2098
                                     " only one of them can be used at a"
2099
                                     " given time.")
2100

    
2101
      # check that KVM supports SPICE
2102
      kvmhelp = cls._GetKVMHelpOutput(constants.KVM_PATH)
2103
      if not cls._SPICE_RE.search(kvmhelp):
2104
        raise errors.HypervisorError("spice is configured, but it is not"
2105
                                     " supported according to kvm --help")
2106

    
2107
      # if spice_bind is not an IP address, it must be a valid interface
2108
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind)
2109
                       or netutils.IP6Address.IsValid(spice_bind))
2110
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2111
        raise errors.HypervisorError("spice: the %s parameter must be either"
2112
                                     " a valid IP address or interface name" %
2113
                                     constants.HV_KVM_SPICE_BIND)
2114

    
2115
  @classmethod
2116
  def PowercycleNode(cls):
2117
    """KVM powercycle, just a wrapper over Linux powercycle.
2118

2119
    """
2120
    cls.LinuxPowercycle()