Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 0ad7f5d8

History | View | Annotate | Download (75.4 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
    }
539

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

    
547
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
548
  _MIGRATION_INFO_RETRY_DELAY = 2
549

    
550
  _VERSION_RE = re.compile(r"\b(\d+)\.(\d+)(\.(\d+))?\b")
551

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

    
556
  _DEFAULT_MACHINE_VERSION_RE = re.compile(r"(\S+).*\(default\)")
557

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

    
569
  ANCILLARY_FILES = [
570
    _KVM_NETWORK_SCRIPT,
571
    ]
572
  ANCILLARY_FILES_OPT = [
573
    _KVM_NETWORK_SCRIPT,
574
    ]
575

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

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

587
    """
588
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
589

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

594
    """
595
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
596

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

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

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

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

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

    
622
    instance = None
623
    memory = 0
624
    vcpus = 0
625

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

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

    
640
    return (instance, memory, vcpus)
641

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

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

650
    """
651
    pidfile = self._InstancePidFile(instance_name)
652
    pid = utils.ReadPidFile(pidfile)
653

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

    
661
    return (pidfile, pid, alive)
662

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

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

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

676
    """
677
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
678

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

683
    """
684
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
685

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

690
    """
691
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
692

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

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

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

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

709
    """
710
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
711

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

716
    """
717
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
718

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

724
    """
725
    return utils.PathJoin(cls._NICS_DIR, instance_name)
726

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

731
    """
732
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
733

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

738
    """
739
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
740

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

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

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

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

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

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

809
    """
810
    if instance.tags:
811
      tags = " ".join(instance.tags)
812
    else:
813
      tags = ""
814

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

    
825
    if nic.ip:
826
      env["IP"] = nic.ip
827

    
828
    if nic.nicparams[constants.NIC_LINK]:
829
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
830

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
928
    return result
929

    
930
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
931
    """Complete CPU pinning.
932

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

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

    
946
  def ListInstances(self):
947
    """Get the list of running instances.
948

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

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

    
959
  def GetInstanceInfo(self, instance_name):
960
    """Get instance properties.
961

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

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

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

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

    
987
    return (instance_name, pid, memory, vcpus, istat, times)
988

    
989
  def GetAllInstancesInfo(self):
990
    """Get properties of all instances.
991

992
    @return: list of tuples (name, id, memory, vcpus, stat, times)
993

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

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

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

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

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

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

    
1037
    kvm_cmd.extend(["-smp", ",".join(smp_list)])
1038

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

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

    
1057
    self.ValidateParameters(hvp)
1058

    
1059
    if startup_paused:
1060
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1061

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1188
    kvm_cmd.extend(["-usb"])
1189

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

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

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

    
1223
        vnc_arg = "%s%s" % (vnc_arg, vnc_append)
1224

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

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

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

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

    
1262
        spice_address = addresses[spice_ip_version][0]
1263

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

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

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

    
1286
      if spice_ip_version:
1287
        spice_arg = "%s,ipv%s" % (spice_arg, spice_ip_version)
1288

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

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

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

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

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

    
1324
    else:
1325
      kvm_cmd.extend(["-nographic"])
1326

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

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

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

    
1337
    # Save the current instance nics, but defer their expansion as parameters,
1338
    # as we'll need to generate executable temp files for them.
1339
    kvm_nics = instance.nics
1340
    hvparams = hvp
1341

    
1342
    return (kvm_cmd, kvm_nics, hvparams)
1343

    
1344
  def _WriteKVMRuntime(self, instance_name, data):
1345
    """Write an instance's KVM runtime
1346

1347
    """
1348
    try:
1349
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1350
                      data=data)
1351
    except EnvironmentError, err:
1352
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1353

    
1354
  def _ReadKVMRuntime(self, instance_name):
1355
    """Read an instance's KVM runtime
1356

1357
    """
1358
    try:
1359
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1360
    except EnvironmentError, err:
1361
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1362
    return file_content
1363

    
1364
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1365
    """Save an instance's KVM runtime
1366

1367
    """
1368
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
1369
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1370
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
1371
    self._WriteKVMRuntime(instance.name, serialized_form)
1372

    
1373
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1374
    """Load an instance's KVM runtime
1375

1376
    """
1377
    if not serialized_runtime:
1378
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1379
    loaded_runtime = serializer.Load(serialized_runtime)
1380
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
1381
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
1382
    return (kvm_cmd, kvm_nics, hvparams)
1383

    
1384
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1385
    """Run the KVM cmd and check for errors
1386

1387
    @type name: string
1388
    @param name: instance name
1389
    @type kvm_cmd: list of strings
1390
    @param kvm_cmd: runcmd input for kvm
1391
    @type tap_fds: list of int
1392
    @param tap_fds: fds of tap devices opened by Ganeti
1393

1394
    """
1395
    try:
1396
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1397
    finally:
1398
      for fd in tap_fds:
1399
        utils_wrapper.CloseFdNoError(fd)
1400

    
1401
    if result.failed:
1402
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1403
                                   (name, result.fail_reason, result.output))
1404
    if not self._InstancePidAlive(name)[2]:
1405
      raise errors.HypervisorError("Failed to start instance %s" % name)
1406

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

1410
    @type incoming: tuple of strings
1411
    @param incoming: (target_host_ip, port)
1412

1413
    """
1414
    # Small _ExecuteKVMRuntime hv parameters programming howto:
1415
    #  - conf_hvp contains the parameters as configured on ganeti. they might
1416
    #    have changed since the instance started; only use them if the change
1417
    #    won't affect the inside of the instance (which hasn't been rebooted).
1418
    #  - up_hvp contains the parameters as they were when the instance was
1419
    #    started, plus any new parameter which has been added between ganeti
1420
    #    versions: it is paramount that those default to a value which won't
1421
    #    affect the inside of the instance as well.
1422
    conf_hvp = instance.hvparams
1423
    name = instance.name
1424
    self._CheckDown(name)
1425

    
1426
    temp_files = []
1427

    
1428
    kvm_cmd, kvm_nics, up_hvp = kvm_runtime
1429
    up_hvp = objects.FillDict(conf_hvp, up_hvp)
1430

    
1431
    kvmhelp = self._GetKVMHelpOutput()
1432
    _, v_major, v_min, _ = self._ParseKVMVersion(kvmhelp)
1433

    
1434
    # We know it's safe to run as a different user upon migration, so we'll use
1435
    # the latest conf, from conf_hvp.
1436
    security_model = conf_hvp[constants.HV_SECURITY_MODEL]
1437
    if security_model == constants.HT_SM_USER:
1438
      kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
1439

    
1440
    keymap = conf_hvp[constants.HV_KEYMAP]
1441
    if keymap:
1442
      keymap_path = self._InstanceKeymapFile(name)
1443
      # If a keymap file is specified, KVM won't use its internal defaults. By
1444
      # first including the "en-us" layout, an error on loading the actual
1445
      # layout (e.g. because it can't be found) won't lead to a non-functional
1446
      # keyboard. A keyboard with incorrect keys is still better than none.
1447
      utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
1448
      kvm_cmd.extend(["-k", keymap_path])
1449

    
1450
    # We have reasons to believe changing something like the nic driver/type
1451
    # upon migration won't exactly fly with the instance kernel, so for nic
1452
    # related parameters we'll use up_hvp
1453
    tapfds = []
1454
    taps = []
1455
    if not kvm_nics:
1456
      kvm_cmd.extend(["-net", "none"])
1457
    else:
1458
      vnet_hdr = False
1459
      tap_extra = ""
1460
      nic_type = up_hvp[constants.HV_NIC_TYPE]
1461
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
1462
        # From version 0.12.0, kvm uses a new sintax for network configuration.
1463
        if (v_major, v_min) >= (0, 12):
1464
          nic_model = "virtio-net-pci"
1465
          vnet_hdr = True
1466
        else:
1467
          nic_model = "virtio"
1468

    
1469
        if up_hvp[constants.HV_VHOST_NET]:
1470
          # vhost_net is only available from version 0.13.0 or newer
1471
          if self._VHOST_RE.search(kvmhelp):
1472
            tap_extra = ",vhost=on"
1473
          else:
1474
            raise errors.HypervisorError("vhost_net is configured"
1475
                                         " but it is not available")
1476
      else:
1477
        nic_model = nic_type
1478

    
1479
      for nic_seq, nic in enumerate(kvm_nics):
1480
        tapname, tapfd = _OpenTap(vnet_hdr)
1481
        tapfds.append(tapfd)
1482
        taps.append(tapname)
1483
        if self._NETDEV_RE.search(kvmhelp):
1484
          nic_val = "%s,mac=%s,netdev=netdev%s" % (nic_model, nic.mac, nic_seq)
1485
          tap_val = "type=tap,id=netdev%s,fd=%d%s" % (nic_seq, tapfd, tap_extra)
1486
          kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
1487
        else:
1488
          nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq,
1489
                                                         nic.mac, nic_model)
1490
          tap_val = "tap,vlan=%s,fd=%d" % (nic_seq, tapfd)
1491
          kvm_cmd.extend(["-net", tap_val, "-net", nic_val])
1492

    
1493
    if incoming:
1494
      target, port = incoming
1495
      kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])
1496

    
1497
    # Changing the vnc password doesn't bother the guest that much. At most it
1498
    # will surprise people who connect to it. Whether positively or negatively
1499
    # it's debatable.
1500
    vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
1501
    vnc_pwd = None
1502
    if vnc_pwd_file:
1503
      try:
1504
        vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
1505
      except EnvironmentError, err:
1506
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
1507
                                     % (vnc_pwd_file, err))
1508

    
1509
    if conf_hvp[constants.HV_KVM_USE_CHROOT]:
1510
      utils.EnsureDirs([(self._InstanceChrootDir(name),
1511
                         constants.SECURE_DIR_MODE)])
1512

    
1513
    # Automatically enable QMP if version is >= 0.14
1514
    if self._QMP_RE.search(kvmhelp):
1515
      logging.debug("Enabling QMP")
1516
      kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
1517
                      self._InstanceQmpMonitor(instance.name)])
1518

    
1519
    # Configure the network now for starting instances and bridged interfaces,
1520
    # during FinalizeMigration for incoming instances' routed interfaces
1521
    for nic_seq, nic in enumerate(kvm_nics):
1522
      if (incoming and
1523
          nic.nicparams[constants.NIC_MODE] != constants.NIC_MODE_BRIDGED):
1524
        continue
1525
      self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
1526

    
1527
    # CPU affinity requires kvm to start paused, so we set this flag if the
1528
    # instance is not already paused and if we are not going to accept a
1529
    # migrating instance. In the latter case, pausing is not needed.
1530
    start_kvm_paused = not (_KVM_START_PAUSED_FLAG in kvm_cmd) and not incoming
1531
    if start_kvm_paused:
1532
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1533

    
1534
    # Note: CPU pinning is using up_hvp since changes take effect
1535
    # during instance startup anyway, and to avoid problems when soft
1536
    # rebooting the instance.
1537
    cpu_pinning = False
1538
    if up_hvp.get(constants.HV_CPU_MASK, None):
1539
      cpu_pinning = True
1540

    
1541
    if security_model == constants.HT_SM_POOL:
1542
      ss = ssconf.SimpleStore()
1543
      uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
1544
      all_uids = set(uidpool.ExpandUidPool(uid_pool))
1545
      uid = uidpool.RequestUnusedUid(all_uids)
1546
      try:
1547
        username = pwd.getpwuid(uid.GetUid()).pw_name
1548
        kvm_cmd.extend(["-runas", username])
1549
        self._RunKVMCmd(name, kvm_cmd, tapfds)
1550
      except:
1551
        uidpool.ReleaseUid(uid)
1552
        raise
1553
      else:
1554
        uid.Unlock()
1555
        utils.WriteFile(self._InstanceUidFile(name), data=uid.AsStr())
1556
    else:
1557
      self._RunKVMCmd(name, kvm_cmd, tapfds)
1558

    
1559
    utils.EnsureDirs([(self._InstanceNICDir(instance.name),
1560
                     constants.RUN_DIRS_MODE)])
1561
    for nic_seq, tap in enumerate(taps):
1562
      utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
1563
                      data=tap)
1564

    
1565
    if vnc_pwd:
1566
      change_cmd = "change vnc password %s" % vnc_pwd
1567
      self._CallMonitorCommand(instance.name, change_cmd)
1568

    
1569
    # Setting SPICE password. We are not vulnerable to malicious passwordless
1570
    # connection attempts because SPICE by default does not allow connections
1571
    # if neither a password nor the "disable_ticketing" options are specified.
1572
    # As soon as we send the password via QMP, that password is a valid ticket
1573
    # for connection.
1574
    spice_password_file = conf_hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]
1575
    if spice_password_file:
1576
      spice_pwd = ""
1577
      try:
1578
        spice_pwd = utils.ReadOneLineFile(spice_password_file, strict=True)
1579
      except EnvironmentError, err:
1580
        raise errors.HypervisorError("Failed to open SPICE password file %s: %s"
1581
                                     % (spice_password_file, err))
1582

    
1583
      qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
1584
      qmp.connect()
1585
      arguments = {
1586
          "protocol": "spice",
1587
          "password": spice_pwd,
1588
      }
1589
      qmp.Execute("set_password", arguments)
1590

    
1591
    for filename in temp_files:
1592
      utils.RemoveFile(filename)
1593

    
1594
    # If requested, set CPU affinity and resume instance execution
1595
    if cpu_pinning:
1596
      self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK])
1597

    
1598
    start_memory = self._InstanceStartupMemory(instance)
1599
    if start_memory < instance.beparams[constants.BE_MAXMEM]:
1600
      self.BalloonInstanceMemory(instance, start_memory)
1601

    
1602
    if start_kvm_paused:
1603
      # To control CPU pinning, ballooning, and vnc/spice passwords
1604
      # the VM was started in a frozen state. If freezing was not
1605
      # explicitly requested resume the vm status.
1606
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1607

    
1608
  def StartInstance(self, instance, block_devices, startup_paused):
1609
    """Start an instance.
1610

1611
    """
1612
    self._CheckDown(instance.name)
1613
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1614
                                           startup_paused)
1615
    self._SaveKVMRuntime(instance, kvm_runtime)
1616
    self._ExecuteKVMRuntime(instance, kvm_runtime)
1617

    
1618
  def _CallMonitorCommand(self, instance_name, command):
1619
    """Invoke a command on the instance monitor.
1620

1621
    """
1622
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1623
             (utils.ShellQuote(command),
1624
              constants.SOCAT_PATH,
1625
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1626
    result = utils.RunCmd(socat)
1627
    if result.failed:
1628
      msg = ("Failed to send command '%s' to instance %s."
1629
             " output: %s, error: %s, fail_reason: %s" %
1630
             (command, instance_name,
1631
              result.stdout, result.stderr, result.fail_reason))
1632
      raise errors.HypervisorError(msg)
1633

    
1634
    return result
1635

    
1636
  @classmethod
1637
  def _ParseKVMVersion(cls, text):
1638
    """Parse the KVM version from the --help output.
1639

1640
    @type text: string
1641
    @param text: output of kvm --help
1642
    @return: (version, v_maj, v_min, v_rev)
1643
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1644

1645
    """
1646
    match = cls._VERSION_RE.search(text.splitlines()[0])
1647
    if not match:
1648
      raise errors.HypervisorError("Unable to get KVM version")
1649

    
1650
    v_all = match.group(0)
1651
    v_maj = int(match.group(1))
1652
    v_min = int(match.group(2))
1653
    if match.group(4):
1654
      v_rev = int(match.group(4))
1655
    else:
1656
      v_rev = 0
1657
    return (v_all, v_maj, v_min, v_rev)
1658

    
1659
  @classmethod
1660
  def _GetKVMHelpOutput(cls):
1661
    """Return the KVM help output.
1662

1663
    @return: output of kvm --help
1664
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
1665

1666
    """
1667
    result = utils.RunCmd([constants.KVM_PATH, "--help"])
1668
    if result.failed:
1669
      raise errors.HypervisorError("Unable to get KVM help output")
1670
    return result.output
1671

    
1672
  @classmethod
1673
  def _GetKVMVersion(cls):
1674
    """Return the installed KVM version.
1675

1676
    @return: (version, v_maj, v_min, v_rev)
1677
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1678

1679
    """
1680
    return cls._ParseKVMVersion(cls._GetKVMHelpOutput())
1681

    
1682
  def StopInstance(self, instance, force=False, retry=False, name=None):
1683
    """Stop an instance.
1684

1685
    """
1686
    if name is not None and not force:
1687
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
1688
    if name is None:
1689
      name = instance.name
1690
      acpi = instance.hvparams[constants.HV_ACPI]
1691
    else:
1692
      acpi = False
1693
    _, pid, alive = self._InstancePidAlive(name)
1694
    if pid > 0 and alive:
1695
      if force or not acpi:
1696
        utils.KillProcess(pid)
1697
      else:
1698
        self._CallMonitorCommand(name, "system_powerdown")
1699

    
1700
  @classmethod
1701
  def _GetDefaultMachineVersion(cls):
1702
    """Return the default hardware revision (e.g. pc-1.1)
1703

1704
    """
1705
    result = utils.RunCmd([constants.KVM_PATH, "-M", "?"])
1706
    if result.failed:
1707
      raise errors.HypervisorError("Unable to get default hardware revision")
1708
    for line in result.output.splitlines():
1709
      match = cls._DEFAULT_MACHINE_VERSION_RE.match(line)
1710
      if match:
1711
        return match.group(1)
1712

    
1713
    return "pc"
1714

    
1715
  def CleanupInstance(self, instance_name):
1716
    """Cleanup after a stopped instance
1717

1718
    """
1719
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1720
    if pid > 0 and alive:
1721
      raise errors.HypervisorError("Cannot cleanup a live instance")
1722
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1723

    
1724
  def RebootInstance(self, instance):
1725
    """Reboot an instance.
1726

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

    
1745
  def MigrationInfo(self, instance):
1746
    """Get instance information to perform a migration.
1747

1748
    @type instance: L{objects.Instance}
1749
    @param instance: instance to be migrated
1750
    @rtype: string
1751
    @return: content of the KVM runtime file
1752

1753
    """
1754
    return self._ReadKVMRuntime(instance.name)
1755

    
1756
  def AcceptInstance(self, instance, info, target):
1757
    """Prepare to accept an instance.
1758

1759
    @type instance: L{objects.Instance}
1760
    @param instance: instance to be accepted
1761
    @type info: string
1762
    @param info: content of the KVM runtime file on the source node
1763
    @type target: string
1764
    @param target: target host (usually ip), on this node
1765

1766
    """
1767
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1768
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1769
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
1770

    
1771
  def FinalizeMigrationDst(self, instance, info, success):
1772
    """Finalize the instance migration on the target node.
1773

1774
    Stop the incoming mode KVM.
1775

1776
    @type instance: L{objects.Instance}
1777
    @param instance: instance whose migration is being finalized
1778

1779
    """
1780
    if success:
1781
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1782
      kvm_nics = kvm_runtime[1]
1783

    
1784
      for nic_seq, nic in enumerate(kvm_nics):
1785
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1786
          # Bridged interfaces have already been configured
1787
          continue
1788
        try:
1789
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
1790
        except EnvironmentError, err:
1791
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
1792
                          instance.name, nic_seq, str(err))
1793
          continue
1794
        try:
1795
          self._ConfigureNIC(instance, nic_seq, nic, tap)
1796
        except errors.HypervisorError, err:
1797
          logging.warning(str(err))
1798

    
1799
      self._WriteKVMRuntime(instance.name, info)
1800
    else:
1801
      self.StopInstance(instance, force=True)
1802

    
1803
  def MigrateInstance(self, instance, target, live):
1804
    """Migrate an instance to a target node.
1805

1806
    The migration will not be attempted if the instance is not
1807
    currently running.
1808

1809
    @type instance: L{objects.Instance}
1810
    @param instance: the instance to be migrated
1811
    @type target: string
1812
    @param target: ip address of the target node
1813
    @type live: boolean
1814
    @param live: perform a live migration
1815

1816
    """
1817
    instance_name = instance.name
1818
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
1819
    _, _, alive = self._InstancePidAlive(instance_name)
1820
    if not alive:
1821
      raise errors.HypervisorError("Instance not running, cannot migrate")
1822

    
1823
    if not live:
1824
      self._CallMonitorCommand(instance_name, "stop")
1825

    
1826
    migrate_command = ("migrate_set_speed %dm" %
1827
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1828
    self._CallMonitorCommand(instance_name, migrate_command)
1829

    
1830
    migrate_command = ("migrate_set_downtime %dms" %
1831
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
1832
    self._CallMonitorCommand(instance_name, migrate_command)
1833

    
1834
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
1835
    self._CallMonitorCommand(instance_name, migrate_command)
1836

    
1837
  def FinalizeMigrationSource(self, instance, success, live):
1838
    """Finalize the instance migration on the source node.
1839

1840
    @type instance: L{objects.Instance}
1841
    @param instance: the instance that was migrated
1842
    @type success: bool
1843
    @param success: whether the migration succeeded or not
1844
    @type live: bool
1845
    @param live: whether the user requested a live migration or not
1846

1847
    """
1848
    if success:
1849
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
1850
      utils.KillProcess(pid)
1851
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
1852
    elif live:
1853
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1854

    
1855
  def GetMigrationStatus(self, instance):
1856
    """Get the migration status
1857

1858
    @type instance: L{objects.Instance}
1859
    @param instance: the instance that is being migrated
1860
    @rtype: L{objects.MigrationStatus}
1861
    @return: the status of the current migration (one of
1862
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
1863
             progress info that can be retrieved from the hypervisor
1864

1865
    """
1866
    info_command = "info migrate"
1867
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
1868
      result = self._CallMonitorCommand(instance.name, info_command)
1869
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
1870
      if not match:
1871
        if not result.stdout:
1872
          logging.info("KVM: empty 'info migrate' result")
1873
        else:
1874
          logging.warning("KVM: unknown 'info migrate' result: %s",
1875
                          result.stdout)
1876
      else:
1877
        status = match.group(1)
1878
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
1879
          migration_status = objects.MigrationStatus(status=status)
1880
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
1881
          if match:
1882
            migration_status.transferred_ram = match.group("transferred")
1883
            migration_status.total_ram = match.group("total")
1884

    
1885
          return migration_status
1886

    
1887
        logging.warning("KVM: unknown migration status '%s'", status)
1888

    
1889
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1890

    
1891
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
1892

    
1893
  def BalloonInstanceMemory(self, instance, mem):
1894
    """Balloon an instance memory to a certain value.
1895

1896
    @type instance: L{objects.Instance}
1897
    @param instance: instance to be accepted
1898
    @type mem: int
1899
    @param mem: actual memory size to use for instance runtime
1900

1901
    """
1902
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
1903

    
1904
  def GetNodeInfo(self):
1905
    """Return information about the node.
1906

1907
    @return: a dict with the following keys (values in MiB):
1908
          - memory_total: the total memory size on the node
1909
          - memory_free: the available memory on the node for instances
1910
          - memory_dom0: the memory used by the node itself, if available
1911
          - hv_version: the hypervisor version in the form (major, minor,
1912
                        revision)
1913

1914
    """
1915
    result = self.GetLinuxNodeInfo()
1916
    _, v_major, v_min, v_rev = self._GetKVMVersion()
1917
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
1918
    return result
1919

    
1920
  @classmethod
1921
  def GetInstanceConsole(cls, instance, hvparams, beparams):
1922
    """Return a command for connecting to the console of an instance.
1923

1924
    """
1925
    if hvparams[constants.HV_SERIAL_CONSOLE]:
1926
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
1927
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
1928
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
1929
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
1930
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
1931
      return objects.InstanceConsole(instance=instance.name,
1932
                                     kind=constants.CONS_SSH,
1933
                                     host=instance.primary_node,
1934
                                     user=constants.SSH_CONSOLE_USER,
1935
                                     command=cmd)
1936

    
1937
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
1938
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
1939
      display = instance.network_port - constants.VNC_BASE_PORT
1940
      return objects.InstanceConsole(instance=instance.name,
1941
                                     kind=constants.CONS_VNC,
1942
                                     host=vnc_bind_address,
1943
                                     port=instance.network_port,
1944
                                     display=display)
1945

    
1946
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
1947
    if spice_bind:
1948
      return objects.InstanceConsole(instance=instance.name,
1949
                                     kind=constants.CONS_SPICE,
1950
                                     host=spice_bind,
1951
                                     port=instance.network_port)
1952

    
1953
    return objects.InstanceConsole(instance=instance.name,
1954
                                   kind=constants.CONS_MESSAGE,
1955
                                   message=("No serial shell for instance %s" %
1956
                                            instance.name))
1957

    
1958
  def Verify(self):
1959
    """Verify the hypervisor.
1960

1961
    Check that the binary exists.
1962

1963
    """
1964
    if not os.path.exists(constants.KVM_PATH):
1965
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
1966
    if not os.path.exists(constants.SOCAT_PATH):
1967
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
1968

    
1969
  @classmethod
1970
  def CheckParameterSyntax(cls, hvparams):
1971
    """Check the given parameters for validity.
1972

1973
    @type hvparams:  dict
1974
    @param hvparams: dictionary with parameter names/value
1975
    @raise errors.HypervisorError: when a parameter is not valid
1976

1977
    """
1978
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
1979

    
1980
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
1981
    if kernel_path:
1982
      if not hvparams[constants.HV_ROOT_PATH]:
1983
        raise errors.HypervisorError("Need a root partition for the instance,"
1984
                                     " if a kernel is defined")
1985

    
1986
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
1987
        not hvparams[constants.HV_VNC_X509]):
1988
      raise errors.HypervisorError("%s must be defined, if %s is" %
1989
                                   (constants.HV_VNC_X509,
1990
                                    constants.HV_VNC_X509_VERIFY))
1991

    
1992
    if hvparams[constants.HV_SERIAL_CONSOLE]:
1993
      serial_speed = hvparams[constants.HV_SERIAL_SPEED]
1994
      valid_speeds = constants.VALID_SERIAL_SPEEDS
1995
      if not serial_speed or serial_speed not in valid_speeds:
1996
        raise errors.HypervisorError("Invalid serial console speed, must be"
1997
                                     " one of: %s" %
1998
                                     utils.CommaJoin(valid_speeds))
1999

    
2000
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2001
    if (boot_order == constants.HT_BO_CDROM and
2002
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2003
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2004
                                   " ISO path")
2005

    
2006
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2007
    if security_model == constants.HT_SM_USER:
2008
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
2009
        raise errors.HypervisorError("A security domain (user to run kvm as)"
2010
                                     " must be specified")
2011
    elif (security_model == constants.HT_SM_NONE or
2012
          security_model == constants.HT_SM_POOL):
2013
      if hvparams[constants.HV_SECURITY_DOMAIN]:
2014
        raise errors.HypervisorError("Cannot have a security domain when the"
2015
                                     " security model is 'none' or 'pool'")
2016

    
2017
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2018
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2019
    if spice_bind:
2020
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2021
        # if an IP version is specified, the spice_bind parameter must be an
2022
        # IP of that family
2023
        if (netutils.IP4Address.IsValid(spice_bind) and
2024
            spice_ip_version != constants.IP4_VERSION):
2025
          raise errors.HypervisorError("spice: got an IPv4 address (%s), but"
2026
                                       " the specified IP version is %s" %
2027
                                       (spice_bind, spice_ip_version))
2028

    
2029
        if (netutils.IP6Address.IsValid(spice_bind) and
2030
            spice_ip_version != constants.IP6_VERSION):
2031
          raise errors.HypervisorError("spice: got an IPv6 address (%s), but"
2032
                                       " the specified IP version is %s" %
2033
                                       (spice_bind, spice_ip_version))
2034
    else:
2035
      # All the other SPICE parameters depend on spice_bind being set. Raise an
2036
      # error if any of them is set without it.
2037
      for param in _SPICE_ADDITIONAL_PARAMS:
2038
        if hvparams[param]:
2039
          raise errors.HypervisorError("spice: %s requires %s to be set" %
2040
                                       (param, constants.HV_KVM_SPICE_BIND))
2041

    
2042
  @classmethod
2043
  def ValidateParameters(cls, hvparams):
2044
    """Check the given parameters for validity.
2045

2046
    @type hvparams:  dict
2047
    @param hvparams: dictionary with parameter names/value
2048
    @raise errors.HypervisorError: when a parameter is not valid
2049

2050
    """
2051
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2052

    
2053
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2054
    if security_model == constants.HT_SM_USER:
2055
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2056
      try:
2057
        pwd.getpwnam(username)
2058
      except KeyError:
2059
        raise errors.HypervisorError("Unknown security domain user %s"
2060
                                     % username)
2061

    
2062
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2063
    if spice_bind:
2064
      # only one of VNC and SPICE can be used currently.
2065
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2066
        raise errors.HypervisorError("both SPICE and VNC are configured, but"
2067
                                     " only one of them can be used at a"
2068
                                     " given time.")
2069

    
2070
      # KVM version should be >= 0.14.0
2071
      kvmhelp = cls._GetKVMHelpOutput()
2072
      if not cls._SPICE_RE.search(kvmhelp):
2073
        raise errors.HypervisorError("spice is configured, but it is not"
2074
                                     " supported according to kvm --help")
2075

    
2076
      # if spice_bind is not an IP address, it must be a valid interface
2077
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind)
2078
                       or netutils.IP6Address.IsValid(spice_bind))
2079
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2080
        raise errors.HypervisorError("spice: the %s parameter must be either"
2081
                                     " a valid IP address or interface name" %
2082
                                     constants.HV_KVM_SPICE_BIND)
2083

    
2084
  @classmethod
2085
  def PowercycleNode(cls):
2086
    """KVM powercycle, just a wrapper over Linux powercycle.
2087

2088
    """
2089
    cls.LinuxPowercycle()