Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 07788a0b

History | View | Annotate | Download (72.8 kB)

1
#
2
#
3

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

    
21

    
22
"""KVM hypervisor
23

24
"""
25

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

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

    
57

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

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

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

    
82

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

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

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

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

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

    
114

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

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

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

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

    
132
  flags = IFF_TAP | IFF_NO_PI
133

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

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

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

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

    
149

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

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

    
172
  return env
173

    
174

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

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

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

    
186
    self.data = data
187

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

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

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

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

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

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

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

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

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

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

    
228

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

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

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

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

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

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

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

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

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

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

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

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

    
297
    self._check_socket()
298

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

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

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

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

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

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

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

    
340
    return (message, buf)
341

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

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

350
    """
351
    self._check_connection()
352

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

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

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

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

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

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

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

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

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

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

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

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

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

    
437

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

441
  """
442
  CAN_MIGRATE = True
443

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

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

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

    
543
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
544
  _MIGRATION_INFO_RETRY_DELAY = 2
545

    
546
  _VERSION_RE = re.compile(r"\b(\d+)\.(\d+)(\.(\d+))?\b")
547

    
548
  _CPU_INFO_RE = re.compile(r"cpu\s+\#(\d+).*thread_id\s*=\s*(\d+)", re.I)
549
  _CPU_INFO_CMD = "info cpus"
550
  _CONT_CMD = "cont"
551

    
552
  ANCILLARY_FILES = [
553
    _KVM_NETWORK_SCRIPT,
554
    ]
555
  ANCILLARY_FILES_OPT = [
556
    _KVM_NETWORK_SCRIPT,
557
    ]
558

    
559
  def __init__(self):
560
    hv_base.BaseHypervisor.__init__(self)
561
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
562
    # in a tmpfs filesystem or has been otherwise wiped out.
563
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
564
    utils.EnsureDirs(dirs)
565

    
566
  @classmethod
567
  def _InstancePidFile(cls, instance_name):
568
    """Returns the instance pidfile.
569

570
    """
571
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
572

    
573
  @classmethod
574
  def _InstanceUidFile(cls, instance_name):
575
    """Returns the instance uidfile.
576

577
    """
578
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
579

    
580
  @classmethod
581
  def _InstancePidInfo(cls, pid):
582
    """Check pid file for instance information.
583

584
    Check that a pid file is associated with an instance, and retrieve
585
    information from its command line.
586

587
    @type pid: string or int
588
    @param pid: process id of the instance to check
589
    @rtype: tuple
590
    @return: (instance_name, memory, vcpus)
591
    @raise errors.HypervisorError: when an instance cannot be found
592

593
    """
594
    alive = utils.IsProcessAlive(pid)
595
    if not alive:
596
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
597

    
598
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
599
    try:
600
      cmdline = utils.ReadFile(cmdline_file)
601
    except EnvironmentError, err:
602
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
603
                                   (pid, err))
604

    
605
    instance = None
606
    memory = 0
607
    vcpus = 0
608

    
609
    arg_list = cmdline.split("\x00")
610
    while arg_list:
611
      arg = arg_list.pop(0)
612
      if arg == "-name":
613
        instance = arg_list.pop(0)
614
      elif arg == "-m":
615
        memory = int(arg_list.pop(0))
616
      elif arg == "-smp":
617
        vcpus = int(arg_list.pop(0))
618

    
619
    if instance is None:
620
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
621
                                   " instance" % pid)
622

    
623
    return (instance, memory, vcpus)
624

    
625
  def _InstancePidAlive(self, instance_name):
626
    """Returns the instance pidfile, pid, and liveness.
627

628
    @type instance_name: string
629
    @param instance_name: instance name
630
    @rtype: tuple
631
    @return: (pid file name, pid, liveness)
632

633
    """
634
    pidfile = self._InstancePidFile(instance_name)
635
    pid = utils.ReadPidFile(pidfile)
636

    
637
    alive = False
638
    try:
639
      cmd_instance = self._InstancePidInfo(pid)[0]
640
      alive = (cmd_instance == instance_name)
641
    except errors.HypervisorError:
642
      pass
643

    
644
    return (pidfile, pid, alive)
645

    
646
  def _CheckDown(self, instance_name):
647
    """Raises an error unless the given instance is down.
648

649
    """
650
    alive = self._InstancePidAlive(instance_name)[2]
651
    if alive:
652
      raise errors.HypervisorError("Failed to start instance %s: %s" %
653
                                   (instance_name, "already running"))
654

    
655
  @classmethod
656
  def _InstanceMonitor(cls, instance_name):
657
    """Returns the instance monitor socket name
658

659
    """
660
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
661

    
662
  @classmethod
663
  def _InstanceSerial(cls, instance_name):
664
    """Returns the instance serial socket name
665

666
    """
667
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
668

    
669
  @classmethod
670
  def _InstanceQmpMonitor(cls, instance_name):
671
    """Returns the instance serial QMP socket name
672

673
    """
674
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
675

    
676
  @staticmethod
677
  def _SocatUnixConsoleParams():
678
    """Returns the correct parameters for socat
679

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

682
    """
683
    if constants.SOCAT_USE_ESCAPE:
684
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
685
    else:
686
      return "echo=0,icanon=0"
687

    
688
  @classmethod
689
  def _InstanceKVMRuntime(cls, instance_name):
690
    """Returns the instance KVM runtime filename
691

692
    """
693
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
694

    
695
  @classmethod
696
  def _InstanceChrootDir(cls, instance_name):
697
    """Returns the name of the KVM chroot dir of the instance
698

699
    """
700
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
701

    
702
  @classmethod
703
  def _InstanceNICDir(cls, instance_name):
704
    """Returns the name of the directory holding the tap device files for a
705
    given instance.
706

707
    """
708
    return utils.PathJoin(cls._NICS_DIR, instance_name)
709

    
710
  @classmethod
711
  def _InstanceNICFile(cls, instance_name, seq):
712
    """Returns the name of the file containing the tap device for a given NIC
713

714
    """
715
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
716

    
717
  @classmethod
718
  def _InstanceKeymapFile(cls, instance_name):
719
    """Returns the name of the file containing the keymap for a given instance
720

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

    
724
  @classmethod
725
  def _TryReadUidFile(cls, uid_file):
726
    """Try to read a uid file
727

728
    """
729
    if os.path.exists(uid_file):
730
      try:
731
        uid = int(utils.ReadOneLineFile(uid_file))
732
        return uid
733
      except EnvironmentError:
734
        logging.warning("Can't read uid file", exc_info=True)
735
      except (TypeError, ValueError):
736
        logging.warning("Can't parse uid file contents", exc_info=True)
737
    return None
738

    
739
  @classmethod
740
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
741
    """Removes an instance's rutime sockets/files/dirs.
742

743
    """
744
    utils.RemoveFile(pidfile)
745
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
746
    utils.RemoveFile(cls._InstanceSerial(instance_name))
747
    utils.RemoveFile(cls._InstanceQmpMonitor(instance_name))
748
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
749
    utils.RemoveFile(cls._InstanceKeymapFile(instance_name))
750
    uid_file = cls._InstanceUidFile(instance_name)
751
    uid = cls._TryReadUidFile(uid_file)
752
    utils.RemoveFile(uid_file)
753
    if uid is not None:
754
      uidpool.ReleaseUid(uid)
755
    try:
756
      shutil.rmtree(cls._InstanceNICDir(instance_name))
757
    except OSError, err:
758
      if err.errno != errno.ENOENT:
759
        raise
760
    try:
761
      chroot_dir = cls._InstanceChrootDir(instance_name)
762
      utils.RemoveDir(chroot_dir)
763
    except OSError, err:
764
      if err.errno == errno.ENOTEMPTY:
765
        # The chroot directory is expected to be empty, but it isn't.
766
        new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
767
                                          prefix="%s-%s-" %
768
                                          (instance_name,
769
                                           utils.TimestampForFilename()))
770
        logging.warning("The chroot directory of instance %s can not be"
771
                        " removed as it is not empty. Moving it to the"
772
                        " quarantine instead. Please investigate the"
773
                        " contents (%s) and clean up manually",
774
                        instance_name, new_chroot_dir)
775
        utils.RenameFile(chroot_dir, new_chroot_dir)
776
      else:
777
        raise
778

    
779
  @staticmethod
780
  def _ConfigureNIC(instance, seq, nic, tap):
781
    """Run the network configuration script for a specified NIC
782

783
    @param instance: instance we're acting on
784
    @type instance: instance object
785
    @param seq: nic sequence number
786
    @type seq: int
787
    @param nic: nic we're acting on
788
    @type nic: nic object
789
    @param tap: the host's tap interface this NIC corresponds to
790
    @type tap: str
791

792
    """
793
    if instance.tags:
794
      tags = " ".join(instance.tags)
795
    else:
796
      tags = ""
797

    
798
    env = {
799
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
800
      "INSTANCE": instance.name,
801
      "MAC": nic.mac,
802
      "MODE": nic.nicparams[constants.NIC_MODE],
803
      "INTERFACE": tap,
804
      "INTERFACE_INDEX": str(seq),
805
      "TAGS": tags,
806
    }
807

    
808
    if nic.ip:
809
      env["IP"] = nic.ip
810

    
811
    if nic.nicparams[constants.NIC_LINK]:
812
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
813

    
814
    if nic.network:
815
      n = objects.Network.FromDict(nic.netinfo)
816
      _BuildNetworkEnv(nic.network, n.network, n.gateway,
817
                       n.network6, n.gateway6, n.network_type,
818
                       n.mac_prefix, n.tags, env)
819

    
820
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
821
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
822

    
823
    result = utils.RunCmd([pathutils.KVM_IFUP, tap], env=env)
824
    if result.failed:
825
      raise errors.HypervisorError("Failed to configure interface %s: %s."
826
                                   " Network configuration script output: %s" %
827
                                   (tap, result.fail_reason, result.output))
828

    
829
  @staticmethod
830
  def _VerifyAffinityPackage():
831
    if affinity is None:
832
      raise errors.HypervisorError("affinity Python package not"
833
                                   " found; cannot use CPU pinning under KVM")
834

    
835
  @staticmethod
836
  def _BuildAffinityCpuMask(cpu_list):
837
    """Create a CPU mask suitable for sched_setaffinity from a list of
838
    CPUs.
839

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

843
    @type cpu_list: list of int
844
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
845
    @rtype: int
846
    @return: a bit mask of CPU affinities
847

848
    """
849
    if cpu_list == constants.CPU_PINNING_OFF:
850
      return constants.CPU_PINNING_ALL_KVM
851
    else:
852
      return sum(2 ** cpu for cpu in cpu_list)
853

    
854
  @classmethod
855
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
856
    """Change CPU affinity for running VM according to given CPU mask.
857

858
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
859
    @type cpu_mask: string
860
    @param process_id: process ID of KVM process. Used to pin entire VM
861
                       to physical CPUs.
862
    @type process_id: int
863
    @param thread_dict: map of virtual CPUs to KVM thread IDs
864
    @type thread_dict: dict int:int
865

866
    """
867
    # Convert the string CPU mask to a list of list of int's
868
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
869

    
870
    if len(cpu_list) == 1:
871
      all_cpu_mapping = cpu_list[0]
872
      if all_cpu_mapping == constants.CPU_PINNING_OFF:
873
        # If CPU pinning has 1 entry that's "all", then do nothing
874
        pass
875
      else:
876
        # If CPU pinning has one non-all entry, map the entire VM to
877
        # one set of physical CPUs
878
        cls._VerifyAffinityPackage()
879
        affinity.set_process_affinity_mask(
880
          process_id, cls._BuildAffinityCpuMask(all_cpu_mapping))
881
    else:
882
      # The number of vCPUs mapped should match the number of vCPUs
883
      # reported by KVM. This was already verified earlier, so
884
      # here only as a sanity check.
885
      assert len(thread_dict) == len(cpu_list)
886
      cls._VerifyAffinityPackage()
887

    
888
      # For each vCPU, map it to the proper list of physical CPUs
889
      for vcpu, i in zip(cpu_list, range(len(cpu_list))):
890
        affinity.set_process_affinity_mask(thread_dict[i],
891
                                           cls._BuildAffinityCpuMask(vcpu))
892

    
893
  def _GetVcpuThreadIds(self, instance_name):
894
    """Get a mapping of vCPU no. to thread IDs for the instance
895

896
    @type instance_name: string
897
    @param instance_name: instance in question
898
    @rtype: dictionary of int:int
899
    @return: a dictionary mapping vCPU numbers to thread IDs
900

901
    """
902
    result = {}
903
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
904
    for line in output.stdout.splitlines():
905
      match = self._CPU_INFO_RE.search(line)
906
      if not match:
907
        continue
908
      grp = map(int, match.groups())
909
      result[grp[0]] = grp[1]
910

    
911
    return result
912

    
913
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
914
    """Complete CPU pinning.
915

916
    @type instance_name: string
917
    @param instance_name: name of instance
918
    @type cpu_mask: string
919
    @param cpu_mask: CPU pinning mask as entered by user
920

921
    """
922
    # Get KVM process ID, to be used if need to pin entire VM
923
    _, pid, _ = self._InstancePidAlive(instance_name)
924
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
925
    thread_dict = self._GetVcpuThreadIds(instance_name)
926
    # Run CPU pinning, based on configured mask
927
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
928

    
929
  def ListInstances(self):
930
    """Get the list of running instances.
931

932
    We can do this by listing our live instances directory and
933
    checking whether the associated kvm process is still alive.
934

935
    """
936
    result = []
937
    for name in os.listdir(self._PIDS_DIR):
938
      if self._InstancePidAlive(name)[2]:
939
        result.append(name)
940
    return result
941

    
942
  def GetInstanceInfo(self, instance_name):
943
    """Get instance properties.
944

945
    @type instance_name: string
946
    @param instance_name: the instance name
947
    @rtype: tuple of strings
948
    @return: (name, id, memory, vcpus, stat, times)
949

950
    """
951
    _, pid, alive = self._InstancePidAlive(instance_name)
952
    if not alive:
953
      return None
954

    
955
    _, memory, vcpus = self._InstancePidInfo(pid)
956
    istat = "---b-"
957
    times = "0"
958

    
959
    try:
960
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
961
      qmp.connect()
962
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
963
      # Will fail if ballooning is not enabled, but we can then just resort to
964
      # the value above.
965
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
966
      memory = mem_bytes / 1048576
967
    except errors.HypervisorError:
968
      pass
969

    
970
    return (instance_name, pid, memory, vcpus, istat, times)
971

    
972
  def GetAllInstancesInfo(self):
973
    """Get properties of all instances.
974

975
    @return: list of tuples (name, id, memory, vcpus, stat, times)
976

977
    """
978
    data = []
979
    for name in os.listdir(self._PIDS_DIR):
980
      try:
981
        info = self.GetInstanceInfo(name)
982
      except errors.HypervisorError:
983
        # Ignore exceptions due to instances being shut down
984
        continue
985
      if info:
986
        data.append(info)
987
    return data
988

    
989
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused):
990
    """Generate KVM information to start an instance.
991

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

999
    """
1000
    # pylint: disable=R0914,R0915
1001
    _, v_major, v_min, _ = self._GetKVMVersion()
1002

    
1003
    pidfile = self._InstancePidFile(instance.name)
1004
    kvm = constants.KVM_PATH
1005
    kvm_cmd = [kvm]
1006
    # used just by the vnc server, if enabled
1007
    kvm_cmd.extend(["-name", instance.name])
1008
    kvm_cmd.extend(["-m", instance.beparams[constants.BE_MAXMEM]])
1009
    kvm_cmd.extend(["-smp", instance.beparams[constants.BE_VCPUS]])
1010
    kvm_cmd.extend(["-pidfile", pidfile])
1011
    kvm_cmd.extend(["-balloon", "virtio"])
1012
    kvm_cmd.extend(["-daemonize"])
1013
    if not instance.hvparams[constants.HV_ACPI]:
1014
      kvm_cmd.extend(["-no-acpi"])
1015
    if instance.hvparams[constants.HV_REBOOT_BEHAVIOR] == \
1016
        constants.INSTANCE_REBOOT_EXIT:
1017
      kvm_cmd.extend(["-no-reboot"])
1018

    
1019
    hvp = instance.hvparams
1020
    kernel_path = hvp[constants.HV_KERNEL_PATH]
1021
    if kernel_path:
1022
      boot_disk = boot_cdrom = boot_floppy = boot_network = False
1023
    else:
1024
      boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
1025
      boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
1026
      boot_floppy = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_FLOPPY
1027
      boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
1028

    
1029
    self.ValidateParameters(hvp)
1030

    
1031
    if startup_paused:
1032
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1033

    
1034
    if hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED:
1035
      kvm_cmd.extend(["-enable-kvm"])
1036
    elif hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED:
1037
      kvm_cmd.extend(["-disable-kvm"])
1038

    
1039
    if boot_network:
1040
      kvm_cmd.extend(["-boot", "n"])
1041

    
1042
    # whether this is an older KVM version that uses the boot=on flag
1043
    # on devices
1044
    needs_boot_flag = (v_major, v_min) < (0, 14)
1045

    
1046
    disk_type = hvp[constants.HV_DISK_TYPE]
1047
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
1048
      if_val = ",if=virtio"
1049
    else:
1050
      if_val = ",if=%s" % disk_type
1051
    # Cache mode
1052
    disk_cache = hvp[constants.HV_DISK_CACHE]
1053
    if instance.disk_template in constants.DTS_EXT_MIRROR:
1054
      if disk_cache != "none":
1055
        # TODO: make this a hard error, instead of a silent overwrite
1056
        logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
1057
                        " to prevent shared storage corruption on migration",
1058
                        disk_cache)
1059
      cache_val = ",cache=none"
1060
    elif disk_cache != constants.HT_CACHE_DEFAULT:
1061
      cache_val = ",cache=%s" % disk_cache
1062
    else:
1063
      cache_val = ""
1064
    for cfdev, dev_path in block_devices:
1065
      if cfdev.mode != constants.DISK_RDWR:
1066
        raise errors.HypervisorError("Instance has read-only disks which"
1067
                                     " are not supported by KVM")
1068
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
1069
      boot_val = ""
1070
      if boot_disk:
1071
        kvm_cmd.extend(["-boot", "c"])
1072
        boot_disk = False
1073
        if needs_boot_flag and disk_type != constants.HT_DISK_IDE:
1074
          boot_val = ",boot=on"
1075

    
1076
      drive_val = "file=%s,format=raw%s%s%s" % (dev_path, if_val, boot_val,
1077
                                                cache_val)
1078
      kvm_cmd.extend(["-drive", drive_val])
1079

    
1080
    #Now we can specify a different device type for CDROM devices.
1081
    cdrom_disk_type = hvp[constants.HV_KVM_CDROM_DISK_TYPE]
1082
    if not cdrom_disk_type:
1083
      cdrom_disk_type = disk_type
1084

    
1085
    iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
1086
    if iso_image:
1087
      options = ",format=raw,media=cdrom"
1088
      # set cdrom 'if' type
1089
      if boot_cdrom:
1090
        actual_cdrom_type = constants.HT_DISK_IDE
1091
      elif cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1092
        actual_cdrom_type = "virtio"
1093
      else:
1094
        actual_cdrom_type = cdrom_disk_type
1095
      if_val = ",if=%s" % actual_cdrom_type
1096
      # set boot flag, if needed
1097
      boot_val = ""
1098
      if boot_cdrom:
1099
        kvm_cmd.extend(["-boot", "d"])
1100
        if needs_boot_flag:
1101
          boot_val = ",boot=on"
1102
      # and finally build the entire '-drive' value
1103
      drive_val = "file=%s%s%s%s" % (iso_image, options, if_val, boot_val)
1104
      kvm_cmd.extend(["-drive", drive_val])
1105

    
1106
    iso_image2 = hvp[constants.HV_KVM_CDROM2_IMAGE_PATH]
1107
    if iso_image2:
1108
      options = ",format=raw,media=cdrom"
1109
      if cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1110
        if_val = ",if=virtio"
1111
      else:
1112
        if_val = ",if=%s" % cdrom_disk_type
1113
      drive_val = "file=%s%s%s" % (iso_image2, options, if_val)
1114
      kvm_cmd.extend(["-drive", drive_val])
1115

    
1116
    floppy_image = hvp[constants.HV_KVM_FLOPPY_IMAGE_PATH]
1117
    if floppy_image:
1118
      options = ",format=raw,media=disk"
1119
      if boot_floppy:
1120
        kvm_cmd.extend(["-boot", "a"])
1121
        options = "%s,boot=on" % options
1122
      if_val = ",if=floppy"
1123
      options = "%s%s" % (options, if_val)
1124
      drive_val = "file=%s%s" % (floppy_image, options)
1125
      kvm_cmd.extend(["-drive", drive_val])
1126

    
1127
    if kernel_path:
1128
      kvm_cmd.extend(["-kernel", kernel_path])
1129
      initrd_path = hvp[constants.HV_INITRD_PATH]
1130
      if initrd_path:
1131
        kvm_cmd.extend(["-initrd", initrd_path])
1132
      root_append = ["root=%s" % hvp[constants.HV_ROOT_PATH],
1133
                     hvp[constants.HV_KERNEL_ARGS]]
1134
      if hvp[constants.HV_SERIAL_CONSOLE]:
1135
        root_append.append("console=ttyS0,38400")
1136
      kvm_cmd.extend(["-append", " ".join(root_append)])
1137

    
1138
    mem_path = hvp[constants.HV_MEM_PATH]
1139
    if mem_path:
1140
      kvm_cmd.extend(["-mem-path", mem_path, "-mem-prealloc"])
1141

    
1142
    monitor_dev = ("unix:%s,server,nowait" %
1143
                   self._InstanceMonitor(instance.name))
1144
    kvm_cmd.extend(["-monitor", monitor_dev])
1145
    if hvp[constants.HV_SERIAL_CONSOLE]:
1146
      serial_dev = ("unix:%s,server,nowait" %
1147
                    self._InstanceSerial(instance.name))
1148
      kvm_cmd.extend(["-serial", serial_dev])
1149
    else:
1150
      kvm_cmd.extend(["-serial", "none"])
1151

    
1152
    mouse_type = hvp[constants.HV_USB_MOUSE]
1153
    vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
1154
    spice_bind = hvp[constants.HV_KVM_SPICE_BIND]
1155
    spice_ip_version = None
1156

    
1157
    if mouse_type:
1158
      kvm_cmd.extend(["-usb"])
1159
      kvm_cmd.extend(["-usbdevice", mouse_type])
1160
    elif vnc_bind_address:
1161
      kvm_cmd.extend(["-usbdevice", constants.HT_MOUSE_TABLET])
1162

    
1163
    if vnc_bind_address:
1164
      if netutils.IP4Address.IsValid(vnc_bind_address):
1165
        if instance.network_port > constants.VNC_BASE_PORT:
1166
          display = instance.network_port - constants.VNC_BASE_PORT
1167
          if vnc_bind_address == constants.IP4_ADDRESS_ANY:
1168
            vnc_arg = ":%d" % (display)
1169
          else:
1170
            vnc_arg = "%s:%d" % (vnc_bind_address, display)
1171
        else:
1172
          logging.error("Network port is not a valid VNC display (%d < %d)."
1173
                        " Not starting VNC", instance.network_port,
1174
                        constants.VNC_BASE_PORT)
1175
          vnc_arg = "none"
1176

    
1177
        # Only allow tls and other option when not binding to a file, for now.
1178
        # kvm/qemu gets confused otherwise about the filename to use.
1179
        vnc_append = ""
1180
        if hvp[constants.HV_VNC_TLS]:
1181
          vnc_append = "%s,tls" % vnc_append
1182
          if hvp[constants.HV_VNC_X509_VERIFY]:
1183
            vnc_append = "%s,x509verify=%s" % (vnc_append,
1184
                                               hvp[constants.HV_VNC_X509])
1185
          elif hvp[constants.HV_VNC_X509]:
1186
            vnc_append = "%s,x509=%s" % (vnc_append,
1187
                                         hvp[constants.HV_VNC_X509])
1188
        if hvp[constants.HV_VNC_PASSWORD_FILE]:
1189
          vnc_append = "%s,password" % vnc_append
1190

    
1191
        vnc_arg = "%s%s" % (vnc_arg, vnc_append)
1192

    
1193
      else:
1194
        vnc_arg = "unix:%s/%s.vnc" % (vnc_bind_address, instance.name)
1195

    
1196
      kvm_cmd.extend(["-vnc", vnc_arg])
1197
    elif spice_bind:
1198
      # FIXME: this is wrong here; the iface ip address differs
1199
      # between systems, so it should be done in _ExecuteKVMRuntime
1200
      if netutils.IsValidInterface(spice_bind):
1201
        # The user specified a network interface, we have to figure out the IP
1202
        # address.
1203
        addresses = netutils.GetInterfaceIpAddresses(spice_bind)
1204
        spice_ip_version = hvp[constants.HV_KVM_SPICE_IP_VERSION]
1205

    
1206
        # if the user specified an IP version and the interface does not
1207
        # have that kind of IP addresses, throw an exception
1208
        if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1209
          if not addresses[spice_ip_version]:
1210
            raise errors.HypervisorError("spice: unable to get an IPv%s address"
1211
                                         " for %s" % (spice_ip_version,
1212
                                                      spice_bind))
1213

    
1214
        # the user did not specify an IP version, we have to figure it out
1215
        elif (addresses[constants.IP4_VERSION] and
1216
              addresses[constants.IP6_VERSION]):
1217
          # we have both ipv4 and ipv6, let's use the cluster default IP
1218
          # version
1219
          cluster_family = ssconf.SimpleStore().GetPrimaryIPFamily()
1220
          spice_ip_version = \
1221
            netutils.IPAddress.GetVersionFromAddressFamily(cluster_family)
1222
        elif addresses[constants.IP4_VERSION]:
1223
          spice_ip_version = constants.IP4_VERSION
1224
        elif addresses[constants.IP6_VERSION]:
1225
          spice_ip_version = constants.IP6_VERSION
1226
        else:
1227
          raise errors.HypervisorError("spice: unable to get an IP address"
1228
                                       " for %s" % (spice_bind))
1229

    
1230
        spice_address = addresses[spice_ip_version][0]
1231

    
1232
      else:
1233
        # spice_bind is known to be a valid IP address, because
1234
        # ValidateParameters checked it.
1235
        spice_address = spice_bind
1236

    
1237
      spice_arg = "addr=%s" % spice_address
1238
      if hvp[constants.HV_KVM_SPICE_USE_TLS]:
1239
        spice_arg = ("%s,tls-port=%s,x509-cacert-file=%s" %
1240
                     (spice_arg, instance.network_port,
1241
                      pathutils.SPICE_CACERT_FILE))
1242
        spice_arg = ("%s,x509-key-file=%s,x509-cert-file=%s" %
1243
                     (spice_arg, pathutils.SPICE_CERT_FILE,
1244
                      pathutils.SPICE_CERT_FILE))
1245
        tls_ciphers = hvp[constants.HV_KVM_SPICE_TLS_CIPHERS]
1246
        if tls_ciphers:
1247
          spice_arg = "%s,tls-ciphers=%s" % (spice_arg, tls_ciphers)
1248
      else:
1249
        spice_arg = "%s,port=%s" % (spice_arg, instance.network_port)
1250

    
1251
      if not hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]:
1252
        spice_arg = "%s,disable-ticketing" % spice_arg
1253

    
1254
      if spice_ip_version:
1255
        spice_arg = "%s,ipv%s" % (spice_arg, spice_ip_version)
1256

    
1257
      # Image compression options
1258
      img_lossless = hvp[constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR]
1259
      img_jpeg = hvp[constants.HV_KVM_SPICE_JPEG_IMG_COMPR]
1260
      img_zlib_glz = hvp[constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR]
1261
      if img_lossless:
1262
        spice_arg = "%s,image-compression=%s" % (spice_arg, img_lossless)
1263
      if img_jpeg:
1264
        spice_arg = "%s,jpeg-wan-compression=%s" % (spice_arg, img_jpeg)
1265
      if img_zlib_glz:
1266
        spice_arg = "%s,zlib-glz-wan-compression=%s" % (spice_arg, img_zlib_glz)
1267

    
1268
      # Video stream detection
1269
      video_streaming = hvp[constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION]
1270
      if video_streaming:
1271
        spice_arg = "%s,streaming-video=%s" % (spice_arg, video_streaming)
1272

    
1273
      # Audio compression, by default in qemu-kvm it is on
1274
      if not hvp[constants.HV_KVM_SPICE_AUDIO_COMPR]:
1275
        spice_arg = "%s,playback-compression=off" % spice_arg
1276
      if not hvp[constants.HV_KVM_SPICE_USE_VDAGENT]:
1277
        spice_arg = "%s,agent-mouse=off" % spice_arg
1278
      else:
1279
        # Enable the spice agent communication channel between the host and the
1280
        # agent.
1281
        kvm_cmd.extend(["-device", "virtio-serial-pci"])
1282
        kvm_cmd.extend(["-device", "virtserialport,chardev=spicechannel0,"
1283
                                                   "name=com.redhat.spice.0"])
1284
        kvm_cmd.extend(["-chardev", "spicevmc,id=spicechannel0,name=vdagent"])
1285

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

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

    
1292
    else:
1293
      kvm_cmd.extend(["-nographic"])
1294

    
1295
    if hvp[constants.HV_USE_LOCALTIME]:
1296
      kvm_cmd.extend(["-localtime"])
1297

    
1298
    if hvp[constants.HV_KVM_USE_CHROOT]:
1299
      kvm_cmd.extend(["-chroot", self._InstanceChrootDir(instance.name)])
1300

    
1301
    # Add qemu-KVM -cpu param
1302
    if hvp[constants.HV_CPU_TYPE]:
1303
      kvm_cmd.extend(["-cpu", hvp[constants.HV_CPU_TYPE]])
1304

    
1305
    # Save the current instance nics, but defer their expansion as parameters,
1306
    # as we'll need to generate executable temp files for them.
1307
    kvm_nics = instance.nics
1308
    hvparams = hvp
1309

    
1310
    return (kvm_cmd, kvm_nics, hvparams)
1311

    
1312
  def _WriteKVMRuntime(self, instance_name, data):
1313
    """Write an instance's KVM runtime
1314

1315
    """
1316
    try:
1317
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1318
                      data=data)
1319
    except EnvironmentError, err:
1320
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1321

    
1322
  def _ReadKVMRuntime(self, instance_name):
1323
    """Read an instance's KVM runtime
1324

1325
    """
1326
    try:
1327
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1328
    except EnvironmentError, err:
1329
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1330
    return file_content
1331

    
1332
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1333
    """Save an instance's KVM runtime
1334

1335
    """
1336
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
1337
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1338
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
1339
    self._WriteKVMRuntime(instance.name, serialized_form)
1340

    
1341
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1342
    """Load an instance's KVM runtime
1343

1344
    """
1345
    if not serialized_runtime:
1346
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1347
    loaded_runtime = serializer.Load(serialized_runtime)
1348
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
1349
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
1350
    return (kvm_cmd, kvm_nics, hvparams)
1351

    
1352
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1353
    """Run the KVM cmd and check for errors
1354

1355
    @type name: string
1356
    @param name: instance name
1357
    @type kvm_cmd: list of strings
1358
    @param kvm_cmd: runcmd input for kvm
1359
    @type tap_fds: list of int
1360
    @param tap_fds: fds of tap devices opened by Ganeti
1361

1362
    """
1363
    try:
1364
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1365
    finally:
1366
      for fd in tap_fds:
1367
        utils_wrapper.CloseFdNoError(fd)
1368

    
1369
    if result.failed:
1370
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1371
                                   (name, result.fail_reason, result.output))
1372
    if not self._InstancePidAlive(name)[2]:
1373
      raise errors.HypervisorError("Failed to start instance %s" % name)
1374

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

1378
    @type incoming: tuple of strings
1379
    @param incoming: (target_host_ip, port)
1380

1381
    """
1382
    # Small _ExecuteKVMRuntime hv parameters programming howto:
1383
    #  - conf_hvp contains the parameters as configured on ganeti. they might
1384
    #    have changed since the instance started; only use them if the change
1385
    #    won't affect the inside of the instance (which hasn't been rebooted).
1386
    #  - up_hvp contains the parameters as they were when the instance was
1387
    #    started, plus any new parameter which has been added between ganeti
1388
    #    versions: it is paramount that those default to a value which won't
1389
    #    affect the inside of the instance as well.
1390
    conf_hvp = instance.hvparams
1391
    name = instance.name
1392
    self._CheckDown(name)
1393

    
1394
    temp_files = []
1395

    
1396
    kvm_cmd, kvm_nics, up_hvp = kvm_runtime
1397
    up_hvp = objects.FillDict(conf_hvp, up_hvp)
1398

    
1399
    _, v_major, v_min, _ = self._GetKVMVersion()
1400

    
1401
    # We know it's safe to run as a different user upon migration, so we'll use
1402
    # the latest conf, from conf_hvp.
1403
    security_model = conf_hvp[constants.HV_SECURITY_MODEL]
1404
    if security_model == constants.HT_SM_USER:
1405
      kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
1406

    
1407
    keymap = conf_hvp[constants.HV_KEYMAP]
1408
    if keymap:
1409
      keymap_path = self._InstanceKeymapFile(name)
1410
      # If a keymap file is specified, KVM won't use its internal defaults. By
1411
      # first including the "en-us" layout, an error on loading the actual
1412
      # layout (e.g. because it can't be found) won't lead to a non-functional
1413
      # keyboard. A keyboard with incorrect keys is still better than none.
1414
      utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
1415
      kvm_cmd.extend(["-k", keymap_path])
1416

    
1417
    # We have reasons to believe changing something like the nic driver/type
1418
    # upon migration won't exactly fly with the instance kernel, so for nic
1419
    # related parameters we'll use up_hvp
1420
    tapfds = []
1421
    taps = []
1422
    if not kvm_nics:
1423
      kvm_cmd.extend(["-net", "none"])
1424
    else:
1425
      vnet_hdr = False
1426
      tap_extra = ""
1427
      nic_type = up_hvp[constants.HV_NIC_TYPE]
1428
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
1429
        # From version 0.12.0, kvm uses a new sintax for network configuration.
1430
        if (v_major, v_min) >= (0, 12):
1431
          nic_model = "virtio-net-pci"
1432
          vnet_hdr = True
1433
        else:
1434
          nic_model = "virtio"
1435

    
1436
        if up_hvp[constants.HV_VHOST_NET]:
1437
          # vhost_net is only available from version 0.13.0 or newer
1438
          if (v_major, v_min) >= (0, 13):
1439
            tap_extra = ",vhost=on"
1440
          else:
1441
            raise errors.HypervisorError("vhost_net is configured"
1442
                                         " but it is not available")
1443
      else:
1444
        nic_model = nic_type
1445

    
1446
      for nic_seq, nic in enumerate(kvm_nics):
1447
        tapname, tapfd = _OpenTap(vnet_hdr)
1448
        tapfds.append(tapfd)
1449
        taps.append(tapname)
1450
        if (v_major, v_min) >= (0, 12):
1451
          nic_val = "%s,mac=%s,netdev=netdev%s" % (nic_model, nic.mac, nic_seq)
1452
          tap_val = "type=tap,id=netdev%s,fd=%d%s" % (nic_seq, tapfd, tap_extra)
1453
          kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
1454
        else:
1455
          nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq,
1456
                                                         nic.mac, nic_model)
1457
          tap_val = "tap,vlan=%s,fd=%d" % (nic_seq, tapfd)
1458
          kvm_cmd.extend(["-net", tap_val, "-net", nic_val])
1459

    
1460
    if incoming:
1461
      target, port = incoming
1462
      kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])
1463

    
1464
    # Changing the vnc password doesn't bother the guest that much. At most it
1465
    # will surprise people who connect to it. Whether positively or negatively
1466
    # it's debatable.
1467
    vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
1468
    vnc_pwd = None
1469
    if vnc_pwd_file:
1470
      try:
1471
        vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
1472
      except EnvironmentError, err:
1473
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
1474
                                     % (vnc_pwd_file, err))
1475

    
1476
    if conf_hvp[constants.HV_KVM_USE_CHROOT]:
1477
      utils.EnsureDirs([(self._InstanceChrootDir(name),
1478
                         constants.SECURE_DIR_MODE)])
1479

    
1480
    # Automatically enable QMP if version is >= 0.14
1481
    if (v_major, v_min) >= (0, 14):
1482
      logging.debug("Enabling QMP")
1483
      kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
1484
                      self._InstanceQmpMonitor(instance.name)])
1485

    
1486
    # Configure the network now for starting instances and bridged interfaces,
1487
    # during FinalizeMigration for incoming instances' routed interfaces
1488
    for nic_seq, nic in enumerate(kvm_nics):
1489
      if (incoming and
1490
          nic.nicparams[constants.NIC_MODE] != constants.NIC_MODE_BRIDGED):
1491
        continue
1492
      self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
1493

    
1494
    # CPU affinity requires kvm to start paused, so we set this flag if the
1495
    # instance is not already paused and if we are not going to accept a
1496
    # migrating instance. In the latter case, pausing is not needed.
1497
    start_kvm_paused = not (_KVM_START_PAUSED_FLAG in kvm_cmd) and not incoming
1498
    if start_kvm_paused:
1499
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1500

    
1501
    # Note: CPU pinning is using up_hvp since changes take effect
1502
    # during instance startup anyway, and to avoid problems when soft
1503
    # rebooting the instance.
1504
    cpu_pinning = False
1505
    if up_hvp.get(constants.HV_CPU_MASK, None):
1506
      cpu_pinning = True
1507

    
1508
    if security_model == constants.HT_SM_POOL:
1509
      ss = ssconf.SimpleStore()
1510
      uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
1511
      all_uids = set(uidpool.ExpandUidPool(uid_pool))
1512
      uid = uidpool.RequestUnusedUid(all_uids)
1513
      try:
1514
        username = pwd.getpwuid(uid.GetUid()).pw_name
1515
        kvm_cmd.extend(["-runas", username])
1516
        self._RunKVMCmd(name, kvm_cmd, tapfds)
1517
      except:
1518
        uidpool.ReleaseUid(uid)
1519
        raise
1520
      else:
1521
        uid.Unlock()
1522
        utils.WriteFile(self._InstanceUidFile(name), data=uid.AsStr())
1523
    else:
1524
      self._RunKVMCmd(name, kvm_cmd, tapfds)
1525

    
1526
    utils.EnsureDirs([(self._InstanceNICDir(instance.name),
1527
                     constants.RUN_DIRS_MODE)])
1528
    for nic_seq, tap in enumerate(taps):
1529
      utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
1530
                      data=tap)
1531

    
1532
    if vnc_pwd:
1533
      change_cmd = "change vnc password %s" % vnc_pwd
1534
      self._CallMonitorCommand(instance.name, change_cmd)
1535

    
1536
    # Setting SPICE password. We are not vulnerable to malicious passwordless
1537
    # connection attempts because SPICE by default does not allow connections
1538
    # if neither a password nor the "disable_ticketing" options are specified.
1539
    # As soon as we send the password via QMP, that password is a valid ticket
1540
    # for connection.
1541
    spice_password_file = conf_hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]
1542
    if spice_password_file:
1543
      spice_pwd = ""
1544
      try:
1545
        spice_pwd = utils.ReadOneLineFile(spice_password_file, strict=True)
1546
      except EnvironmentError, err:
1547
        raise errors.HypervisorError("Failed to open SPICE password file %s: %s"
1548
                                     % (spice_password_file, err))
1549

    
1550
      qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
1551
      qmp.connect()
1552
      arguments = {
1553
          "protocol": "spice",
1554
          "password": spice_pwd,
1555
      }
1556
      qmp.Execute("set_password", arguments)
1557

    
1558
    for filename in temp_files:
1559
      utils.RemoveFile(filename)
1560

    
1561
    # If requested, set CPU affinity and resume instance execution
1562
    if cpu_pinning:
1563
      self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK])
1564

    
1565
    start_memory = self._InstanceStartupMemory(instance)
1566
    if start_memory < instance.beparams[constants.BE_MAXMEM]:
1567
      self.BalloonInstanceMemory(instance, start_memory)
1568

    
1569
    if start_kvm_paused:
1570
      # To control CPU pinning, ballooning, and vnc/spice passwords
1571
      # the VM was started in a frozen state. If freezing was not
1572
      # explicitly requested resume the vm status.
1573
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1574

    
1575
  def StartInstance(self, instance, block_devices, startup_paused):
1576
    """Start an instance.
1577

1578
    """
1579
    self._CheckDown(instance.name)
1580
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1581
                                           startup_paused)
1582
    self._SaveKVMRuntime(instance, kvm_runtime)
1583
    self._ExecuteKVMRuntime(instance, kvm_runtime)
1584

    
1585
  def _CallMonitorCommand(self, instance_name, command):
1586
    """Invoke a command on the instance monitor.
1587

1588
    """
1589
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1590
             (utils.ShellQuote(command),
1591
              constants.SOCAT_PATH,
1592
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1593
    result = utils.RunCmd(socat)
1594
    if result.failed:
1595
      msg = ("Failed to send command '%s' to instance %s."
1596
             " output: %s, error: %s, fail_reason: %s" %
1597
             (command, instance_name,
1598
              result.stdout, result.stderr, result.fail_reason))
1599
      raise errors.HypervisorError(msg)
1600

    
1601
    return result
1602

    
1603
  @classmethod
1604
  def _ParseKVMVersion(cls, text):
1605
    """Parse the KVM version from the --help output.
1606

1607
    @type text: string
1608
    @param text: output of kvm --help
1609
    @return: (version, v_maj, v_min, v_rev)
1610
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1611

1612
    """
1613
    match = cls._VERSION_RE.search(text.splitlines()[0])
1614
    if not match:
1615
      raise errors.HypervisorError("Unable to get KVM version")
1616

    
1617
    v_all = match.group(0)
1618
    v_maj = int(match.group(1))
1619
    v_min = int(match.group(2))
1620
    if match.group(4):
1621
      v_rev = int(match.group(4))
1622
    else:
1623
      v_rev = 0
1624
    return (v_all, v_maj, v_min, v_rev)
1625

    
1626
  @classmethod
1627
  def _GetKVMVersion(cls):
1628
    """Return the installed KVM version.
1629

1630
    @return: (version, v_maj, v_min, v_rev)
1631
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1632

1633
    """
1634
    result = utils.RunCmd([constants.KVM_PATH, "--help"])
1635
    if result.failed:
1636
      raise errors.HypervisorError("Unable to get KVM version")
1637
    return cls._ParseKVMVersion(result.output)
1638

    
1639
  def StopInstance(self, instance, force=False, retry=False, name=None):
1640
    """Stop an instance.
1641

1642
    """
1643
    if name is not None and not force:
1644
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
1645
    if name is None:
1646
      name = instance.name
1647
      acpi = instance.hvparams[constants.HV_ACPI]
1648
    else:
1649
      acpi = False
1650
    _, pid, alive = self._InstancePidAlive(name)
1651
    if pid > 0 and alive:
1652
      if force or not acpi:
1653
        utils.KillProcess(pid)
1654
      else:
1655
        self._CallMonitorCommand(name, "system_powerdown")
1656

    
1657
  def CleanupInstance(self, instance_name):
1658
    """Cleanup after a stopped instance
1659

1660
    """
1661
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1662
    if pid > 0 and alive:
1663
      raise errors.HypervisorError("Cannot cleanup a live instance")
1664
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1665

    
1666
  def RebootInstance(self, instance):
1667
    """Reboot an instance.
1668

1669
    """
1670
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
1671
    # socket the instance will stop, but now power up again. So we'll resort
1672
    # to shutdown and restart.
1673
    _, _, alive = self._InstancePidAlive(instance.name)
1674
    if not alive:
1675
      raise errors.HypervisorError("Failed to reboot instance %s:"
1676
                                   " not running" % instance.name)
1677
    # StopInstance will delete the saved KVM runtime so:
1678
    # ...first load it...
1679
    kvm_runtime = self._LoadKVMRuntime(instance)
1680
    # ...now we can safely call StopInstance...
1681
    if not self.StopInstance(instance):
1682
      self.StopInstance(instance, force=True)
1683
    # ...and finally we can save it again, and execute it...
1684
    self._SaveKVMRuntime(instance, kvm_runtime)
1685
    self._ExecuteKVMRuntime(instance, kvm_runtime)
1686

    
1687
  def MigrationInfo(self, instance):
1688
    """Get instance information to perform a migration.
1689

1690
    @type instance: L{objects.Instance}
1691
    @param instance: instance to be migrated
1692
    @rtype: string
1693
    @return: content of the KVM runtime file
1694

1695
    """
1696
    return self._ReadKVMRuntime(instance.name)
1697

    
1698
  def AcceptInstance(self, instance, info, target):
1699
    """Prepare to accept an instance.
1700

1701
    @type instance: L{objects.Instance}
1702
    @param instance: instance to be accepted
1703
    @type info: string
1704
    @param info: content of the KVM runtime file on the source node
1705
    @type target: string
1706
    @param target: target host (usually ip), on this node
1707

1708
    """
1709
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1710
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1711
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
1712

    
1713
  def FinalizeMigrationDst(self, instance, info, success):
1714
    """Finalize the instance migration on the target node.
1715

1716
    Stop the incoming mode KVM.
1717

1718
    @type instance: L{objects.Instance}
1719
    @param instance: instance whose migration is being finalized
1720

1721
    """
1722
    if success:
1723
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1724
      kvm_nics = kvm_runtime[1]
1725

    
1726
      for nic_seq, nic in enumerate(kvm_nics):
1727
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1728
          # Bridged interfaces have already been configured
1729
          continue
1730
        try:
1731
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
1732
        except EnvironmentError, err:
1733
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
1734
                          instance.name, nic_seq, str(err))
1735
          continue
1736
        try:
1737
          self._ConfigureNIC(instance, nic_seq, nic, tap)
1738
        except errors.HypervisorError, err:
1739
          logging.warning(str(err))
1740

    
1741
      self._WriteKVMRuntime(instance.name, info)
1742
    else:
1743
      self.StopInstance(instance, force=True)
1744

    
1745
  def MigrateInstance(self, instance, target, live):
1746
    """Migrate an instance to a target node.
1747

1748
    The migration will not be attempted if the instance is not
1749
    currently running.
1750

1751
    @type instance: L{objects.Instance}
1752
    @param instance: the instance to be migrated
1753
    @type target: string
1754
    @param target: ip address of the target node
1755
    @type live: boolean
1756
    @param live: perform a live migration
1757

1758
    """
1759
    instance_name = instance.name
1760
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
1761
    _, _, alive = self._InstancePidAlive(instance_name)
1762
    if not alive:
1763
      raise errors.HypervisorError("Instance not running, cannot migrate")
1764

    
1765
    if not live:
1766
      self._CallMonitorCommand(instance_name, "stop")
1767

    
1768
    migrate_command = ("migrate_set_speed %dm" %
1769
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1770
    self._CallMonitorCommand(instance_name, migrate_command)
1771

    
1772
    migrate_command = ("migrate_set_downtime %dms" %
1773
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
1774
    self._CallMonitorCommand(instance_name, migrate_command)
1775

    
1776
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
1777
    self._CallMonitorCommand(instance_name, migrate_command)
1778

    
1779
  def FinalizeMigrationSource(self, instance, success, live):
1780
    """Finalize the instance migration on the source node.
1781

1782
    @type instance: L{objects.Instance}
1783
    @param instance: the instance that was migrated
1784
    @type success: bool
1785
    @param success: whether the migration succeeded or not
1786
    @type live: bool
1787
    @param live: whether the user requested a live migration or not
1788

1789
    """
1790
    if success:
1791
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
1792
      utils.KillProcess(pid)
1793
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
1794
    elif live:
1795
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1796

    
1797
  def GetMigrationStatus(self, instance):
1798
    """Get the migration status
1799

1800
    @type instance: L{objects.Instance}
1801
    @param instance: the instance that is being migrated
1802
    @rtype: L{objects.MigrationStatus}
1803
    @return: the status of the current migration (one of
1804
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
1805
             progress info that can be retrieved from the hypervisor
1806

1807
    """
1808
    info_command = "info migrate"
1809
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
1810
      result = self._CallMonitorCommand(instance.name, info_command)
1811
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
1812
      if not match:
1813
        if not result.stdout:
1814
          logging.info("KVM: empty 'info migrate' result")
1815
        else:
1816
          logging.warning("KVM: unknown 'info migrate' result: %s",
1817
                          result.stdout)
1818
      else:
1819
        status = match.group(1)
1820
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
1821
          migration_status = objects.MigrationStatus(status=status)
1822
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
1823
          if match:
1824
            migration_status.transferred_ram = match.group("transferred")
1825
            migration_status.total_ram = match.group("total")
1826

    
1827
          return migration_status
1828

    
1829
        logging.warning("KVM: unknown migration status '%s'", status)
1830

    
1831
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1832

    
1833
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
1834

    
1835
  def BalloonInstanceMemory(self, instance, mem):
1836
    """Balloon an instance memory to a certain value.
1837

1838
    @type instance: L{objects.Instance}
1839
    @param instance: instance to be accepted
1840
    @type mem: int
1841
    @param mem: actual memory size to use for instance runtime
1842

1843
    """
1844
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
1845

    
1846
  def GetNodeInfo(self):
1847
    """Return information about the node.
1848

1849
    @return: a dict with the following keys (values in MiB):
1850
          - memory_total: the total memory size on the node
1851
          - memory_free: the available memory on the node for instances
1852
          - memory_dom0: the memory used by the node itself, if available
1853
          - hv_version: the hypervisor version in the form (major, minor,
1854
                        revision)
1855

1856
    """
1857
    result = self.GetLinuxNodeInfo()
1858
    _, v_major, v_min, v_rev = self._GetKVMVersion()
1859
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
1860
    return result
1861

    
1862
  @classmethod
1863
  def GetInstanceConsole(cls, instance, hvparams, beparams):
1864
    """Return a command for connecting to the console of an instance.
1865

1866
    """
1867
    if hvparams[constants.HV_SERIAL_CONSOLE]:
1868
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
1869
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
1870
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
1871
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
1872
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
1873
      return objects.InstanceConsole(instance=instance.name,
1874
                                     kind=constants.CONS_SSH,
1875
                                     host=instance.primary_node,
1876
                                     user=constants.SSH_CONSOLE_USER,
1877
                                     command=cmd)
1878

    
1879
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
1880
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
1881
      display = instance.network_port - constants.VNC_BASE_PORT
1882
      return objects.InstanceConsole(instance=instance.name,
1883
                                     kind=constants.CONS_VNC,
1884
                                     host=vnc_bind_address,
1885
                                     port=instance.network_port,
1886
                                     display=display)
1887

    
1888
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
1889
    if spice_bind:
1890
      return objects.InstanceConsole(instance=instance.name,
1891
                                     kind=constants.CONS_SPICE,
1892
                                     host=spice_bind,
1893
                                     port=instance.network_port)
1894

    
1895
    return objects.InstanceConsole(instance=instance.name,
1896
                                   kind=constants.CONS_MESSAGE,
1897
                                   message=("No serial shell for instance %s" %
1898
                                            instance.name))
1899

    
1900
  def Verify(self):
1901
    """Verify the hypervisor.
1902

1903
    Check that the binary exists.
1904

1905
    """
1906
    if not os.path.exists(constants.KVM_PATH):
1907
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
1908
    if not os.path.exists(constants.SOCAT_PATH):
1909
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
1910

    
1911
  @classmethod
1912
  def CheckParameterSyntax(cls, hvparams):
1913
    """Check the given parameters for validity.
1914

1915
    @type hvparams:  dict
1916
    @param hvparams: dictionary with parameter names/value
1917
    @raise errors.HypervisorError: when a parameter is not valid
1918

1919
    """
1920
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
1921

    
1922
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
1923
    if kernel_path:
1924
      if not hvparams[constants.HV_ROOT_PATH]:
1925
        raise errors.HypervisorError("Need a root partition for the instance,"
1926
                                     " if a kernel is defined")
1927

    
1928
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
1929
        not hvparams[constants.HV_VNC_X509]):
1930
      raise errors.HypervisorError("%s must be defined, if %s is" %
1931
                                   (constants.HV_VNC_X509,
1932
                                    constants.HV_VNC_X509_VERIFY))
1933

    
1934
    boot_order = hvparams[constants.HV_BOOT_ORDER]
1935
    if (boot_order == constants.HT_BO_CDROM and
1936
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
1937
      raise errors.HypervisorError("Cannot boot from cdrom without an"
1938
                                   " ISO path")
1939

    
1940
    security_model = hvparams[constants.HV_SECURITY_MODEL]
1941
    if security_model == constants.HT_SM_USER:
1942
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
1943
        raise errors.HypervisorError("A security domain (user to run kvm as)"
1944
                                     " must be specified")
1945
    elif (security_model == constants.HT_SM_NONE or
1946
          security_model == constants.HT_SM_POOL):
1947
      if hvparams[constants.HV_SECURITY_DOMAIN]:
1948
        raise errors.HypervisorError("Cannot have a security domain when the"
1949
                                     " security model is 'none' or 'pool'")
1950

    
1951
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
1952
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
1953
    if spice_bind:
1954
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1955
        # if an IP version is specified, the spice_bind parameter must be an
1956
        # IP of that family
1957
        if (netutils.IP4Address.IsValid(spice_bind) and
1958
            spice_ip_version != constants.IP4_VERSION):
1959
          raise errors.HypervisorError("spice: got an IPv4 address (%s), but"
1960
                                       " the specified IP version is %s" %
1961
                                       (spice_bind, spice_ip_version))
1962

    
1963
        if (netutils.IP6Address.IsValid(spice_bind) and
1964
            spice_ip_version != constants.IP6_VERSION):
1965
          raise errors.HypervisorError("spice: got an IPv6 address (%s), but"
1966
                                       " the specified IP version is %s" %
1967
                                       (spice_bind, spice_ip_version))
1968
    else:
1969
      # All the other SPICE parameters depend on spice_bind being set. Raise an
1970
      # error if any of them is set without it.
1971
      for param in _SPICE_ADDITIONAL_PARAMS:
1972
        if hvparams[param]:
1973
          raise errors.HypervisorError("spice: %s requires %s to be set" %
1974
                                       (param, constants.HV_KVM_SPICE_BIND))
1975

    
1976
  @classmethod
1977
  def ValidateParameters(cls, hvparams):
1978
    """Check the given parameters for validity.
1979

1980
    @type hvparams:  dict
1981
    @param hvparams: dictionary with parameter names/value
1982
    @raise errors.HypervisorError: when a parameter is not valid
1983

1984
    """
1985
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
1986

    
1987
    security_model = hvparams[constants.HV_SECURITY_MODEL]
1988
    if security_model == constants.HT_SM_USER:
1989
      username = hvparams[constants.HV_SECURITY_DOMAIN]
1990
      try:
1991
        pwd.getpwnam(username)
1992
      except KeyError:
1993
        raise errors.HypervisorError("Unknown security domain user %s"
1994
                                     % username)
1995

    
1996
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
1997
    if spice_bind:
1998
      # only one of VNC and SPICE can be used currently.
1999
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2000
        raise errors.HypervisorError("both SPICE and VNC are configured, but"
2001
                                     " only one of them can be used at a"
2002
                                     " given time.")
2003

    
2004
      # KVM version should be >= 0.14.0
2005
      _, v_major, v_min, _ = cls._GetKVMVersion()
2006
      if (v_major, v_min) < (0, 14):
2007
        raise errors.HypervisorError("spice is configured, but it is not"
2008
                                     " available in versions of KVM < 0.14")
2009

    
2010
      # if spice_bind is not an IP address, it must be a valid interface
2011
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind)
2012
                       or netutils.IP6Address.IsValid(spice_bind))
2013
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2014
        raise errors.HypervisorError("spice: the %s parameter must be either"
2015
                                     " a valid IP address or interface name" %
2016
                                     constants.HV_KVM_SPICE_BIND)
2017

    
2018
  @classmethod
2019
  def PowercycleNode(cls):
2020
    """KVM powercycle, just a wrapper over Linux powercycle.
2021

2022
    """
2023
    cls.LinuxPowercycle()