Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ e6f24d89

History | View | Annotate | Download (75.9 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_KVM_EXTRA: hv_base.NO_CHECK,
541
    }
542

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

    
550
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
551
  _MIGRATION_INFO_RETRY_DELAY = 2
552

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
643
    return (instance, memory, vcpus)
644

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

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

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

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

    
664
    return (pidfile, pid, alive)
665

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
931
    return result
932

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1060
    self.ValidateParameters(hvp)
1061

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1265
        spice_address = addresses[spice_ip_version][0]
1266

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1349
    if hvp[constants.HV_KVM_EXTRA]:
1350
      kvm_cmd.extend([hvp[constants.HV_KVM_EXTRA]])
1351

    
1352
    # Save the current instance nics, but defer their expansion as parameters,
1353
    # as we'll need to generate executable temp files for them.
1354
    kvm_nics = instance.nics
1355
    hvparams = hvp
1356

    
1357
    return (kvm_cmd, kvm_nics, hvparams)
1358

    
1359
  def _WriteKVMRuntime(self, instance_name, data):
1360
    """Write an instance's KVM runtime
1361

1362
    """
1363
    try:
1364
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1365
                      data=data)
1366
    except EnvironmentError, err:
1367
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1368

    
1369
  def _ReadKVMRuntime(self, instance_name):
1370
    """Read an instance's KVM runtime
1371

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

    
1379
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1380
    """Save an instance's KVM runtime
1381

1382
    """
1383
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
1384
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1385
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
1386
    self._WriteKVMRuntime(instance.name, serialized_form)
1387

    
1388
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1389
    """Load an instance's KVM runtime
1390

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

    
1399
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1400
    """Run the KVM cmd and check for errors
1401

1402
    @type name: string
1403
    @param name: instance name
1404
    @type kvm_cmd: list of strings
1405
    @param kvm_cmd: runcmd input for kvm
1406
    @type tap_fds: list of int
1407
    @param tap_fds: fds of tap devices opened by Ganeti
1408

1409
    """
1410
    try:
1411
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1412
    finally:
1413
      for fd in tap_fds:
1414
        utils_wrapper.CloseFdNoError(fd)
1415

    
1416
    if result.failed:
1417
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1418
                                   (name, result.fail_reason, result.output))
1419
    if not self._InstancePidAlive(name)[2]:
1420
      raise errors.HypervisorError("Failed to start instance %s" % name)
1421

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

1425
    @type incoming: tuple of strings
1426
    @param incoming: (target_host_ip, port)
1427

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

    
1441
    temp_files = []
1442

    
1443
    kvm_cmd, kvm_nics, up_hvp = kvm_runtime
1444
    up_hvp = objects.FillDict(conf_hvp, up_hvp)
1445

    
1446
    kvmhelp = self._GetKVMHelpOutput()
1447
    _, v_major, v_min, _ = self._ParseKVMVersion(kvmhelp)
1448

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

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

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

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

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

    
1508
    if incoming:
1509
      target, port = incoming
1510
      kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])
1511

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

    
1524
    if conf_hvp[constants.HV_KVM_USE_CHROOT]:
1525
      utils.EnsureDirs([(self._InstanceChrootDir(name),
1526
                         constants.SECURE_DIR_MODE)])
1527

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

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

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

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

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

    
1574
    utils.EnsureDirs([(self._InstanceNICDir(instance.name),
1575
                     constants.RUN_DIRS_MODE)])
1576
    for nic_seq, tap in enumerate(taps):
1577
      utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
1578
                      data=tap)
1579

    
1580
    if vnc_pwd:
1581
      change_cmd = "change vnc password %s" % vnc_pwd
1582
      self._CallMonitorCommand(instance.name, change_cmd)
1583

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

    
1598
      qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
1599
      qmp.connect()
1600
      arguments = {
1601
          "protocol": "spice",
1602
          "password": spice_pwd,
1603
      }
1604
      qmp.Execute("set_password", arguments)
1605

    
1606
    for filename in temp_files:
1607
      utils.RemoveFile(filename)
1608

    
1609
    # If requested, set CPU affinity and resume instance execution
1610
    if cpu_pinning:
1611
      self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK])
1612

    
1613
    start_memory = self._InstanceStartupMemory(instance)
1614
    if start_memory < instance.beparams[constants.BE_MAXMEM]:
1615
      self.BalloonInstanceMemory(instance, start_memory)
1616

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

    
1623
  def StartInstance(self, instance, block_devices, startup_paused):
1624
    """Start an instance.
1625

1626
    """
1627
    self._CheckDown(instance.name)
1628
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1629
                                           startup_paused)
1630
    self._SaveKVMRuntime(instance, kvm_runtime)
1631
    self._ExecuteKVMRuntime(instance, kvm_runtime)
1632

    
1633
  def _CallMonitorCommand(self, instance_name, command):
1634
    """Invoke a command on the instance monitor.
1635

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

    
1649
    return result
1650

    
1651
  @classmethod
1652
  def _ParseKVMVersion(cls, text):
1653
    """Parse the KVM version from the --help output.
1654

1655
    @type text: string
1656
    @param text: output of kvm --help
1657
    @return: (version, v_maj, v_min, v_rev)
1658
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1659

1660
    """
1661
    match = cls._VERSION_RE.search(text.splitlines()[0])
1662
    if not match:
1663
      raise errors.HypervisorError("Unable to get KVM version")
1664

    
1665
    v_all = match.group(0)
1666
    v_maj = int(match.group(1))
1667
    v_min = int(match.group(2))
1668
    if match.group(4):
1669
      v_rev = int(match.group(4))
1670
    else:
1671
      v_rev = 0
1672
    return (v_all, v_maj, v_min, v_rev)
1673

    
1674
  @classmethod
1675
  def _GetKVMHelpOutput(cls):
1676
    """Return the KVM help output.
1677

1678
    @return: output of kvm --help
1679
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
1680

1681
    """
1682
    result = utils.RunCmd([constants.KVM_PATH, "--help"])
1683
    if result.failed:
1684
      raise errors.HypervisorError("Unable to get KVM help output")
1685
    return result.output
1686

    
1687
  @classmethod
1688
  def _GetKVMVersion(cls):
1689
    """Return the installed KVM version.
1690

1691
    @return: (version, v_maj, v_min, v_rev)
1692
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1693

1694
    """
1695
    return cls._ParseKVMVersion(cls._GetKVMHelpOutput())
1696

    
1697
  def StopInstance(self, instance, force=False, retry=False, name=None):
1698
    """Stop an instance.
1699

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

    
1715
  @classmethod
1716
  def _GetDefaultMachineVersion(cls):
1717
    """Return the default hardware revision (e.g. pc-1.1)
1718

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

    
1729
  def CleanupInstance(self, instance_name):
1730
    """Cleanup after a stopped instance
1731

1732
    """
1733
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1734
    if pid > 0 and alive:
1735
      raise errors.HypervisorError("Cannot cleanup a live instance")
1736
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1737

    
1738
  def RebootInstance(self, instance):
1739
    """Reboot an instance.
1740

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

    
1759
  def MigrationInfo(self, instance):
1760
    """Get instance information to perform a migration.
1761

1762
    @type instance: L{objects.Instance}
1763
    @param instance: instance to be migrated
1764
    @rtype: string
1765
    @return: content of the KVM runtime file
1766

1767
    """
1768
    return self._ReadKVMRuntime(instance.name)
1769

    
1770
  def AcceptInstance(self, instance, info, target):
1771
    """Prepare to accept an instance.
1772

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

1780
    """
1781
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1782
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1783
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
1784

    
1785
  def FinalizeMigrationDst(self, instance, info, success):
1786
    """Finalize the instance migration on the target node.
1787

1788
    Stop the incoming mode KVM.
1789

1790
    @type instance: L{objects.Instance}
1791
    @param instance: instance whose migration is being finalized
1792

1793
    """
1794
    if success:
1795
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1796
      kvm_nics = kvm_runtime[1]
1797

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

    
1813
      self._WriteKVMRuntime(instance.name, info)
1814
    else:
1815
      self.StopInstance(instance, force=True)
1816

    
1817
  def MigrateInstance(self, instance, target, live):
1818
    """Migrate an instance to a target node.
1819

1820
    The migration will not be attempted if the instance is not
1821
    currently running.
1822

1823
    @type instance: L{objects.Instance}
1824
    @param instance: the instance to be migrated
1825
    @type target: string
1826
    @param target: ip address of the target node
1827
    @type live: boolean
1828
    @param live: perform a live migration
1829

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

    
1837
    if not live:
1838
      self._CallMonitorCommand(instance_name, "stop")
1839

    
1840
    migrate_command = ("migrate_set_speed %dm" %
1841
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1842
    self._CallMonitorCommand(instance_name, migrate_command)
1843

    
1844
    migrate_command = ("migrate_set_downtime %dms" %
1845
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
1846
    self._CallMonitorCommand(instance_name, migrate_command)
1847

    
1848
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
1849
    self._CallMonitorCommand(instance_name, migrate_command)
1850

    
1851
  def FinalizeMigrationSource(self, instance, success, live):
1852
    """Finalize the instance migration on the source node.
1853

1854
    @type instance: L{objects.Instance}
1855
    @param instance: the instance that was migrated
1856
    @type success: bool
1857
    @param success: whether the migration succeeded or not
1858
    @type live: bool
1859
    @param live: whether the user requested a live migration or not
1860

1861
    """
1862
    if success:
1863
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
1864
      utils.KillProcess(pid)
1865
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
1866
    elif live:
1867
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1868

    
1869
  def GetMigrationStatus(self, instance):
1870
    """Get the migration status
1871

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

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

    
1899
          return migration_status
1900

    
1901
        logging.warning("KVM: unknown migration status '%s'", status)
1902

    
1903
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1904

    
1905
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
1906

    
1907
  def BalloonInstanceMemory(self, instance, mem):
1908
    """Balloon an instance memory to a certain value.
1909

1910
    @type instance: L{objects.Instance}
1911
    @param instance: instance to be accepted
1912
    @type mem: int
1913
    @param mem: actual memory size to use for instance runtime
1914

1915
    """
1916
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
1917

    
1918
  def GetNodeInfo(self):
1919
    """Return information about the node.
1920

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

1928
    """
1929
    result = self.GetLinuxNodeInfo()
1930
    _, v_major, v_min, v_rev = self._GetKVMVersion()
1931
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
1932
    return result
1933

    
1934
  @classmethod
1935
  def GetInstanceConsole(cls, instance, hvparams, beparams):
1936
    """Return a command for connecting to the console of an instance.
1937

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

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

    
1960
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
1961
    if spice_bind:
1962
      return objects.InstanceConsole(instance=instance.name,
1963
                                     kind=constants.CONS_SPICE,
1964
                                     host=spice_bind,
1965
                                     port=instance.network_port)
1966

    
1967
    return objects.InstanceConsole(instance=instance.name,
1968
                                   kind=constants.CONS_MESSAGE,
1969
                                   message=("No serial shell for instance %s" %
1970
                                            instance.name))
1971

    
1972
  def Verify(self):
1973
    """Verify the hypervisor.
1974

1975
    Check that the binary exists.
1976

1977
    """
1978
    if not os.path.exists(constants.KVM_PATH):
1979
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
1980
    if not os.path.exists(constants.SOCAT_PATH):
1981
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
1982

    
1983
  @classmethod
1984
  def CheckParameterSyntax(cls, hvparams):
1985
    """Check the given parameters for validity.
1986

1987
    @type hvparams:  dict
1988
    @param hvparams: dictionary with parameter names/value
1989
    @raise errors.HypervisorError: when a parameter is not valid
1990

1991
    """
1992
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
1993

    
1994
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
1995
    if kernel_path:
1996
      if not hvparams[constants.HV_ROOT_PATH]:
1997
        raise errors.HypervisorError("Need a root partition for the instance,"
1998
                                     " if a kernel is defined")
1999

    
2000
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
2001
        not hvparams[constants.HV_VNC_X509]):
2002
      raise errors.HypervisorError("%s must be defined, if %s is" %
2003
                                   (constants.HV_VNC_X509,
2004
                                    constants.HV_VNC_X509_VERIFY))
2005

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

    
2014
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2015
    if (boot_order == constants.HT_BO_CDROM and
2016
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2017
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2018
                                   " ISO path")
2019

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

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

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

    
2056
  @classmethod
2057
  def ValidateParameters(cls, hvparams):
2058
    """Check the given parameters for validity.
2059

2060
    @type hvparams:  dict
2061
    @param hvparams: dictionary with parameter names/value
2062
    @raise errors.HypervisorError: when a parameter is not valid
2063

2064
    """
2065
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2066

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

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

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

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

    
2098
  @classmethod
2099
  def PowercycleNode(cls):
2100
    """KVM powercycle, just a wrapper over Linux powercycle.
2101

2102
    """
2103
    cls.LinuxPowercycle()