Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 0288e7bf

History | View | Annotate | Download (87.4 kB)

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

24 eb58f9b1 Guido Trotter
"""
25 eb58f9b1 Guido Trotter
26 547a63b7 Balazs Lecz
import errno
27 eb58f9b1 Guido Trotter
import os
28 eb58f9b1 Guido Trotter
import os.path
29 eb58f9b1 Guido Trotter
import re
30 eb58f9b1 Guido Trotter
import tempfile
31 6567aff3 Guido Trotter
import time
32 30e42c4e Guido Trotter
import logging
33 d19d94db Guido Trotter
import pwd
34 199b2053 Apollon Oikonomopoulos
import struct
35 199b2053 Apollon Oikonomopoulos
import fcntl
36 5d9bfd87 Apollon Oikonomopoulos
import shutil
37 91c10532 Andrea Spadaccini
import socket
38 fc84cd5d Guido Trotter
import stat
39 91c10532 Andrea Spadaccini
import StringIO
40 8b7be6f2 Dimitris Aragiorgis
from bitarray import bitarray
41 b693125f Tsachy Shacham
try:
42 471a31b6 Andrea Spadaccini
  import affinity   # pylint: disable=F0401
43 b693125f Tsachy Shacham
except ImportError:
44 b693125f Tsachy Shacham
  affinity = None
45 eb58f9b1 Guido Trotter
46 eb58f9b1 Guido Trotter
from ganeti import utils
47 eb58f9b1 Guido Trotter
from ganeti import constants
48 eb58f9b1 Guido Trotter
from ganeti import errors
49 38e250ba Guido Trotter
from ganeti import serializer
50 38e250ba Guido Trotter
from ganeti import objects
51 76431533 Guido Trotter
from ganeti import uidpool
52 76431533 Guido Trotter
from ganeti import ssconf
53 a744b676 Manuel Franceschini
from ganeti import netutils
54 9d9bded1 Michael Hanselmann
from ganeti import pathutils
55 9d9bded1 Michael Hanselmann
from ganeti.hypervisor import hv_base
56 5d9bfd87 Apollon Oikonomopoulos
from ganeti.utils import wrapper as utils_wrapper
57 eb58f9b1 Guido Trotter
58 eb58f9b1 Guido Trotter
59 0e1e0b6a Michael Hanselmann
_KVM_NETWORK_SCRIPT = pathutils.CONF_DIR + "/kvm-vif-bridge"
60 b693125f Tsachy Shacham
_KVM_START_PAUSED_FLAG = "-S"
61 748e4b5a Michael Hanselmann
62 199b2053 Apollon Oikonomopoulos
# TUN/TAP driver constants, taken from <linux/if_tun.h>
63 199b2053 Apollon Oikonomopoulos
# They are architecture-independent and already hardcoded in qemu-kvm source,
64 199b2053 Apollon Oikonomopoulos
# so we can safely include them here.
65 199b2053 Apollon Oikonomopoulos
TUNSETIFF = 0x400454ca
66 199b2053 Apollon Oikonomopoulos
TUNGETIFF = 0x800454d2
67 199b2053 Apollon Oikonomopoulos
TUNGETFEATURES = 0x800454cf
68 199b2053 Apollon Oikonomopoulos
IFF_TAP = 0x0002
69 199b2053 Apollon Oikonomopoulos
IFF_NO_PI = 0x1000
70 199b2053 Apollon Oikonomopoulos
IFF_VNET_HDR = 0x4000
71 199b2053 Apollon Oikonomopoulos
72 07788a0b Michael Hanselmann
#: SPICE parameters which depend on L{constants.HV_KVM_SPICE_BIND}
73 07788a0b Michael Hanselmann
_SPICE_ADDITIONAL_PARAMS = frozenset([
74 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_IP_VERSION,
75 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_PASSWORD_FILE,
76 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR,
77 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_JPEG_IMG_COMPR,
78 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR,
79 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION,
80 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_USE_TLS,
81 07788a0b Michael Hanselmann
  ])
82 07788a0b Michael Hanselmann
83 8b7be6f2 Dimitris Aragiorgis
# Constant bitarray that reflects to a free pci slot
84 8b7be6f2 Dimitris Aragiorgis
# Use it with bitarray.search()
85 8b7be6f2 Dimitris Aragiorgis
_AVAILABLE_PCI_SLOT = bitarray("0")
86 8b7be6f2 Dimitris Aragiorgis
87 58502c9e Dimitris Aragiorgis
# below constants show the format of runtime file
88 58502c9e Dimitris Aragiorgis
# the nics are in second possition, while the disks in 4th (last)
89 58502c9e Dimitris Aragiorgis
# moreover disk entries are stored in tupples of L{objects.Disk}, dev_path
90 58502c9e Dimitris Aragiorgis
_KVM_NICS_RUNTIME_INDEX = 1
91 58502c9e Dimitris Aragiorgis
_KVM_DISKS_RUNTIME_INDEX = 3
92 58502c9e Dimitris Aragiorgis
_DEVICE_RUNTIME_INDEX = {
93 58502c9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK: _KVM_DISKS_RUNTIME_INDEX,
94 58502c9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC: _KVM_NICS_RUNTIME_INDEX
95 58502c9e Dimitris Aragiorgis
  }
96 58502c9e Dimitris Aragiorgis
_FIND_RUNTIME_ENTRY = {
97 58502c9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC:
98 58502c9e Dimitris Aragiorgis
    lambda nic, kvm_nics: [n for n in kvm_nics if n.uuid == nic.uuid],
99 58502c9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK:
100 277a9de7 Dimitris Aragiorgis
    lambda disk, kvm_disks: [(d, l) for (d, l) in kvm_disks
101 58502c9e Dimitris Aragiorgis
                             if d.uuid == disk.uuid]
102 58502c9e Dimitris Aragiorgis
  }
103 58502c9e Dimitris Aragiorgis
_RUNTIME_DEVICE = {
104 58502c9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC: lambda d: d,
105 277a9de7 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK: lambda (d, e): d
106 58502c9e Dimitris Aragiorgis
  }
107 58502c9e Dimitris Aragiorgis
_RUNTIME_ENTRY = {
108 58502c9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC: lambda d, e: d,
109 277a9de7 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK: lambda d, e: (d, e)
110 58502c9e Dimitris Aragiorgis
  }
111 58502c9e Dimitris Aragiorgis
112 58502c9e Dimitris Aragiorgis
113 8b7be6f2 Dimitris Aragiorgis
def _GenerateDeviceKVMId(dev_type, dev):
114 8b7be6f2 Dimitris Aragiorgis
  """Helper function to generate a unique device name used by KVM
115 8b7be6f2 Dimitris Aragiorgis

116 8b7be6f2 Dimitris Aragiorgis
  QEMU monitor commands use names to identify devices. Here we use their pci
117 8b7be6f2 Dimitris Aragiorgis
  slot and a part of their UUID to name them. dev.pci might be None for old
118 8b7be6f2 Dimitris Aragiorgis
  devices in the cluster.
119 8b7be6f2 Dimitris Aragiorgis

120 8b7be6f2 Dimitris Aragiorgis
  @type dev_type: sting
121 8b7be6f2 Dimitris Aragiorgis
  @param dev_type: device type of param dev
122 8b7be6f2 Dimitris Aragiorgis
  @type dev: L{objects.Disk} or L{objects.NIC}
123 8b7be6f2 Dimitris Aragiorgis
  @param dev: the device object for which we generate a kvm name
124 8b7be6f2 Dimitris Aragiorgis
  @raise errors.HotplugError: in case a device has no pci slot (old devices)
125 8b7be6f2 Dimitris Aragiorgis

126 8b7be6f2 Dimitris Aragiorgis
  """
127 8b7be6f2 Dimitris Aragiorgis
128 8b7be6f2 Dimitris Aragiorgis
  if not dev.pci:
129 8b7be6f2 Dimitris Aragiorgis
    raise errors.HotplugError("Hotplug is not supported for %s with UUID %s" %
130 8b7be6f2 Dimitris Aragiorgis
                              (dev_type, dev.uuid))
131 8b7be6f2 Dimitris Aragiorgis
132 8b7be6f2 Dimitris Aragiorgis
  return "%s-%s-pci-%d" % (dev_type.lower(), dev.uuid.split("-")[0], dev.pci)
133 8b7be6f2 Dimitris Aragiorgis
134 8b7be6f2 Dimitris Aragiorgis
135 8b7be6f2 Dimitris Aragiorgis
def _UpdatePCISlots(dev, pci_reservations):
136 8b7be6f2 Dimitris Aragiorgis
  """Update pci configuration for a stopped instance
137 8b7be6f2 Dimitris Aragiorgis

138 8b7be6f2 Dimitris Aragiorgis
  If dev has a pci slot then reserve it, else find first available
139 8b7be6f2 Dimitris Aragiorgis
  in pci_reservations bitarray. It acts on the same objects passed
140 8b7be6f2 Dimitris Aragiorgis
  as params so there is no need to return anything.
141 8b7be6f2 Dimitris Aragiorgis

142 8b7be6f2 Dimitris Aragiorgis
  @type dev: L{objects.Disk} or L{objects.NIC}
143 8b7be6f2 Dimitris Aragiorgis
  @param dev: the device object for which we update its pci slot
144 8b7be6f2 Dimitris Aragiorgis
  @type pci_reservations: bitarray
145 8b7be6f2 Dimitris Aragiorgis
  @param pci_reservations: existing pci reservations for an instance
146 8b7be6f2 Dimitris Aragiorgis
  @raise errors.HotplugError: in case an instance has all its slot occupied
147 8b7be6f2 Dimitris Aragiorgis

148 8b7be6f2 Dimitris Aragiorgis
  """
149 8b7be6f2 Dimitris Aragiorgis
  if dev.pci:
150 8b7be6f2 Dimitris Aragiorgis
    free = dev.pci
151 8b7be6f2 Dimitris Aragiorgis
  else: # pylint: disable=E1103
152 8b7be6f2 Dimitris Aragiorgis
    [free] = pci_reservations.search(_AVAILABLE_PCI_SLOT, 1)
153 8b7be6f2 Dimitris Aragiorgis
    if not free:
154 8b7be6f2 Dimitris Aragiorgis
      raise errors.HypervisorError("All PCI slots occupied")
155 8b7be6f2 Dimitris Aragiorgis
    dev.pci = int(free)
156 8b7be6f2 Dimitris Aragiorgis
157 8b7be6f2 Dimitris Aragiorgis
  pci_reservations[free] = True
158 8b7be6f2 Dimitris Aragiorgis
159 8b7be6f2 Dimitris Aragiorgis
160 58502c9e Dimitris Aragiorgis
def _GetExistingDeviceInfo(dev_type, device, runtime):
161 58502c9e Dimitris Aragiorgis
  """Helper function to get an existing device inside the runtime file
162 58502c9e Dimitris Aragiorgis

163 58502c9e Dimitris Aragiorgis
  Used when an instance is running. Load kvm runtime file and search
164 58502c9e Dimitris Aragiorgis
  for a device based on its type and uuid.
165 58502c9e Dimitris Aragiorgis

166 58502c9e Dimitris Aragiorgis
  @type dev_type: sting
167 58502c9e Dimitris Aragiorgis
  @param dev_type: device type of param dev
168 58502c9e Dimitris Aragiorgis
  @type device: L{objects.Disk} or L{objects.NIC}
169 58502c9e Dimitris Aragiorgis
  @param device: the device object for which we generate a kvm name
170 58502c9e Dimitris Aragiorgis
  @type runtime: tuple (cmd, nics, hvparams, disks)
171 58502c9e Dimitris Aragiorgis
  @param runtime: the runtime data to search for the device
172 58502c9e Dimitris Aragiorgis
  @raise errors.HotplugError: in case the requested device does not
173 58502c9e Dimitris Aragiorgis
    exist (e.g. device has been added without --hotplug option) or
174 58502c9e Dimitris Aragiorgis
    device info has not pci slot (e.g. old devices in the cluster)
175 58502c9e Dimitris Aragiorgis

176 58502c9e Dimitris Aragiorgis
  """
177 58502c9e Dimitris Aragiorgis
  index = _DEVICE_RUNTIME_INDEX[dev_type]
178 58502c9e Dimitris Aragiorgis
  found = _FIND_RUNTIME_ENTRY[dev_type](device, runtime[index])
179 58502c9e Dimitris Aragiorgis
  if not found:
180 58502c9e Dimitris Aragiorgis
    raise errors.HotplugError("Cannot find runtime info for %s with UUID %s" %
181 58502c9e Dimitris Aragiorgis
                              (dev_type, device.uuid))
182 58502c9e Dimitris Aragiorgis
183 58502c9e Dimitris Aragiorgis
  return found[0]
184 58502c9e Dimitris Aragiorgis
185 58502c9e Dimitris Aragiorgis
186 58502c9e Dimitris Aragiorgis
def _AnalyzeSerializedRuntime(serialized_runtime):
187 58502c9e Dimitris Aragiorgis
  """Return runtime entries for a serialized runtime file
188 58502c9e Dimitris Aragiorgis

189 58502c9e Dimitris Aragiorgis
  @type serialized_runtime: string
190 58502c9e Dimitris Aragiorgis
  @param serialized_runtime: raw text data read from actual runtime file
191 58502c9e Dimitris Aragiorgis
  @return: (cmd, nics, hvparams, bdevs)
192 58502c9e Dimitris Aragiorgis
  @rtype: list
193 58502c9e Dimitris Aragiorgis

194 58502c9e Dimitris Aragiorgis
  """
195 58502c9e Dimitris Aragiorgis
  loaded_runtime = serializer.Load(serialized_runtime)
196 58502c9e Dimitris Aragiorgis
  if len(loaded_runtime) == 3:
197 58502c9e Dimitris Aragiorgis
    serialized_blockdevs = []
198 58502c9e Dimitris Aragiorgis
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
199 58502c9e Dimitris Aragiorgis
  else:
200 58502c9e Dimitris Aragiorgis
    kvm_cmd, serialized_nics, hvparams, serialized_blockdevs = loaded_runtime
201 58502c9e Dimitris Aragiorgis
202 58502c9e Dimitris Aragiorgis
  kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
203 277a9de7 Dimitris Aragiorgis
  block_devices = [(objects.Disk.FromDict(sdisk), link)
204 277a9de7 Dimitris Aragiorgis
                   for sdisk, link in serialized_blockdevs]
205 58502c9e Dimitris Aragiorgis
206 58502c9e Dimitris Aragiorgis
  return (kvm_cmd, kvm_nics, hvparams, block_devices)
207 58502c9e Dimitris Aragiorgis
208 199b2053 Apollon Oikonomopoulos
209 ea2bcb82 Michael Hanselmann
def _GetTunFeatures(fd, _ioctl=fcntl.ioctl):
210 ea2bcb82 Michael Hanselmann
  """Retrieves supported TUN features from file descriptor.
211 ea2bcb82 Michael Hanselmann

212 ea2bcb82 Michael Hanselmann
  @see: L{_ProbeTapVnetHdr}
213 ea2bcb82 Michael Hanselmann

214 ea2bcb82 Michael Hanselmann
  """
215 ea2bcb82 Michael Hanselmann
  req = struct.pack("I", 0)
216 ea2bcb82 Michael Hanselmann
  try:
217 ea2bcb82 Michael Hanselmann
    buf = _ioctl(fd, TUNGETFEATURES, req)
218 ea2bcb82 Michael Hanselmann
  except EnvironmentError, err:
219 cfc24646 Iustin Pop
    logging.warning("ioctl(TUNGETFEATURES) failed: %s", err)
220 ea2bcb82 Michael Hanselmann
    return None
221 ea2bcb82 Michael Hanselmann
  else:
222 ea2bcb82 Michael Hanselmann
    (flags, ) = struct.unpack("I", buf)
223 ea2bcb82 Michael Hanselmann
    return flags
224 ea2bcb82 Michael Hanselmann
225 ea2bcb82 Michael Hanselmann
226 ea2bcb82 Michael Hanselmann
def _ProbeTapVnetHdr(fd, _features_fn=_GetTunFeatures):
227 199b2053 Apollon Oikonomopoulos
  """Check whether to enable the IFF_VNET_HDR flag.
228 199b2053 Apollon Oikonomopoulos

229 199b2053 Apollon Oikonomopoulos
  To do this, _all_ of the following conditions must be met:
230 199b2053 Apollon Oikonomopoulos
   1. TUNGETFEATURES ioctl() *must* be implemented
231 199b2053 Apollon Oikonomopoulos
   2. TUNGETFEATURES ioctl() result *must* contain the IFF_VNET_HDR flag
232 199b2053 Apollon Oikonomopoulos
   3. TUNGETIFF ioctl() *must* be implemented; reading the kernel code in
233 199b2053 Apollon Oikonomopoulos
      drivers/net/tun.c there is no way to test this until after the tap device
234 199b2053 Apollon Oikonomopoulos
      has been created using TUNSETIFF, and there is no way to change the
235 199b2053 Apollon Oikonomopoulos
      IFF_VNET_HDR flag after creating the interface, catch-22! However both
236 199b2053 Apollon Oikonomopoulos
      TUNGETIFF and TUNGETFEATURES were introduced in kernel version 2.6.27,
237 199b2053 Apollon Oikonomopoulos
      thus we can expect TUNGETIFF to be present if TUNGETFEATURES is.
238 199b2053 Apollon Oikonomopoulos

239 199b2053 Apollon Oikonomopoulos
   @type fd: int
240 199b2053 Apollon Oikonomopoulos
   @param fd: the file descriptor of /dev/net/tun
241 199b2053 Apollon Oikonomopoulos

242 199b2053 Apollon Oikonomopoulos
  """
243 ea2bcb82 Michael Hanselmann
  flags = _features_fn(fd)
244 199b2053 Apollon Oikonomopoulos
245 ea2bcb82 Michael Hanselmann
  if flags is None:
246 ea2bcb82 Michael Hanselmann
    # Not supported
247 199b2053 Apollon Oikonomopoulos
    return False
248 199b2053 Apollon Oikonomopoulos
249 ea2bcb82 Michael Hanselmann
  result = bool(flags & IFF_VNET_HDR)
250 ea2bcb82 Michael Hanselmann
251 ea2bcb82 Michael Hanselmann
  if not result:
252 ea2bcb82 Michael Hanselmann
    logging.warning("Kernel does not support IFF_VNET_HDR, not enabling")
253 ea2bcb82 Michael Hanselmann
254 ea2bcb82 Michael Hanselmann
  return result
255 ea2bcb82 Michael Hanselmann
256 199b2053 Apollon Oikonomopoulos
257 199b2053 Apollon Oikonomopoulos
def _OpenTap(vnet_hdr=True):
258 199b2053 Apollon Oikonomopoulos
  """Open a new tap device and return its file descriptor.
259 199b2053 Apollon Oikonomopoulos

260 199b2053 Apollon Oikonomopoulos
  This is intended to be used by a qemu-type hypervisor together with the -net
261 199b2053 Apollon Oikonomopoulos
  tap,fd=<fd> command line parameter.
262 199b2053 Apollon Oikonomopoulos

263 199b2053 Apollon Oikonomopoulos
  @type vnet_hdr: boolean
264 199b2053 Apollon Oikonomopoulos
  @param vnet_hdr: Enable the VNET Header
265 199b2053 Apollon Oikonomopoulos
  @return: (ifname, tapfd)
266 199b2053 Apollon Oikonomopoulos
  @rtype: tuple
267 199b2053 Apollon Oikonomopoulos

268 199b2053 Apollon Oikonomopoulos
  """
269 199b2053 Apollon Oikonomopoulos
  try:
270 199b2053 Apollon Oikonomopoulos
    tapfd = os.open("/dev/net/tun", os.O_RDWR)
271 199b2053 Apollon Oikonomopoulos
  except EnvironmentError:
272 199b2053 Apollon Oikonomopoulos
    raise errors.HypervisorError("Failed to open /dev/net/tun")
273 199b2053 Apollon Oikonomopoulos
274 199b2053 Apollon Oikonomopoulos
  flags = IFF_TAP | IFF_NO_PI
275 199b2053 Apollon Oikonomopoulos
276 199b2053 Apollon Oikonomopoulos
  if vnet_hdr and _ProbeTapVnetHdr(tapfd):
277 199b2053 Apollon Oikonomopoulos
    flags |= IFF_VNET_HDR
278 199b2053 Apollon Oikonomopoulos
279 199b2053 Apollon Oikonomopoulos
  # The struct ifreq ioctl request (see netdevice(7))
280 199b2053 Apollon Oikonomopoulos
  ifr = struct.pack("16sh", "", flags)
281 199b2053 Apollon Oikonomopoulos
282 199b2053 Apollon Oikonomopoulos
  try:
283 199b2053 Apollon Oikonomopoulos
    res = fcntl.ioctl(tapfd, TUNSETIFF, ifr)
284 6f1e1921 Michael Hanselmann
  except EnvironmentError, err:
285 6f1e1921 Michael Hanselmann
    raise errors.HypervisorError("Failed to allocate a new TAP device: %s" %
286 6f1e1921 Michael Hanselmann
                                 err)
287 199b2053 Apollon Oikonomopoulos
288 199b2053 Apollon Oikonomopoulos
  # Get the interface name from the ioctl
289 199b2053 Apollon Oikonomopoulos
  ifname = struct.unpack("16sh", res)[0].strip("\x00")
290 199b2053 Apollon Oikonomopoulos
  return (ifname, tapfd)
291 199b2053 Apollon Oikonomopoulos
292 748e4b5a Michael Hanselmann
293 91c10532 Andrea Spadaccini
class QmpMessage:
294 91c10532 Andrea Spadaccini
  """QEMU Messaging Protocol (QMP) message.
295 91c10532 Andrea Spadaccini

296 91c10532 Andrea Spadaccini
  """
297 91c10532 Andrea Spadaccini
  def __init__(self, data):
298 91c10532 Andrea Spadaccini
    """Creates a new QMP message based on the passed data.
299 91c10532 Andrea Spadaccini

300 91c10532 Andrea Spadaccini
    """
301 91c10532 Andrea Spadaccini
    if not isinstance(data, dict):
302 91c10532 Andrea Spadaccini
      raise TypeError("QmpMessage must be initialized with a dict")
303 91c10532 Andrea Spadaccini
304 91c10532 Andrea Spadaccini
    self.data = data
305 91c10532 Andrea Spadaccini
306 91c10532 Andrea Spadaccini
  def __getitem__(self, field_name):
307 91c10532 Andrea Spadaccini
    """Get the value of the required field if present, or None.
308 91c10532 Andrea Spadaccini

309 91c10532 Andrea Spadaccini
    Overrides the [] operator to provide access to the message data,
310 91c10532 Andrea Spadaccini
    returning None if the required item is not in the message
311 91c10532 Andrea Spadaccini
    @return: the value of the field_name field, or None if field_name
312 91c10532 Andrea Spadaccini
             is not contained in the message
313 91c10532 Andrea Spadaccini

314 91c10532 Andrea Spadaccini
    """
315 9b87c2cf Michael Hanselmann
    return self.data.get(field_name, None)
316 91c10532 Andrea Spadaccini
317 91c10532 Andrea Spadaccini
  def __setitem__(self, field_name, field_value):
318 91c10532 Andrea Spadaccini
    """Set the value of the required field_name to field_value.
319 91c10532 Andrea Spadaccini

320 91c10532 Andrea Spadaccini
    """
321 91c10532 Andrea Spadaccini
    self.data[field_name] = field_value
322 91c10532 Andrea Spadaccini
323 91c10532 Andrea Spadaccini
  @staticmethod
324 91c10532 Andrea Spadaccini
  def BuildFromJsonString(json_string):
325 91c10532 Andrea Spadaccini
    """Build a QmpMessage from a JSON encoded string.
326 91c10532 Andrea Spadaccini

327 91c10532 Andrea Spadaccini
    @type json_string: str
328 91c10532 Andrea Spadaccini
    @param json_string: JSON string representing the message
329 91c10532 Andrea Spadaccini
    @rtype: L{QmpMessage}
330 91c10532 Andrea Spadaccini
    @return: a L{QmpMessage} built from json_string
331 91c10532 Andrea Spadaccini

332 91c10532 Andrea Spadaccini
    """
333 91c10532 Andrea Spadaccini
    # Parse the string
334 91c10532 Andrea Spadaccini
    data = serializer.LoadJson(json_string)
335 91c10532 Andrea Spadaccini
    return QmpMessage(data)
336 91c10532 Andrea Spadaccini
337 91c10532 Andrea Spadaccini
  def __str__(self):
338 a182a3ed Michael Hanselmann
    # The protocol expects the JSON object to be sent as a single line.
339 a182a3ed Michael Hanselmann
    return serializer.DumpJson(self.data)
340 91c10532 Andrea Spadaccini
341 91c10532 Andrea Spadaccini
  def __eq__(self, other):
342 91c10532 Andrea Spadaccini
    # When comparing two QmpMessages, we are interested in comparing
343 91c10532 Andrea Spadaccini
    # their internal representation of the message data
344 91c10532 Andrea Spadaccini
    return self.data == other.data
345 91c10532 Andrea Spadaccini
346 91c10532 Andrea Spadaccini
347 91c10532 Andrea Spadaccini
class QmpConnection:
348 91c10532 Andrea Spadaccini
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
349 91c10532 Andrea Spadaccini

350 91c10532 Andrea Spadaccini
  """
351 91c10532 Andrea Spadaccini
  _FIRST_MESSAGE_KEY = "QMP"
352 91c10532 Andrea Spadaccini
  _EVENT_KEY = "event"
353 91c10532 Andrea Spadaccini
  _ERROR_KEY = "error"
354 89da2ff3 Guido Trotter
  _RETURN_KEY = RETURN_KEY = "return"
355 89da2ff3 Guido Trotter
  _ACTUAL_KEY = ACTUAL_KEY = "actual"
356 91c10532 Andrea Spadaccini
  _ERROR_CLASS_KEY = "class"
357 91c10532 Andrea Spadaccini
  _ERROR_DATA_KEY = "data"
358 91c10532 Andrea Spadaccini
  _ERROR_DESC_KEY = "desc"
359 91c10532 Andrea Spadaccini
  _EXECUTE_KEY = "execute"
360 91c10532 Andrea Spadaccini
  _ARGUMENTS_KEY = "arguments"
361 91c10532 Andrea Spadaccini
  _CAPABILITIES_COMMAND = "qmp_capabilities"
362 91c10532 Andrea Spadaccini
  _MESSAGE_END_TOKEN = "\r\n"
363 91c10532 Andrea Spadaccini
  _SOCKET_TIMEOUT = 5
364 91c10532 Andrea Spadaccini
365 91c10532 Andrea Spadaccini
  def __init__(self, monitor_filename):
366 91c10532 Andrea Spadaccini
    """Instantiates the QmpConnection object.
367 91c10532 Andrea Spadaccini

368 91c10532 Andrea Spadaccini
    @type monitor_filename: string
369 91c10532 Andrea Spadaccini
    @param monitor_filename: the filename of the UNIX raw socket on which the
370 91c10532 Andrea Spadaccini
                             QMP monitor is listening
371 91c10532 Andrea Spadaccini

372 91c10532 Andrea Spadaccini
    """
373 91c10532 Andrea Spadaccini
    self.monitor_filename = monitor_filename
374 91c10532 Andrea Spadaccini
    self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
375 91c10532 Andrea Spadaccini
    # We want to fail if the server doesn't send a complete message
376 91c10532 Andrea Spadaccini
    # in a reasonable amount of time
377 91c10532 Andrea Spadaccini
    self.sock.settimeout(self._SOCKET_TIMEOUT)
378 91c10532 Andrea Spadaccini
    self._connected = False
379 91c10532 Andrea Spadaccini
    self._buf = ""
380 91c10532 Andrea Spadaccini
381 fc84cd5d Guido Trotter
  def _check_socket(self):
382 fc84cd5d Guido Trotter
    sock_stat = None
383 fc84cd5d Guido Trotter
    try:
384 fc84cd5d Guido Trotter
      sock_stat = os.stat(self.monitor_filename)
385 fc84cd5d Guido Trotter
    except EnvironmentError, err:
386 fc84cd5d Guido Trotter
      if err.errno == errno.ENOENT:
387 fc84cd5d Guido Trotter
        raise errors.HypervisorError("No qmp socket found")
388 fc84cd5d Guido Trotter
      else:
389 fc84cd5d Guido Trotter
        raise errors.HypervisorError("Error checking qmp socket: %s",
390 fc84cd5d Guido Trotter
                                     utils.ErrnoOrStr(err))
391 fc84cd5d Guido Trotter
    if not stat.S_ISSOCK(sock_stat.st_mode):
392 fc84cd5d Guido Trotter
      raise errors.HypervisorError("Qmp socket is not a socket")
393 fc84cd5d Guido Trotter
394 91c10532 Andrea Spadaccini
  def _check_connection(self):
395 91c10532 Andrea Spadaccini
    """Make sure that the connection is established.
396 91c10532 Andrea Spadaccini

397 91c10532 Andrea Spadaccini
    """
398 91c10532 Andrea Spadaccini
    if not self._connected:
399 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("To use a QmpConnection you need to first"
400 91c10532 Andrea Spadaccini
                                   " invoke connect() on it")
401 91c10532 Andrea Spadaccini
402 91c10532 Andrea Spadaccini
  def connect(self):
403 91c10532 Andrea Spadaccini
    """Connects to the QMP monitor.
404 91c10532 Andrea Spadaccini

405 91c10532 Andrea Spadaccini
    Connects to the UNIX socket and makes sure that we can actually send and
406 91c10532 Andrea Spadaccini
    receive data to the kvm instance via QMP.
407 91c10532 Andrea Spadaccini

408 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
409 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
410 91c10532 Andrea Spadaccini

411 91c10532 Andrea Spadaccini
    """
412 fc84cd5d Guido Trotter
    if self._connected:
413 fc84cd5d Guido Trotter
      raise errors.ProgrammerError("Cannot connect twice")
414 fc84cd5d Guido Trotter
415 fc84cd5d Guido Trotter
    self._check_socket()
416 fc84cd5d Guido Trotter
417 fc84cd5d Guido Trotter
    # Check file existance/stuff
418 fc84cd5d Guido Trotter
    try:
419 fc84cd5d Guido Trotter
      self.sock.connect(self.monitor_filename)
420 fc84cd5d Guido Trotter
    except EnvironmentError:
421 fc84cd5d Guido Trotter
      raise errors.HypervisorError("Can't connect to qmp socket")
422 91c10532 Andrea Spadaccini
    self._connected = True
423 91c10532 Andrea Spadaccini
424 91c10532 Andrea Spadaccini
    # Check if we receive a correct greeting message from the server
425 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 2.2)
426 91c10532 Andrea Spadaccini
    greeting = self._Recv()
427 91c10532 Andrea Spadaccini
    if not greeting[self._FIRST_MESSAGE_KEY]:
428 91c10532 Andrea Spadaccini
      self._connected = False
429 afa9bb2e Michael Hanselmann
      raise errors.HypervisorError("kvm: QMP communication error (wrong"
430 91c10532 Andrea Spadaccini
                                   " server greeting")
431 91c10532 Andrea Spadaccini
432 91c10532 Andrea Spadaccini
    # Let's put the monitor in command mode using the qmp_capabilities
433 91c10532 Andrea Spadaccini
    # command, or else no command will be executable.
434 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 4)
435 91c10532 Andrea Spadaccini
    self.Execute(self._CAPABILITIES_COMMAND)
436 91c10532 Andrea Spadaccini
437 91c10532 Andrea Spadaccini
  def _ParseMessage(self, buf):
438 91c10532 Andrea Spadaccini
    """Extract and parse a QMP message from the given buffer.
439 91c10532 Andrea Spadaccini

440 91c10532 Andrea Spadaccini
    Seeks for a QMP message in the given buf. If found, it parses it and
441 91c10532 Andrea Spadaccini
    returns it together with the rest of the characters in the buf.
442 91c10532 Andrea Spadaccini
    If no message is found, returns None and the whole buffer.
443 91c10532 Andrea Spadaccini

444 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
445 91c10532 Andrea Spadaccini

446 91c10532 Andrea Spadaccini
    """
447 91c10532 Andrea Spadaccini
    message = None
448 91c10532 Andrea Spadaccini
    # Check if we got the message end token (CRLF, as per the QEMU Protocol
449 91c10532 Andrea Spadaccini
    # Specification 0.1 - Section 2.1.1)
450 91c10532 Andrea Spadaccini
    pos = buf.find(self._MESSAGE_END_TOKEN)
451 91c10532 Andrea Spadaccini
    if pos >= 0:
452 91c10532 Andrea Spadaccini
      try:
453 91c10532 Andrea Spadaccini
        message = QmpMessage.BuildFromJsonString(buf[:pos + 1])
454 91c10532 Andrea Spadaccini
      except Exception, err:
455 91c10532 Andrea Spadaccini
        raise errors.ProgrammerError("QMP data serialization error: %s" % err)
456 91c10532 Andrea Spadaccini
      buf = buf[pos + 1:]
457 91c10532 Andrea Spadaccini
458 91c10532 Andrea Spadaccini
    return (message, buf)
459 91c10532 Andrea Spadaccini
460 91c10532 Andrea Spadaccini
  def _Recv(self):
461 91c10532 Andrea Spadaccini
    """Receives a message from QMP and decodes the received JSON object.
462 91c10532 Andrea Spadaccini

463 91c10532 Andrea Spadaccini
    @rtype: QmpMessage
464 91c10532 Andrea Spadaccini
    @return: the received message
465 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
466 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
467 91c10532 Andrea Spadaccini

468 91c10532 Andrea Spadaccini
    """
469 91c10532 Andrea Spadaccini
    self._check_connection()
470 91c10532 Andrea Spadaccini
471 91c10532 Andrea Spadaccini
    # Check if there is already a message in the buffer
472 91c10532 Andrea Spadaccini
    (message, self._buf) = self._ParseMessage(self._buf)
473 91c10532 Andrea Spadaccini
    if message:
474 91c10532 Andrea Spadaccini
      return message
475 91c10532 Andrea Spadaccini
476 91c10532 Andrea Spadaccini
    recv_buffer = StringIO.StringIO(self._buf)
477 91c10532 Andrea Spadaccini
    recv_buffer.seek(len(self._buf))
478 91c10532 Andrea Spadaccini
    try:
479 91c10532 Andrea Spadaccini
      while True:
480 91c10532 Andrea Spadaccini
        data = self.sock.recv(4096)
481 91c10532 Andrea Spadaccini
        if not data:
482 91c10532 Andrea Spadaccini
          break
483 91c10532 Andrea Spadaccini
        recv_buffer.write(data)
484 91c10532 Andrea Spadaccini
485 91c10532 Andrea Spadaccini
        (message, self._buf) = self._ParseMessage(recv_buffer.getvalue())
486 91c10532 Andrea Spadaccini
        if message:
487 91c10532 Andrea Spadaccini
          return message
488 91c10532 Andrea Spadaccini
489 91c10532 Andrea Spadaccini
    except socket.timeout, err:
490 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while receiving a QMP message: "
491 91c10532 Andrea Spadaccini
                                   "%s" % (err))
492 91c10532 Andrea Spadaccini
    except socket.error, err:
493 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to receive data from KVM using the"
494 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
495 91c10532 Andrea Spadaccini
496 91c10532 Andrea Spadaccini
  def _Send(self, message):
497 91c10532 Andrea Spadaccini
    """Encodes and sends a message to KVM using QMP.
498 91c10532 Andrea Spadaccini

499 91c10532 Andrea Spadaccini
    @type message: QmpMessage
500 91c10532 Andrea Spadaccini
    @param message: message to send to KVM
501 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
502 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
503 91c10532 Andrea Spadaccini

504 91c10532 Andrea Spadaccini
    """
505 91c10532 Andrea Spadaccini
    self._check_connection()
506 91c10532 Andrea Spadaccini
    try:
507 91c10532 Andrea Spadaccini
      message_str = str(message)
508 91c10532 Andrea Spadaccini
    except Exception, err:
509 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("QMP data deserialization error: %s" % err)
510 91c10532 Andrea Spadaccini
511 91c10532 Andrea Spadaccini
    try:
512 91c10532 Andrea Spadaccini
      self.sock.sendall(message_str)
513 91c10532 Andrea Spadaccini
    except socket.timeout, err:
514 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while sending a QMP message: "
515 91c10532 Andrea Spadaccini
                                   "%s (%s)" % (err.string, err.errno))
516 91c10532 Andrea Spadaccini
    except socket.error, err:
517 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to send data from KVM using the"
518 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
519 91c10532 Andrea Spadaccini
520 91c10532 Andrea Spadaccini
  def Execute(self, command, arguments=None):
521 91c10532 Andrea Spadaccini
    """Executes a QMP command and returns the response of the server.
522 91c10532 Andrea Spadaccini

523 91c10532 Andrea Spadaccini
    @type command: str
524 91c10532 Andrea Spadaccini
    @param command: the command to execute
525 91c10532 Andrea Spadaccini
    @type arguments: dict
526 91c10532 Andrea Spadaccini
    @param arguments: dictionary of arguments to be passed to the command
527 91c10532 Andrea Spadaccini
    @rtype: dict
528 91c10532 Andrea Spadaccini
    @return: dictionary representing the received JSON object
529 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
530 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
531 91c10532 Andrea Spadaccini

532 91c10532 Andrea Spadaccini
    """
533 91c10532 Andrea Spadaccini
    self._check_connection()
534 91c10532 Andrea Spadaccini
    message = QmpMessage({self._EXECUTE_KEY: command})
535 91c10532 Andrea Spadaccini
    if arguments:
536 91c10532 Andrea Spadaccini
      message[self._ARGUMENTS_KEY] = arguments
537 91c10532 Andrea Spadaccini
    self._Send(message)
538 91c10532 Andrea Spadaccini
539 91c10532 Andrea Spadaccini
    # Events can occur between the sending of the command and the reception
540 91c10532 Andrea Spadaccini
    # of the response, so we need to filter out messages with the event key.
541 91c10532 Andrea Spadaccini
    while True:
542 91c10532 Andrea Spadaccini
      response = self._Recv()
543 91c10532 Andrea Spadaccini
      err = response[self._ERROR_KEY]
544 91c10532 Andrea Spadaccini
      if err:
545 91c10532 Andrea Spadaccini
        raise errors.HypervisorError("kvm: error executing the %s"
546 91c10532 Andrea Spadaccini
                                     " command: %s (%s, %s):" %
547 91c10532 Andrea Spadaccini
                                     (command,
548 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DESC_KEY],
549 91c10532 Andrea Spadaccini
                                      err[self._ERROR_CLASS_KEY],
550 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DATA_KEY]))
551 91c10532 Andrea Spadaccini
552 91c10532 Andrea Spadaccini
      elif not response[self._EVENT_KEY]:
553 91c10532 Andrea Spadaccini
        return response
554 91c10532 Andrea Spadaccini
555 91c10532 Andrea Spadaccini
556 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
557 65107a2f Michael Hanselmann
  """KVM hypervisor interface
558 65107a2f Michael Hanselmann

559 65107a2f Michael Hanselmann
  """
560 d271c6fd Iustin Pop
  CAN_MIGRATE = True
561 eb58f9b1 Guido Trotter
562 9d9bded1 Michael Hanselmann
  _ROOT_DIR = pathutils.RUN_DIR + "/kvm-hypervisor"
563 a1d79fc6 Guido Trotter
  _PIDS_DIR = _ROOT_DIR + "/pid" # contains live instances pids
564 7548396c Guido Trotter
  _UIDS_DIR = _ROOT_DIR + "/uid" # contains instances reserved uids
565 a1d79fc6 Guido Trotter
  _CTRL_DIR = _ROOT_DIR + "/ctrl" # contains instances control sockets
566 a1d79fc6 Guido Trotter
  _CONF_DIR = _ROOT_DIR + "/conf" # contains instances startup data
567 5d9bfd87 Apollon Oikonomopoulos
  _NICS_DIR = _ROOT_DIR + "/nic" # contains instances nic <-> tap associations
568 4f580fef Sรฉbastien Bocahu
  _KEYMAP_DIR = _ROOT_DIR + "/keymap" # contains instances keymaps
569 547a63b7 Balazs Lecz
  # KVM instances with chroot enabled are started in empty chroot directories.
570 547a63b7 Balazs Lecz
  _CHROOT_DIR = _ROOT_DIR + "/chroot" # for empty chroot directories
571 547a63b7 Balazs Lecz
  # After an instance is stopped, its chroot directory is removed.
572 547a63b7 Balazs Lecz
  # If the chroot directory is not empty, it can't be removed.
573 547a63b7 Balazs Lecz
  # A non-empty chroot directory indicates a possible security incident.
574 547a63b7 Balazs Lecz
  # To support forensics, the non-empty chroot directory is quarantined in
575 547a63b7 Balazs Lecz
  # a separate directory, called 'chroot-quarantine'.
576 547a63b7 Balazs Lecz
  _CHROOT_QUARANTINE_DIR = _ROOT_DIR + "/chroot-quarantine"
577 5d9bfd87 Apollon Oikonomopoulos
  _DIRS = [_ROOT_DIR, _PIDS_DIR, _UIDS_DIR, _CTRL_DIR, _CONF_DIR, _NICS_DIR,
578 2911f46c Iustin Pop
           _CHROOT_DIR, _CHROOT_QUARANTINE_DIR, _KEYMAP_DIR]
579 eb58f9b1 Guido Trotter
580 205ab586 Iustin Pop
  PARAMETERS = {
581 4b9638dc Guido Trotter
    constants.HV_KVM_PATH: hv_base.REQ_FILE_CHECK,
582 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK,
583 205ab586 Iustin Pop
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
584 205ab586 Iustin Pop
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
585 205ab586 Iustin Pop
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
586 205ab586 Iustin Pop
    constants.HV_ACPI: hv_base.NO_CHECK,
587 205ab586 Iustin Pop
    constants.HV_SERIAL_CONSOLE: hv_base.NO_CHECK,
588 14fd6c81 Guido Trotter
    constants.HV_SERIAL_SPEED: hv_base.NO_CHECK,
589 d73ef63f Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS:
590 8b312c1d Manuel Franceschini
      (False, lambda x: (netutils.IP4Address.IsValid(x) or
591 8b312c1d Manuel Franceschini
                         utils.IsNormAbsPath(x)),
592 afa9bb2e Michael Hanselmann
       "The VNC bind address must be either a valid IP address or an absolute"
593 d73ef63f Michael Hanselmann
       " pathname", None, None),
594 205ab586 Iustin Pop
    constants.HV_VNC_TLS: hv_base.NO_CHECK,
595 205ab586 Iustin Pop
    constants.HV_VNC_X509: hv_base.OPT_DIR_CHECK,
596 205ab586 Iustin Pop
    constants.HV_VNC_X509_VERIFY: hv_base.NO_CHECK,
597 6e6bb8d5 Guido Trotter
    constants.HV_VNC_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
598 b1cb62bd Andrea Spadaccini
    constants.HV_KVM_SPICE_BIND: hv_base.NO_CHECK, # will be checked later
599 b1cb62bd Andrea Spadaccini
    constants.HV_KVM_SPICE_IP_VERSION:
600 b1cb62bd Andrea Spadaccini
      (False, lambda x: (x == constants.IFACE_NO_IP_VERSION_SPECIFIED or
601 b1cb62bd Andrea Spadaccini
                         x in constants.VALID_IP_VERSIONS),
602 afa9bb2e Michael Hanselmann
       "The SPICE IP version should be 4 or 6",
603 b1cb62bd Andrea Spadaccini
       None, None),
604 b451c4c7 Andrea Spadaccini
    constants.HV_KVM_SPICE_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
605 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR:
606 5ae4945a Iustin Pop
      hv_base.ParamInSet(
607 5ae4945a Iustin Pop
        False, constants.HT_KVM_SPICE_VALID_LOSSLESS_IMG_COMPR_OPTIONS),
608 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_JPEG_IMG_COMPR:
609 5ae4945a Iustin Pop
      hv_base.ParamInSet(
610 5ae4945a Iustin Pop
        False, constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
611 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR:
612 5ae4945a Iustin Pop
      hv_base.ParamInSet(
613 5ae4945a Iustin Pop
        False, constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
614 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION:
615 5ae4945a Iustin Pop
      hv_base.ParamInSet(
616 5ae4945a Iustin Pop
        False, constants.HT_KVM_SPICE_VALID_VIDEO_STREAM_DETECTION_OPTIONS),
617 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_AUDIO_COMPR: hv_base.NO_CHECK,
618 bfe86c76 Andrea Spadaccini
    constants.HV_KVM_SPICE_USE_TLS: hv_base.NO_CHECK,
619 3e40b587 Andrea Spadaccini
    constants.HV_KVM_SPICE_TLS_CIPHERS: hv_base.NO_CHECK,
620 3e40b587 Andrea Spadaccini
    constants.HV_KVM_SPICE_USE_VDAGENT: hv_base.NO_CHECK,
621 cc130cc7 Marco Casavecchia
    constants.HV_KVM_FLOPPY_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
622 205ab586 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
623 cc130cc7 Marco Casavecchia
    constants.HV_KVM_CDROM2_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
624 d73ef63f Michael Hanselmann
    constants.HV_BOOT_ORDER:
625 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
626 d73ef63f Michael Hanselmann
    constants.HV_NIC_TYPE:
627 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
628 d73ef63f Michael Hanselmann
    constants.HV_DISK_TYPE:
629 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
630 cc130cc7 Marco Casavecchia
    constants.HV_KVM_CDROM_DISK_TYPE:
631 cc130cc7 Marco Casavecchia
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_DISK_TYPES),
632 d73ef63f Michael Hanselmann
    constants.HV_USB_MOUSE:
633 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
634 4f580fef Sรฉbastien Bocahu
    constants.HV_KEYMAP: hv_base.NO_CHECK,
635 e2d14329 Andrea Spadaccini
    constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
636 2c368f28 Guido Trotter
    constants.HV_MIGRATION_BANDWIDTH: hv_base.REQ_NONNEGATIVE_INT_CHECK,
637 2c368f28 Guido Trotter
    constants.HV_MIGRATION_DOWNTIME: hv_base.REQ_NONNEGATIVE_INT_CHECK,
638 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
639 6b970cef Jun Futagawa
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
640 19572932 Iustin Pop
    constants.HV_DISK_CACHE:
641 19572932 Iustin Pop
      hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
642 d19d94db Guido Trotter
    constants.HV_SECURITY_MODEL:
643 d19d94db Guido Trotter
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_SM_TYPES),
644 d19d94db Guido Trotter
    constants.HV_SECURITY_DOMAIN: hv_base.NO_CHECK,
645 7ba594c0 Guido Trotter
    constants.HV_KVM_FLAG:
646 7ba594c0 Guido Trotter
      hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES),
647 fbe27e2b Guido Trotter
    constants.HV_VHOST_NET: hv_base.NO_CHECK,
648 547a63b7 Balazs Lecz
    constants.HV_KVM_USE_CHROOT: hv_base.NO_CHECK,
649 4f958b0b Miguel Di Ciurcio Filho
    constants.HV_MEM_PATH: hv_base.OPT_DIR_CHECK,
650 990ade2d Stephen Shirley
    constants.HV_REBOOT_BEHAVIOR:
651 a7f884d3 Tsachy Shacham
      hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
652 a7f884d3 Tsachy Shacham
    constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
653 3c286190 Dimitris Aragiorgis
    constants.HV_CPU_TYPE: hv_base.NO_CHECK,
654 2c368f28 Guido Trotter
    constants.HV_CPU_CORES: hv_base.OPT_NONNEGATIVE_INT_CHECK,
655 2c368f28 Guido Trotter
    constants.HV_CPU_THREADS: hv_base.OPT_NONNEGATIVE_INT_CHECK,
656 2c368f28 Guido Trotter
    constants.HV_CPU_SOCKETS: hv_base.OPT_NONNEGATIVE_INT_CHECK,
657 2fddb144 Guido Trotter
    constants.HV_SOUNDHW: hv_base.NO_CHECK,
658 156681c1 Guido Trotter
    constants.HV_USB_DEVICES: hv_base.NO_CHECK,
659 7589346f Guido Trotter
    constants.HV_VGA: hv_base.NO_CHECK,
660 e6f24d89 Guido Trotter
    constants.HV_KVM_EXTRA: hv_base.NO_CHECK,
661 4ab75599 Dimitris Aragiorgis
    constants.HV_KVM_MACHINE_VERSION: hv_base.NO_CHECK,
662 8a534fbe Stratos Psomdakis
    constants.HV_VNET_HDR: hv_base.NO_CHECK,
663 205ab586 Iustin Pop
    }
664 6b5605e8 Iustin Pop
665 f0db563d Guido Trotter
  _VIRTIO = "virtio"
666 f0db563d Guido Trotter
  _VIRTIO_NET_PCI = "virtio-net-pci"
667 994ccaf2 Dimitris Aragiorgis
  _VIRTIO_BLK_PCI = "virtio-blk-pci"
668 f0db563d Guido Trotter
669 d0c8c01d Iustin Pop
  _MIGRATION_STATUS_RE = re.compile("Migration\s+status:\s+(\w+)",
670 30e42c4e Guido Trotter
                                    re.M | re.I)
671 65107a2f Michael Hanselmann
  _MIGRATION_PROGRESS_RE = \
672 527c0cf7 Michael Hanselmann
    re.compile(r"\s*transferred\s+ram:\s+(?P<transferred>\d+)\s+kbytes\s*\n"
673 527c0cf7 Michael Hanselmann
               r"\s*remaining\s+ram:\s+(?P<remaining>\d+)\s+kbytes\s*\n"
674 527c0cf7 Michael Hanselmann
               r"\s*total\s+ram:\s+(?P<total>\d+)\s+kbytes\s*\n", re.I)
675 61643226 Andrea Spadaccini
676 c4e388a5 Guido Trotter
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
677 c4e388a5 Guido Trotter
  _MIGRATION_INFO_RETRY_DELAY = 2
678 30e42c4e Guido Trotter
679 585c8187 Guido Trotter
  _VERSION_RE = re.compile(r"\b(\d+)\.(\d+)(\.(\d+))?\b")
680 b52d85c1 Guido Trotter
681 b693125f Tsachy Shacham
  _CPU_INFO_RE = re.compile(r"cpu\s+\#(\d+).*thread_id\s*=\s*(\d+)", re.I)
682 b693125f Tsachy Shacham
  _CPU_INFO_CMD = "info cpus"
683 b693125f Tsachy Shacham
  _CONT_CMD = "cont"
684 b693125f Tsachy Shacham
685 7f83345f Guido Trotter
  _DEFAULT_MACHINE_VERSION_RE = re.compile(r"^(\S+).*\(default\)", re.M)
686 82e3bf85 Dimitris Aragiorgis
  _CHECK_MACHINE_VERSION_RE = \
687 82e3bf85 Dimitris Aragiorgis
    staticmethod(lambda x: re.compile(r"^(%s)[ ]+.*PC" % x, re.M))
688 e6ba3320 Dimitris Aragiorgis
689 0ad7f5d8 Guido Trotter
  _QMP_RE = re.compile(r"^-qmp\s", re.M)
690 0ad7f5d8 Guido Trotter
  _SPICE_RE = re.compile(r"^-spice\s", re.M)
691 0ad7f5d8 Guido Trotter
  _VHOST_RE = re.compile(r"^-net\s.*,vhost=on|off", re.M)
692 0ad7f5d8 Guido Trotter
  _ENABLE_KVM_RE = re.compile(r"^-enable-kvm\s", re.M)
693 0ad7f5d8 Guido Trotter
  _DISABLE_KVM_RE = re.compile(r"^-disable-kvm\s", re.M)
694 0ad7f5d8 Guido Trotter
  _NETDEV_RE = re.compile(r"^-netdev\s", re.M)
695 99c7cd5b Guido Trotter
  _DISPLAY_RE = re.compile(r"^-display\s", re.M)
696 8cb5634a Guido Trotter
  _MACHINE_RE = re.compile(r"^-machine\s", re.M)
697 994ccaf2 Dimitris Aragiorgis
  _VIRTIO_NET_RE = re.compile(r"^name \"%s\"" % _VIRTIO_NET_PCI, re.M)
698 994ccaf2 Dimitris Aragiorgis
  _VIRTIO_BLK_RE = re.compile(r"^name \"%s\"" % _VIRTIO_BLK_PCI, re.M)
699 0ad7f5d8 Guido Trotter
  # match  -drive.*boot=on|off on different lines, but in between accept only
700 0ad7f5d8 Guido Trotter
  # dashes not preceeded by a new line (which would mean another option
701 0ad7f5d8 Guido Trotter
  # different than -drive is starting)
702 0ad7f5d8 Guido Trotter
  _BOOT_RE = re.compile(r"^-drive\s([^-]|(?<!^)-)*,boot=on\|off", re.M | re.S)
703 0ad7f5d8 Guido Trotter
704 8b7be6f2 Dimitris Aragiorgis
  _INFO_PCI_RE = re.compile(r'Bus.*device[ ]*(\d+).*')
705 8b7be6f2 Dimitris Aragiorgis
  _INFO_PCI_CMD = "info pci"
706 8b7be6f2 Dimitris Aragiorgis
  _INFO_VERSION_RE = \
707 8b7be6f2 Dimitris Aragiorgis
    re.compile(r'^QEMU (\d+)\.(\d+)(\.(\d+))?.*monitor.*', re.M)
708 8b7be6f2 Dimitris Aragiorgis
  _INFO_VERSION_CMD = "info version"
709 8b7be6f2 Dimitris Aragiorgis
710 8b7be6f2 Dimitris Aragiorgis
  _DEFAULT_PCI_RESERVATIONS = "11110000000000000000000000000000"
711 8b7be6f2 Dimitris Aragiorgis
712 64bfbc08 Guido Trotter
  ANCILLARY_FILES = [
713 64bfbc08 Guido Trotter
    _KVM_NETWORK_SCRIPT,
714 64bfbc08 Guido Trotter
    ]
715 69ab2e12 Guido Trotter
  ANCILLARY_FILES_OPT = [
716 69ab2e12 Guido Trotter
    _KVM_NETWORK_SCRIPT,
717 69ab2e12 Guido Trotter
    ]
718 64bfbc08 Guido Trotter
719 6e043e60 Guido Trotter
  # Supported kvm options to get output from
720 6e043e60 Guido Trotter
  _KVMOPT_HELP = "help"
721 6e043e60 Guido Trotter
  _KVMOPT_MLIST = "mlist"
722 f0db563d Guido Trotter
  _KVMOPT_DEVICELIST = "devicelist"
723 bc0fed4b Guido Trotter
724 bc0fed4b Guido Trotter
  # Command to execute to get the output from kvm, and whether to
725 bc0fed4b Guido Trotter
  # accept the output even on failure.
726 6e043e60 Guido Trotter
  _KVMOPTS_CMDS = {
727 bc0fed4b Guido Trotter
    _KVMOPT_HELP: (["--help"], False),
728 bc0fed4b Guido Trotter
    _KVMOPT_MLIST: (["-M", "?"], False),
729 bc0fed4b Guido Trotter
    _KVMOPT_DEVICELIST: (["-device", "?"], True),
730 6e043e60 Guido Trotter
  }
731 6e043e60 Guido Trotter
732 eb58f9b1 Guido Trotter
  def __init__(self):
733 eb58f9b1 Guido Trotter
    hv_base.BaseHypervisor.__init__(self)
734 eb58f9b1 Guido Trotter
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
735 eb58f9b1 Guido Trotter
    # in a tmpfs filesystem or has been otherwise wiped out.
736 29921401 Iustin Pop
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
737 9afb67fe Guido Trotter
    utils.EnsureDirs(dirs)
738 eb58f9b1 Guido Trotter
739 30786fc9 Iustin Pop
  @classmethod
740 30786fc9 Iustin Pop
  def _InstancePidFile(cls, instance_name):
741 98ec75d6 Iustin Pop
    """Returns the instance pidfile.
742 98ec75d6 Iustin Pop

743 98ec75d6 Iustin Pop
    """
744 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
745 98ec75d6 Iustin Pop
746 263b8de6 Guido Trotter
  @classmethod
747 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
748 7548396c Guido Trotter
    """Returns the instance uidfile.
749 7548396c Guido Trotter

750 7548396c Guido Trotter
    """
751 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
752 7548396c Guido Trotter
753 7548396c Guido Trotter
  @classmethod
754 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
755 263b8de6 Guido Trotter
    """Check pid file for instance information.
756 263b8de6 Guido Trotter

757 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
758 263b8de6 Guido Trotter
    information from its command line.
759 263b8de6 Guido Trotter

760 263b8de6 Guido Trotter
    @type pid: string or int
761 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
762 263b8de6 Guido Trotter
    @rtype: tuple
763 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
764 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
765 263b8de6 Guido Trotter

766 263b8de6 Guido Trotter
    """
767 263b8de6 Guido Trotter
    alive = utils.IsProcessAlive(pid)
768 263b8de6 Guido Trotter
    if not alive:
769 263b8de6 Guido Trotter
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
770 263b8de6 Guido Trotter
771 263b8de6 Guido Trotter
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
772 263b8de6 Guido Trotter
    try:
773 263b8de6 Guido Trotter
      cmdline = utils.ReadFile(cmdline_file)
774 263b8de6 Guido Trotter
    except EnvironmentError, err:
775 263b8de6 Guido Trotter
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
776 263b8de6 Guido Trotter
                                   (pid, err))
777 263b8de6 Guido Trotter
778 263b8de6 Guido Trotter
    instance = None
779 263b8de6 Guido Trotter
    memory = 0
780 263b8de6 Guido Trotter
    vcpus = 0
781 263b8de6 Guido Trotter
782 d0c8c01d Iustin Pop
    arg_list = cmdline.split("\x00")
783 263b8de6 Guido Trotter
    while arg_list:
784 e687ec01 Michael Hanselmann
      arg = arg_list.pop(0)
785 263b8de6 Guido Trotter
      if arg == "-name":
786 263b8de6 Guido Trotter
        instance = arg_list.pop(0)
787 263b8de6 Guido Trotter
      elif arg == "-m":
788 263b8de6 Guido Trotter
        memory = int(arg_list.pop(0))
789 263b8de6 Guido Trotter
      elif arg == "-smp":
790 4888a609 Guido Trotter
        vcpus = int(arg_list.pop(0).split(",")[0])
791 263b8de6 Guido Trotter
792 263b8de6 Guido Trotter
    if instance is None:
793 263b8de6 Guido Trotter
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
794 263b8de6 Guido Trotter
                                   " instance" % pid)
795 263b8de6 Guido Trotter
796 263b8de6 Guido Trotter
    return (instance, memory, vcpus)
797 263b8de6 Guido Trotter
798 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
799 263b8de6 Guido Trotter
    """Returns the instance pidfile, pid, and liveness.
800 263b8de6 Guido Trotter

801 263b8de6 Guido Trotter
    @type instance_name: string
802 263b8de6 Guido Trotter
    @param instance_name: instance name
803 263b8de6 Guido Trotter
    @rtype: tuple
804 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
805 1f8b3a27 Guido Trotter

806 1f8b3a27 Guido Trotter
    """
807 98ec75d6 Iustin Pop
    pidfile = self._InstancePidFile(instance_name)
808 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
809 263b8de6 Guido Trotter
810 263b8de6 Guido Trotter
    alive = False
811 263b8de6 Guido Trotter
    try:
812 263b8de6 Guido Trotter
      cmd_instance = self._InstancePidInfo(pid)[0]
813 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
814 263b8de6 Guido Trotter
    except errors.HypervisorError:
815 263b8de6 Guido Trotter
      pass
816 1f8b3a27 Guido Trotter
817 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
818 1f8b3a27 Guido Trotter
819 5905901c Iustin Pop
  def _CheckDown(self, instance_name):
820 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
821 5905901c Iustin Pop

822 5905901c Iustin Pop
    """
823 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
824 5905901c Iustin Pop
    if alive:
825 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
826 5905901c Iustin Pop
                                   (instance_name, "already running"))
827 5905901c Iustin Pop
828 0df4d98a Guido Trotter
  @classmethod
829 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
830 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
831 c4fbefc8 Guido Trotter

832 c4fbefc8 Guido Trotter
    """
833 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
834 c4fbefc8 Guido Trotter
835 0df4d98a Guido Trotter
  @classmethod
836 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
837 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
838 c4fbefc8 Guido Trotter

839 c4fbefc8 Guido Trotter
    """
840 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
841 c4fbefc8 Guido Trotter
842 91c10532 Andrea Spadaccini
  @classmethod
843 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
844 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
845 91c10532 Andrea Spadaccini

846 91c10532 Andrea Spadaccini
    """
847 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
848 91c10532 Andrea Spadaccini
849 86d6bc2a Guido Trotter
  @staticmethod
850 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
851 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
852 86d6bc2a Guido Trotter

853 86d6bc2a Guido Trotter
    If we have a new-enough socat we can use raw mode with an escape character.
854 86d6bc2a Guido Trotter

855 86d6bc2a Guido Trotter
    """
856 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
857 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
858 86d6bc2a Guido Trotter
    else:
859 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
860 86d6bc2a Guido Trotter
861 0df4d98a Guido Trotter
  @classmethod
862 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
863 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
864 38e250ba Guido Trotter

865 38e250ba Guido Trotter
    """
866 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
867 38e250ba Guido Trotter
868 7e66c35b Guido Trotter
  @classmethod
869 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
870 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
871 547a63b7 Balazs Lecz

872 547a63b7 Balazs Lecz
    """
873 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
874 547a63b7 Balazs Lecz
875 547a63b7 Balazs Lecz
  @classmethod
876 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
877 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
878 5d9bfd87 Apollon Oikonomopoulos
    given instance.
879 5d9bfd87 Apollon Oikonomopoulos

880 5d9bfd87 Apollon Oikonomopoulos
    """
881 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
882 5d9bfd87 Apollon Oikonomopoulos
883 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
884 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
885 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
886 5d9bfd87 Apollon Oikonomopoulos

887 5d9bfd87 Apollon Oikonomopoulos
    """
888 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
889 5d9bfd87 Apollon Oikonomopoulos
890 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
891 4f580fef Sรฉbastien Bocahu
  def _InstanceKeymapFile(cls, instance_name):
892 4f580fef Sรฉbastien Bocahu
    """Returns the name of the file containing the keymap for a given instance
893 4f580fef Sรฉbastien Bocahu

894 4f580fef Sรฉbastien Bocahu
    """
895 4f580fef Sรฉbastien Bocahu
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
896 4f580fef Sรฉbastien Bocahu
897 4f580fef Sรฉbastien Bocahu
  @classmethod
898 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
899 7548396c Guido Trotter
    """Try to read a uid file
900 7548396c Guido Trotter

901 7548396c Guido Trotter
    """
902 7548396c Guido Trotter
    if os.path.exists(uid_file):
903 7548396c Guido Trotter
      try:
904 682f7601 Guido Trotter
        uid = int(utils.ReadOneLineFile(uid_file))
905 aa0b600b Guido Trotter
        return uid
906 7548396c Guido Trotter
      except EnvironmentError:
907 7548396c Guido Trotter
        logging.warning("Can't read uid file", exc_info=True)
908 7548396c Guido Trotter
      except (TypeError, ValueError):
909 7548396c Guido Trotter
        logging.warning("Can't parse uid file contents", exc_info=True)
910 aa0b600b Guido Trotter
    return None
911 7548396c Guido Trotter
912 7548396c Guido Trotter
  @classmethod
913 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
914 547a63b7 Balazs Lecz
    """Removes an instance's rutime sockets/files/dirs.
915 7e66c35b Guido Trotter

916 7e66c35b Guido Trotter
    """
917 7e66c35b Guido Trotter
    utils.RemoveFile(pidfile)
918 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
919 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceSerial(instance_name))
920 91c10532 Andrea Spadaccini
    utils.RemoveFile(cls._InstanceQmpMonitor(instance_name))
921 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
922 4f580fef Sรฉbastien Bocahu
    utils.RemoveFile(cls._InstanceKeymapFile(instance_name))
923 7548396c Guido Trotter
    uid_file = cls._InstanceUidFile(instance_name)
924 7548396c Guido Trotter
    uid = cls._TryReadUidFile(uid_file)
925 7548396c Guido Trotter
    utils.RemoveFile(uid_file)
926 7548396c Guido Trotter
    if uid is not None:
927 7548396c Guido Trotter
      uidpool.ReleaseUid(uid)
928 7be85163 Guido Trotter
    try:
929 7be85163 Guido Trotter
      shutil.rmtree(cls._InstanceNICDir(instance_name))
930 7be85163 Guido Trotter
    except OSError, err:
931 7be85163 Guido Trotter
      if err.errno != errno.ENOENT:
932 7be85163 Guido Trotter
        raise
933 547a63b7 Balazs Lecz
    try:
934 547a63b7 Balazs Lecz
      chroot_dir = cls._InstanceChrootDir(instance_name)
935 547a63b7 Balazs Lecz
      utils.RemoveDir(chroot_dir)
936 547a63b7 Balazs Lecz
    except OSError, err:
937 547a63b7 Balazs Lecz
      if err.errno == errno.ENOTEMPTY:
938 547a63b7 Balazs Lecz
        # The chroot directory is expected to be empty, but it isn't.
939 547a63b7 Balazs Lecz
        new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
940 547a63b7 Balazs Lecz
                                          prefix="%s-%s-" %
941 547a63b7 Balazs Lecz
                                          (instance_name,
942 547a63b7 Balazs Lecz
                                           utils.TimestampForFilename()))
943 547a63b7 Balazs Lecz
        logging.warning("The chroot directory of instance %s can not be"
944 547a63b7 Balazs Lecz
                        " removed as it is not empty. Moving it to the"
945 547a63b7 Balazs Lecz
                        " quarantine instead. Please investigate the"
946 547a63b7 Balazs Lecz
                        " contents (%s) and clean up manually",
947 547a63b7 Balazs Lecz
                        instance_name, new_chroot_dir)
948 547a63b7 Balazs Lecz
        utils.RenameFile(chroot_dir, new_chroot_dir)
949 547a63b7 Balazs Lecz
      else:
950 547a63b7 Balazs Lecz
        raise
951 7e66c35b Guido Trotter
952 748e4b5a Michael Hanselmann
  @staticmethod
953 5d9bfd87 Apollon Oikonomopoulos
  def _ConfigureNIC(instance, seq, nic, tap):
954 5d9bfd87 Apollon Oikonomopoulos
    """Run the network configuration script for a specified NIC
955 eb58f9b1 Guido Trotter

956 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
957 eb58f9b1 Guido Trotter
    @type instance: instance object
958 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
959 eb58f9b1 Guido Trotter
    @type seq: int
960 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
961 eb58f9b1 Guido Trotter
    @type nic: nic object
962 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
963 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
964 eb58f9b1 Guido Trotter

965 eb58f9b1 Guido Trotter
    """
966 5d9bfd87 Apollon Oikonomopoulos
    if instance.tags:
967 5d9bfd87 Apollon Oikonomopoulos
      tags = " ".join(instance.tags)
968 5d9bfd87 Apollon Oikonomopoulos
    else:
969 5d9bfd87 Apollon Oikonomopoulos
      tags = ""
970 5d9bfd87 Apollon Oikonomopoulos
971 5d9bfd87 Apollon Oikonomopoulos
    env = {
972 5d9bfd87 Apollon Oikonomopoulos
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
973 5d9bfd87 Apollon Oikonomopoulos
      "INSTANCE": instance.name,
974 5d9bfd87 Apollon Oikonomopoulos
      "MAC": nic.mac,
975 5d9bfd87 Apollon Oikonomopoulos
      "MODE": nic.nicparams[constants.NIC_MODE],
976 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE": tap,
977 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE_INDEX": str(seq),
978 5d9bfd87 Apollon Oikonomopoulos
      "TAGS": tags,
979 5d9bfd87 Apollon Oikonomopoulos
    }
980 5d9bfd87 Apollon Oikonomopoulos
981 5d9bfd87 Apollon Oikonomopoulos
    if nic.ip:
982 5d9bfd87 Apollon Oikonomopoulos
      env["IP"] = nic.ip
983 5d9bfd87 Apollon Oikonomopoulos
984 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_LINK]:
985 5d9bfd87 Apollon Oikonomopoulos
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
986 5d9bfd87 Apollon Oikonomopoulos
987 a5ad5e58 Apollon Oikonomopoulos
    if nic.network:
988 cbe4a0a5 Dimitris Aragiorgis
      n = objects.Network.FromDict(nic.netinfo)
989 7e8f03e3 Dimitris Aragiorgis
      env.update(n.HooksDict())
990 a5ad5e58 Apollon Oikonomopoulos
991 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
992 5d9bfd87 Apollon Oikonomopoulos
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
993 5d9bfd87 Apollon Oikonomopoulos
994 9d9bded1 Michael Hanselmann
    result = utils.RunCmd([pathutils.KVM_IFUP, tap], env=env)
995 5d9bfd87 Apollon Oikonomopoulos
    if result.failed:
996 afa9bb2e Michael Hanselmann
      raise errors.HypervisorError("Failed to configure interface %s: %s;"
997 afa9bb2e Michael Hanselmann
                                   " network configuration script output: %s" %
998 5d9bfd87 Apollon Oikonomopoulos
                                   (tap, result.fail_reason, result.output))
999 eb58f9b1 Guido Trotter
1000 b693125f Tsachy Shacham
  @staticmethod
1001 b693125f Tsachy Shacham
  def _VerifyAffinityPackage():
1002 b693125f Tsachy Shacham
    if affinity is None:
1003 b693125f Tsachy Shacham
      raise errors.HypervisorError("affinity Python package not"
1004 5ae4945a Iustin Pop
                                   " found; cannot use CPU pinning under KVM")
1005 b693125f Tsachy Shacham
1006 b693125f Tsachy Shacham
  @staticmethod
1007 b693125f Tsachy Shacham
  def _BuildAffinityCpuMask(cpu_list):
1008 b693125f Tsachy Shacham
    """Create a CPU mask suitable for sched_setaffinity from a list of
1009 b693125f Tsachy Shacham
    CPUs.
1010 b693125f Tsachy Shacham

1011 b693125f Tsachy Shacham
    See man taskset for more info on sched_setaffinity masks.
1012 b693125f Tsachy Shacham
    For example: [ 0, 2, 5, 6 ] will return 101 (0x65, 0..01100101).
1013 b693125f Tsachy Shacham

1014 b693125f Tsachy Shacham
    @type cpu_list: list of int
1015 b693125f Tsachy Shacham
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
1016 b693125f Tsachy Shacham
    @rtype: int
1017 b693125f Tsachy Shacham
    @return: a bit mask of CPU affinities
1018 b693125f Tsachy Shacham

1019 b693125f Tsachy Shacham
    """
1020 b693125f Tsachy Shacham
    if cpu_list == constants.CPU_PINNING_OFF:
1021 b693125f Tsachy Shacham
      return constants.CPU_PINNING_ALL_KVM
1022 b693125f Tsachy Shacham
    else:
1023 b693125f Tsachy Shacham
      return sum(2 ** cpu for cpu in cpu_list)
1024 b693125f Tsachy Shacham
1025 b693125f Tsachy Shacham
  @classmethod
1026 b693125f Tsachy Shacham
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
1027 b693125f Tsachy Shacham
    """Change CPU affinity for running VM according to given CPU mask.
1028 b693125f Tsachy Shacham

1029 b693125f Tsachy Shacham
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
1030 b693125f Tsachy Shacham
    @type cpu_mask: string
1031 b693125f Tsachy Shacham
    @param process_id: process ID of KVM process. Used to pin entire VM
1032 b693125f Tsachy Shacham
                       to physical CPUs.
1033 b693125f Tsachy Shacham
    @type process_id: int
1034 b693125f Tsachy Shacham
    @param thread_dict: map of virtual CPUs to KVM thread IDs
1035 b693125f Tsachy Shacham
    @type thread_dict: dict int:int
1036 b693125f Tsachy Shacham

1037 b693125f Tsachy Shacham
    """
1038 b693125f Tsachy Shacham
    # Convert the string CPU mask to a list of list of int's
1039 b693125f Tsachy Shacham
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
1040 b693125f Tsachy Shacham
1041 b693125f Tsachy Shacham
    if len(cpu_list) == 1:
1042 b693125f Tsachy Shacham
      all_cpu_mapping = cpu_list[0]
1043 b693125f Tsachy Shacham
      if all_cpu_mapping == constants.CPU_PINNING_OFF:
1044 b693125f Tsachy Shacham
        # If CPU pinning has 1 entry that's "all", then do nothing
1045 b693125f Tsachy Shacham
        pass
1046 b693125f Tsachy Shacham
      else:
1047 b693125f Tsachy Shacham
        # If CPU pinning has one non-all entry, map the entire VM to
1048 b693125f Tsachy Shacham
        # one set of physical CPUs
1049 b693125f Tsachy Shacham
        cls._VerifyAffinityPackage()
1050 5ae4945a Iustin Pop
        affinity.set_process_affinity_mask(
1051 5ae4945a Iustin Pop
          process_id, cls._BuildAffinityCpuMask(all_cpu_mapping))
1052 b693125f Tsachy Shacham
    else:
1053 b693125f Tsachy Shacham
      # The number of vCPUs mapped should match the number of vCPUs
1054 b693125f Tsachy Shacham
      # reported by KVM. This was already verified earlier, so
1055 b693125f Tsachy Shacham
      # here only as a sanity check.
1056 b693125f Tsachy Shacham
      assert len(thread_dict) == len(cpu_list)
1057 b693125f Tsachy Shacham
      cls._VerifyAffinityPackage()
1058 b693125f Tsachy Shacham
1059 b693125f Tsachy Shacham
      # For each vCPU, map it to the proper list of physical CPUs
1060 b693125f Tsachy Shacham
      for vcpu, i in zip(cpu_list, range(len(cpu_list))):
1061 b693125f Tsachy Shacham
        affinity.set_process_affinity_mask(thread_dict[i],
1062 5ae4945a Iustin Pop
                                           cls._BuildAffinityCpuMask(vcpu))
1063 b693125f Tsachy Shacham
1064 b693125f Tsachy Shacham
  def _GetVcpuThreadIds(self, instance_name):
1065 b693125f Tsachy Shacham
    """Get a mapping of vCPU no. to thread IDs for the instance
1066 b693125f Tsachy Shacham

1067 b693125f Tsachy Shacham
    @type instance_name: string
1068 b693125f Tsachy Shacham
    @param instance_name: instance in question
1069 b693125f Tsachy Shacham
    @rtype: dictionary of int:int
1070 b693125f Tsachy Shacham
    @return: a dictionary mapping vCPU numbers to thread IDs
1071 b693125f Tsachy Shacham

1072 b693125f Tsachy Shacham
    """
1073 b693125f Tsachy Shacham
    result = {}
1074 b693125f Tsachy Shacham
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
1075 b693125f Tsachy Shacham
    for line in output.stdout.splitlines():
1076 b693125f Tsachy Shacham
      match = self._CPU_INFO_RE.search(line)
1077 b693125f Tsachy Shacham
      if not match:
1078 b693125f Tsachy Shacham
        continue
1079 b693125f Tsachy Shacham
      grp = map(int, match.groups())
1080 b693125f Tsachy Shacham
      result[grp[0]] = grp[1]
1081 b693125f Tsachy Shacham
1082 b693125f Tsachy Shacham
    return result
1083 b693125f Tsachy Shacham
1084 1d8a7812 Andrea Spadaccini
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
1085 1d8a7812 Andrea Spadaccini
    """Complete CPU pinning.
1086 b693125f Tsachy Shacham

1087 b693125f Tsachy Shacham
    @type instance_name: string
1088 b693125f Tsachy Shacham
    @param instance_name: name of instance
1089 b693125f Tsachy Shacham
    @type cpu_mask: string
1090 b693125f Tsachy Shacham
    @param cpu_mask: CPU pinning mask as entered by user
1091 b693125f Tsachy Shacham

1092 b693125f Tsachy Shacham
    """
1093 1d8a7812 Andrea Spadaccini
    # Get KVM process ID, to be used if need to pin entire VM
1094 1d8a7812 Andrea Spadaccini
    _, pid, _ = self._InstancePidAlive(instance_name)
1095 1d8a7812 Andrea Spadaccini
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
1096 1d8a7812 Andrea Spadaccini
    thread_dict = self._GetVcpuThreadIds(instance_name)
1097 1d8a7812 Andrea Spadaccini
    # Run CPU pinning, based on configured mask
1098 1d8a7812 Andrea Spadaccini
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
1099 b693125f Tsachy Shacham
1100 eb58f9b1 Guido Trotter
  def ListInstances(self):
1101 eb58f9b1 Guido Trotter
    """Get the list of running instances.
1102 eb58f9b1 Guido Trotter

1103 c41eea6e Iustin Pop
    We can do this by listing our live instances directory and
1104 c41eea6e Iustin Pop
    checking whether the associated kvm process is still alive.
1105 eb58f9b1 Guido Trotter

1106 eb58f9b1 Guido Trotter
    """
1107 eb58f9b1 Guido Trotter
    result = []
1108 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1109 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
1110 eb58f9b1 Guido Trotter
        result.append(name)
1111 eb58f9b1 Guido Trotter
    return result
1112 eb58f9b1 Guido Trotter
1113 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
1114 eb58f9b1 Guido Trotter
    """Get instance properties.
1115 eb58f9b1 Guido Trotter

1116 4fbb3c60 Guido Trotter
    @type instance_name: string
1117 c41eea6e Iustin Pop
    @param instance_name: the instance name
1118 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
1119 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
1120 eb58f9b1 Guido Trotter

1121 eb58f9b1 Guido Trotter
    """
1122 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
1123 1f8b3a27 Guido Trotter
    if not alive:
1124 eb58f9b1 Guido Trotter
      return None
1125 eb58f9b1 Guido Trotter
1126 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
1127 fc84cd5d Guido Trotter
    istat = "---b-"
1128 eb58f9b1 Guido Trotter
    times = "0"
1129 eb58f9b1 Guido Trotter
1130 89da2ff3 Guido Trotter
    try:
1131 89da2ff3 Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
1132 89da2ff3 Guido Trotter
      qmp.connect()
1133 89da2ff3 Guido Trotter
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
1134 89da2ff3 Guido Trotter
      # Will fail if ballooning is not enabled, but we can then just resort to
1135 89da2ff3 Guido Trotter
      # the value above.
1136 89da2ff3 Guido Trotter
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
1137 89da2ff3 Guido Trotter
      memory = mem_bytes / 1048576
1138 89da2ff3 Guido Trotter
    except errors.HypervisorError:
1139 89da2ff3 Guido Trotter
      pass
1140 89da2ff3 Guido Trotter
1141 fc84cd5d Guido Trotter
    return (instance_name, pid, memory, vcpus, istat, times)
1142 eb58f9b1 Guido Trotter
1143 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
1144 eb58f9b1 Guido Trotter
    """Get properties of all instances.
1145 eb58f9b1 Guido Trotter

1146 c41eea6e Iustin Pop
    @return: list of tuples (name, id, memory, vcpus, stat, times)
1147 c41eea6e Iustin Pop

1148 eb58f9b1 Guido Trotter
    """
1149 eb58f9b1 Guido Trotter
    data = []
1150 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1151 263b8de6 Guido Trotter
      try:
1152 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
1153 263b8de6 Guido Trotter
      except errors.HypervisorError:
1154 3bc145d8 Bernardo Dal Seno
        # Ignore exceptions due to instances being shut down
1155 263b8de6 Guido Trotter
        continue
1156 263b8de6 Guido Trotter
      if info:
1157 263b8de6 Guido Trotter
        data.append(info)
1158 eb58f9b1 Guido Trotter
    return data
1159 eb58f9b1 Guido Trotter
1160 ece1057c Dimitris Aragiorgis
  def _GenerateKVMBlockDevicesOptions(self, instance, block_devices, kvmhelp):
1161 ece1057c Dimitris Aragiorgis
1162 ece1057c Dimitris Aragiorgis
    hvp = instance.hvparams
1163 ece1057c Dimitris Aragiorgis
    boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
1164 994ccaf2 Dimitris Aragiorgis
    kvm_path = hvp[constants.HV_KVM_PATH]
1165 ece1057c Dimitris Aragiorgis
1166 ece1057c Dimitris Aragiorgis
    # whether this is an older KVM version that uses the boot=on flag
1167 ece1057c Dimitris Aragiorgis
    # on devices
1168 ece1057c Dimitris Aragiorgis
    needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1169 ece1057c Dimitris Aragiorgis
1170 ece1057c Dimitris Aragiorgis
    dev_opts = []
1171 994ccaf2 Dimitris Aragiorgis
    device_driver = None
1172 ece1057c Dimitris Aragiorgis
    disk_type = hvp[constants.HV_DISK_TYPE]
1173 ece1057c Dimitris Aragiorgis
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
1174 ece1057c Dimitris Aragiorgis
      if_val = ",if=%s" % self._VIRTIO
1175 994ccaf2 Dimitris Aragiorgis
      try:
1176 994ccaf2 Dimitris Aragiorgis
        devlist = self._GetKVMOutput(kvm_path, self._KVMOPT_DEVICELIST)
1177 994ccaf2 Dimitris Aragiorgis
        if self._VIRTIO_BLK_RE.search(devlist):
1178 0288e7bf Dimitris Aragiorgis
          if_val = ",if=none"
1179 994ccaf2 Dimitris Aragiorgis
          # will be passed in -device option as driver
1180 994ccaf2 Dimitris Aragiorgis
          device_driver = self._VIRTIO_BLK_PCI
1181 994ccaf2 Dimitris Aragiorgis
      except errors.HypervisorError, _:
1182 994ccaf2 Dimitris Aragiorgis
        pass
1183 ece1057c Dimitris Aragiorgis
    else:
1184 ece1057c Dimitris Aragiorgis
      if_val = ",if=%s" % disk_type
1185 ece1057c Dimitris Aragiorgis
    # Cache mode
1186 ece1057c Dimitris Aragiorgis
    disk_cache = hvp[constants.HV_DISK_CACHE]
1187 ece1057c Dimitris Aragiorgis
    if instance.disk_template in constants.DTS_EXT_MIRROR:
1188 ece1057c Dimitris Aragiorgis
      if disk_cache != "none":
1189 ece1057c Dimitris Aragiorgis
        # TODO: make this a hard error, instead of a silent overwrite
1190 ece1057c Dimitris Aragiorgis
        logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
1191 ece1057c Dimitris Aragiorgis
                        " to prevent shared storage corruption on migration",
1192 ece1057c Dimitris Aragiorgis
                        disk_cache)
1193 ece1057c Dimitris Aragiorgis
      cache_val = ",cache=none"
1194 ece1057c Dimitris Aragiorgis
    elif disk_cache != constants.HT_CACHE_DEFAULT:
1195 ece1057c Dimitris Aragiorgis
      cache_val = ",cache=%s" % disk_cache
1196 ece1057c Dimitris Aragiorgis
    else:
1197 ece1057c Dimitris Aragiorgis
      cache_val = ""
1198 ece1057c Dimitris Aragiorgis
    for cfdev, dev_path in block_devices:
1199 ece1057c Dimitris Aragiorgis
      if cfdev.mode != constants.DISK_RDWR:
1200 ece1057c Dimitris Aragiorgis
        raise errors.HypervisorError("Instance has read-only disks which"
1201 ece1057c Dimitris Aragiorgis
                                     " are not supported by KVM")
1202 ece1057c Dimitris Aragiorgis
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
1203 ece1057c Dimitris Aragiorgis
      boot_val = ""
1204 ece1057c Dimitris Aragiorgis
      if boot_disk:
1205 ece1057c Dimitris Aragiorgis
        dev_opts.extend(["-boot", "c"])
1206 ece1057c Dimitris Aragiorgis
        boot_disk = False
1207 ece1057c Dimitris Aragiorgis
        if needs_boot_flag and disk_type != constants.HT_DISK_IDE:
1208 ece1057c Dimitris Aragiorgis
          boot_val = ",boot=on"
1209 ece1057c Dimitris Aragiorgis
      drive_val = "file=%s,format=raw%s%s%s" % \
1210 ece1057c Dimitris Aragiorgis
                  (dev_path, if_val, boot_val, cache_val)
1211 ece1057c Dimitris Aragiorgis
1212 994ccaf2 Dimitris Aragiorgis
      if device_driver:
1213 0288e7bf Dimitris Aragiorgis
        # block_devices are the 4th entry of runtime file that did not exist in
1214 0288e7bf Dimitris Aragiorgis
        # the past. That means that cfdev should always have pci slot and
1215 0288e7bf Dimitris Aragiorgis
        # _GenerateDeviceKVMId() will not raise a exception.
1216 0288e7bf Dimitris Aragiorgis
        kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_DISK, cfdev)
1217 0288e7bf Dimitris Aragiorgis
        drive_val += (",id=%s" % kvm_devid)
1218 0288e7bf Dimitris Aragiorgis
        drive_val += (",bus=0,unit=%d" % cfdev.pci)
1219 0288e7bf Dimitris Aragiorgis
        dev_val = ("%s,drive=%s,id=%s" %
1220 0288e7bf Dimitris Aragiorgis
                   (device_driver, kvm_devid, kvm_devid))
1221 0288e7bf Dimitris Aragiorgis
        dev_val += ",bus=pci.0,addr=%s" % hex(cfdev.pci)
1222 0288e7bf Dimitris Aragiorgis
        dev_opts.extend(["-device", dev_val])
1223 0288e7bf Dimitris Aragiorgis
1224 ece1057c Dimitris Aragiorgis
      dev_opts.extend(["-drive", drive_val])
1225 ece1057c Dimitris Aragiorgis
1226 ece1057c Dimitris Aragiorgis
    return dev_opts
1227 ece1057c Dimitris Aragiorgis
1228 b73f1c59 Guido Trotter
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused,
1229 b73f1c59 Guido Trotter
                          kvmhelp):
1230 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
1231 eb58f9b1 Guido Trotter

1232 b73f1c59 Guido Trotter
    @type kvmhelp: string
1233 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1234 839642c2 Iustin Pop
    @attention: this function must not have any side-effects; for
1235 839642c2 Iustin Pop
        example, it must not write to the filesystem, or read values
1236 839642c2 Iustin Pop
        from the current system the are expected to differ between
1237 839642c2 Iustin Pop
        nodes, since it is only run once at instance startup;
1238 839642c2 Iustin Pop
        actions/kvm arguments that can vary between systems should be
1239 839642c2 Iustin Pop
        done in L{_ExecuteKVMRuntime}
1240 839642c2 Iustin Pop

1241 eb58f9b1 Guido Trotter
    """
1242 4888a609 Guido Trotter
    # pylint: disable=R0912,R0914,R0915
1243 4888a609 Guido Trotter
    hvp = instance.hvparams
1244 81e265f5 Guido Trotter
    self.ValidateParameters(hvp)
1245 4304964a Guido Trotter
1246 e687ec01 Michael Hanselmann
    pidfile = self._InstancePidFile(instance.name)
1247 4b9638dc Guido Trotter
    kvm = hvp[constants.HV_KVM_PATH]
1248 eb58f9b1 Guido Trotter
    kvm_cmd = [kvm]
1249 c6a39fc2 Guido Trotter
    # used just by the vnc server, if enabled
1250 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-name", instance.name])
1251 f5a4b9ce Guido Trotter
    kvm_cmd.extend(["-m", instance.beparams[constants.BE_MAXMEM]])
1252 4888a609 Guido Trotter
1253 4888a609 Guido Trotter
    smp_list = ["%s" % instance.beparams[constants.BE_VCPUS]]
1254 4888a609 Guido Trotter
    if hvp[constants.HV_CPU_CORES]:
1255 4888a609 Guido Trotter
      smp_list.append("cores=%s" % hvp[constants.HV_CPU_CORES])
1256 4888a609 Guido Trotter
    if hvp[constants.HV_CPU_THREADS]:
1257 4888a609 Guido Trotter
      smp_list.append("threads=%s" % hvp[constants.HV_CPU_THREADS])
1258 4888a609 Guido Trotter
    if hvp[constants.HV_CPU_SOCKETS]:
1259 4888a609 Guido Trotter
      smp_list.append("sockets=%s" % hvp[constants.HV_CPU_SOCKETS])
1260 4888a609 Guido Trotter
1261 4888a609 Guido Trotter
    kvm_cmd.extend(["-smp", ",".join(smp_list)])
1262 4888a609 Guido Trotter
1263 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-pidfile", pidfile])
1264 fcf5b670 Guido Trotter
    kvm_cmd.extend(["-balloon", "virtio"])
1265 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-daemonize"])
1266 6b5605e8 Iustin Pop
    if not instance.hvparams[constants.HV_ACPI]:
1267 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-no-acpi"])
1268 990ade2d Stephen Shirley
    if instance.hvparams[constants.HV_REBOOT_BEHAVIOR] == \
1269 990ade2d Stephen Shirley
        constants.INSTANCE_REBOOT_EXIT:
1270 990ade2d Stephen Shirley
      kvm_cmd.extend(["-no-reboot"])
1271 eb58f9b1 Guido Trotter
1272 4ab75599 Dimitris Aragiorgis
    mversion = hvp[constants.HV_KVM_MACHINE_VERSION]
1273 4ab75599 Dimitris Aragiorgis
    if not mversion:
1274 4b9638dc Guido Trotter
      mversion = self._GetDefaultMachineVersion(kvm)
1275 8cb5634a Guido Trotter
    if self._MACHINE_RE.search(kvmhelp):
1276 8cb5634a Guido Trotter
      # TODO (2.8): kernel_irqchip and kvm_shadow_mem machine properties, as
1277 8cb5634a Guido Trotter
      # extra hypervisor parameters. We should also investigate whether and how
1278 8cb5634a Guido Trotter
      # shadow_mem should be considered for the resource model.
1279 8cb5634a Guido Trotter
      if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED):
1280 8cb5634a Guido Trotter
        specprop = ",accel=kvm"
1281 8cb5634a Guido Trotter
      else:
1282 8cb5634a Guido Trotter
        specprop = ""
1283 8cb5634a Guido Trotter
      machinespec = "%s%s" % (mversion, specprop)
1284 8cb5634a Guido Trotter
      kvm_cmd.extend(["-machine", machinespec])
1285 8cb5634a Guido Trotter
    else:
1286 8cb5634a Guido Trotter
      kvm_cmd.extend(["-M", mversion])
1287 8cb5634a Guido Trotter
      if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED and
1288 8cb5634a Guido Trotter
          self._ENABLE_KVM_RE.search(kvmhelp)):
1289 8cb5634a Guido Trotter
        kvm_cmd.extend(["-enable-kvm"])
1290 8cb5634a Guido Trotter
      elif (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED and
1291 8cb5634a Guido Trotter
            self._DISABLE_KVM_RE.search(kvmhelp)):
1292 8cb5634a Guido Trotter
        kvm_cmd.extend(["-disable-kvm"])
1293 4ab75599 Dimitris Aragiorgis
1294 2b846304 Iustin Pop
    kernel_path = hvp[constants.HV_KERNEL_PATH]
1295 2b846304 Iustin Pop
    if kernel_path:
1296 ece1057c Dimitris Aragiorgis
      boot_cdrom = boot_floppy = boot_network = False
1297 2b846304 Iustin Pop
    else:
1298 2b846304 Iustin Pop
      boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
1299 2b846304 Iustin Pop
      boot_floppy = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_FLOPPY
1300 2b846304 Iustin Pop
      boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
1301 8745c3d7 Guido Trotter
1302 b693125f Tsachy Shacham
    if startup_paused:
1303 b693125f Tsachy Shacham
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1304 b693125f Tsachy Shacham
1305 8745c3d7 Guido Trotter
    if boot_network:
1306 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-boot", "n"])
1307 1213604d Guido Trotter
1308 24be50e0 Iustin Pop
    # whether this is an older KVM version that uses the boot=on flag
1309 24be50e0 Iustin Pop
    # on devices
1310 0ad7f5d8 Guido Trotter
    needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1311 24be50e0 Iustin Pop
1312 a985b417 Iustin Pop
    disk_type = hvp[constants.HV_DISK_TYPE]
1313 eb58f9b1 Guido Trotter
1314 cc130cc7 Marco Casavecchia
    #Now we can specify a different device type for CDROM devices.
1315 cc130cc7 Marco Casavecchia
    cdrom_disk_type = hvp[constants.HV_KVM_CDROM_DISK_TYPE]
1316 cc130cc7 Marco Casavecchia
    if not cdrom_disk_type:
1317 cc130cc7 Marco Casavecchia
      cdrom_disk_type = disk_type
1318 cc130cc7 Marco Casavecchia
1319 a985b417 Iustin Pop
    iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
1320 66d5dbef Guido Trotter
    if iso_image:
1321 d0c8c01d Iustin Pop
      options = ",format=raw,media=cdrom"
1322 24be50e0 Iustin Pop
      # set cdrom 'if' type
1323 66d5dbef Guido Trotter
      if boot_cdrom:
1324 24be50e0 Iustin Pop
        actual_cdrom_type = constants.HT_DISK_IDE
1325 24be50e0 Iustin Pop
      elif cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1326 24be50e0 Iustin Pop
        actual_cdrom_type = "virtio"
1327 9dd363eb Guido Trotter
      else:
1328 24be50e0 Iustin Pop
        actual_cdrom_type = cdrom_disk_type
1329 24be50e0 Iustin Pop
      if_val = ",if=%s" % actual_cdrom_type
1330 24be50e0 Iustin Pop
      # set boot flag, if needed
1331 24be50e0 Iustin Pop
      boot_val = ""
1332 24be50e0 Iustin Pop
      if boot_cdrom:
1333 24be50e0 Iustin Pop
        kvm_cmd.extend(["-boot", "d"])
1334 24be50e0 Iustin Pop
        if needs_boot_flag:
1335 24be50e0 Iustin Pop
          boot_val = ",boot=on"
1336 24be50e0 Iustin Pop
      # and finally build the entire '-drive' value
1337 24be50e0 Iustin Pop
      drive_val = "file=%s%s%s%s" % (iso_image, options, if_val, boot_val)
1338 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1339 66d5dbef Guido Trotter
1340 cc130cc7 Marco Casavecchia
    iso_image2 = hvp[constants.HV_KVM_CDROM2_IMAGE_PATH]
1341 cc130cc7 Marco Casavecchia
    if iso_image2:
1342 d0c8c01d Iustin Pop
      options = ",format=raw,media=cdrom"
1343 cc130cc7 Marco Casavecchia
      if cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1344 d0c8c01d Iustin Pop
        if_val = ",if=virtio"
1345 cc130cc7 Marco Casavecchia
      else:
1346 d0c8c01d Iustin Pop
        if_val = ",if=%s" % cdrom_disk_type
1347 24be50e0 Iustin Pop
      drive_val = "file=%s%s%s" % (iso_image2, options, if_val)
1348 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1349 cc130cc7 Marco Casavecchia
1350 cc130cc7 Marco Casavecchia
    floppy_image = hvp[constants.HV_KVM_FLOPPY_IMAGE_PATH]
1351 cc130cc7 Marco Casavecchia
    if floppy_image:
1352 d0c8c01d Iustin Pop
      options = ",format=raw,media=disk"
1353 cc130cc7 Marco Casavecchia
      if boot_floppy:
1354 d0c8c01d Iustin Pop
        kvm_cmd.extend(["-boot", "a"])
1355 d0c8c01d Iustin Pop
        options = "%s,boot=on" % options
1356 d0c8c01d Iustin Pop
      if_val = ",if=floppy"
1357 d0c8c01d Iustin Pop
      options = "%s%s" % (options, if_val)
1358 d0c8c01d Iustin Pop
      drive_val = "file=%s%s" % (floppy_image, options)
1359 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1360 cc130cc7 Marco Casavecchia
1361 df5ab9f0 Guido Trotter
    if kernel_path:
1362 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-kernel", kernel_path])
1363 a985b417 Iustin Pop
      initrd_path = hvp[constants.HV_INITRD_PATH]
1364 df5ab9f0 Guido Trotter
      if initrd_path:
1365 d0c8c01d Iustin Pop
        kvm_cmd.extend(["-initrd", initrd_path])
1366 d0c8c01d Iustin Pop
      root_append = ["root=%s" % hvp[constants.HV_ROOT_PATH],
1367 07813a9e Iustin Pop
                     hvp[constants.HV_KERNEL_ARGS]]
1368 07813a9e Iustin Pop
      if hvp[constants.HV_SERIAL_CONSOLE]:
1369 14fd6c81 Guido Trotter
        serial_speed = hvp[constants.HV_SERIAL_SPEED]
1370 14fd6c81 Guido Trotter
        root_append.append("console=ttyS0,%s" % serial_speed)
1371 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-append", " ".join(root_append)])
1372 eb58f9b1 Guido Trotter
1373 4f958b0b Miguel Di Ciurcio Filho
    mem_path = hvp[constants.HV_MEM_PATH]
1374 4f958b0b Miguel Di Ciurcio Filho
    if mem_path:
1375 9d3015f9 Guido Trotter
      kvm_cmd.extend(["-mem-path", mem_path, "-mem-prealloc"])
1376 4f958b0b Miguel Di Ciurcio Filho
1377 596b2459 Guido Trotter
    monitor_dev = ("unix:%s,server,nowait" %
1378 596b2459 Guido Trotter
                   self._InstanceMonitor(instance.name))
1379 596b2459 Guido Trotter
    kvm_cmd.extend(["-monitor", monitor_dev])
1380 596b2459 Guido Trotter
    if hvp[constants.HV_SERIAL_CONSOLE]:
1381 596b2459 Guido Trotter
      serial_dev = ("unix:%s,server,nowait" %
1382 596b2459 Guido Trotter
                    self._InstanceSerial(instance.name))
1383 596b2459 Guido Trotter
      kvm_cmd.extend(["-serial", serial_dev])
1384 596b2459 Guido Trotter
    else:
1385 596b2459 Guido Trotter
      kvm_cmd.extend(["-serial", "none"])
1386 596b2459 Guido Trotter
1387 a985b417 Iustin Pop
    mouse_type = hvp[constants.HV_USB_MOUSE]
1388 31f6f67a Guido Trotter
    vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
1389 596b2459 Guido Trotter
    spice_bind = hvp[constants.HV_KVM_SPICE_BIND]
1390 596b2459 Guido Trotter
    spice_ip_version = None
1391 31f6f67a Guido Trotter
1392 a900a30c Guido Trotter
    kvm_cmd.extend(["-usb"])
1393 a900a30c Guido Trotter
1394 11344a50 Guido Trotter
    if mouse_type:
1395 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-usbdevice", mouse_type])
1396 31f6f67a Guido Trotter
    elif vnc_bind_address:
1397 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-usbdevice", constants.HT_MOUSE_TABLET])
1398 11344a50 Guido Trotter
1399 8470c8db Guido Trotter
    if vnc_bind_address:
1400 8b312c1d Manuel Franceschini
      if netutils.IP4Address.IsValid(vnc_bind_address):
1401 377d74c9 Guido Trotter
        if instance.network_port > constants.VNC_BASE_PORT:
1402 377d74c9 Guido Trotter
          display = instance.network_port - constants.VNC_BASE_PORT
1403 14f5f1b6 Manuel Franceschini
          if vnc_bind_address == constants.IP4_ADDRESS_ANY:
1404 d0c8c01d Iustin Pop
            vnc_arg = ":%d" % (display)
1405 8447f52b Guido Trotter
          else:
1406 d0c8c01d Iustin Pop
            vnc_arg = "%s:%d" % (vnc_bind_address, display)
1407 8470c8db Guido Trotter
        else:
1408 afa9bb2e Michael Hanselmann
          logging.error("Network port is not a valid VNC display (%d < %d),"
1409 afa9bb2e Michael Hanselmann
                        " not starting VNC",
1410 afa9bb2e Michael Hanselmann
                        instance.network_port, constants.VNC_BASE_PORT)
1411 d0c8c01d Iustin Pop
          vnc_arg = "none"
1412 8b2d1013 Guido Trotter
1413 8b2d1013 Guido Trotter
        # Only allow tls and other option when not binding to a file, for now.
1414 8b2d1013 Guido Trotter
        # kvm/qemu gets confused otherwise about the filename to use.
1415 d0c8c01d Iustin Pop
        vnc_append = ""
1416 a985b417 Iustin Pop
        if hvp[constants.HV_VNC_TLS]:
1417 d0c8c01d Iustin Pop
          vnc_append = "%s,tls" % vnc_append
1418 a985b417 Iustin Pop
          if hvp[constants.HV_VNC_X509_VERIFY]:
1419 d0c8c01d Iustin Pop
            vnc_append = "%s,x509verify=%s" % (vnc_append,
1420 a985b417 Iustin Pop
                                               hvp[constants.HV_VNC_X509])
1421 a985b417 Iustin Pop
          elif hvp[constants.HV_VNC_X509]:
1422 d0c8c01d Iustin Pop
            vnc_append = "%s,x509=%s" % (vnc_append,
1423 a985b417 Iustin Pop
                                         hvp[constants.HV_VNC_X509])
1424 6e6bb8d5 Guido Trotter
        if hvp[constants.HV_VNC_PASSWORD_FILE]:
1425 d0c8c01d Iustin Pop
          vnc_append = "%s,password" % vnc_append
1426 6e6bb8d5 Guido Trotter
1427 d0c8c01d Iustin Pop
        vnc_arg = "%s%s" % (vnc_arg, vnc_append)
1428 8b2d1013 Guido Trotter
1429 8470c8db Guido Trotter
      else:
1430 d0c8c01d Iustin Pop
        vnc_arg = "unix:%s/%s.vnc" % (vnc_bind_address, instance.name)
1431 8b2d1013 Guido Trotter
1432 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-vnc", vnc_arg])
1433 596b2459 Guido Trotter
    elif spice_bind:
1434 839642c2 Iustin Pop
      # FIXME: this is wrong here; the iface ip address differs
1435 839642c2 Iustin Pop
      # between systems, so it should be done in _ExecuteKVMRuntime
1436 b1cb62bd Andrea Spadaccini
      if netutils.IsValidInterface(spice_bind):
1437 b1cb62bd Andrea Spadaccini
        # The user specified a network interface, we have to figure out the IP
1438 b1cb62bd Andrea Spadaccini
        # address.
1439 b1cb62bd Andrea Spadaccini
        addresses = netutils.GetInterfaceIpAddresses(spice_bind)
1440 b1cb62bd Andrea Spadaccini
        spice_ip_version = hvp[constants.HV_KVM_SPICE_IP_VERSION]
1441 b1cb62bd Andrea Spadaccini
1442 b1cb62bd Andrea Spadaccini
        # if the user specified an IP version and the interface does not
1443 b1cb62bd Andrea Spadaccini
        # have that kind of IP addresses, throw an exception
1444 b1cb62bd Andrea Spadaccini
        if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1445 b1cb62bd Andrea Spadaccini
          if not addresses[spice_ip_version]:
1446 afa9bb2e Michael Hanselmann
            raise errors.HypervisorError("SPICE: Unable to get an IPv%s address"
1447 b1cb62bd Andrea Spadaccini
                                         " for %s" % (spice_ip_version,
1448 b1cb62bd Andrea Spadaccini
                                                      spice_bind))
1449 b1cb62bd Andrea Spadaccini
1450 b1cb62bd Andrea Spadaccini
        # the user did not specify an IP version, we have to figure it out
1451 b1cb62bd Andrea Spadaccini
        elif (addresses[constants.IP4_VERSION] and
1452 b1cb62bd Andrea Spadaccini
              addresses[constants.IP6_VERSION]):
1453 b1cb62bd Andrea Spadaccini
          # we have both ipv4 and ipv6, let's use the cluster default IP
1454 b1cb62bd Andrea Spadaccini
          # version
1455 b1cb62bd Andrea Spadaccini
          cluster_family = ssconf.SimpleStore().GetPrimaryIPFamily()
1456 65107a2f Michael Hanselmann
          spice_ip_version = \
1457 65107a2f Michael Hanselmann
            netutils.IPAddress.GetVersionFromAddressFamily(cluster_family)
1458 b1cb62bd Andrea Spadaccini
        elif addresses[constants.IP4_VERSION]:
1459 b1cb62bd Andrea Spadaccini
          spice_ip_version = constants.IP4_VERSION
1460 b845c8a1 Andrea Spadaccini
        elif addresses[constants.IP6_VERSION]:
1461 b1cb62bd Andrea Spadaccini
          spice_ip_version = constants.IP6_VERSION
1462 b845c8a1 Andrea Spadaccini
        else:
1463 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Unable to get an IP address"
1464 b845c8a1 Andrea Spadaccini
                                       " for %s" % (spice_bind))
1465 b1cb62bd Andrea Spadaccini
1466 b1cb62bd Andrea Spadaccini
        spice_address = addresses[spice_ip_version][0]
1467 b1cb62bd Andrea Spadaccini
1468 b1cb62bd Andrea Spadaccini
      else:
1469 b1cb62bd Andrea Spadaccini
        # spice_bind is known to be a valid IP address, because
1470 b1cb62bd Andrea Spadaccini
        # ValidateParameters checked it.
1471 b1cb62bd Andrea Spadaccini
        spice_address = spice_bind
1472 b1cb62bd Andrea Spadaccini
1473 bfe86c76 Andrea Spadaccini
      spice_arg = "addr=%s" % spice_address
1474 bfe86c76 Andrea Spadaccini
      if hvp[constants.HV_KVM_SPICE_USE_TLS]:
1475 5ae4945a Iustin Pop
        spice_arg = ("%s,tls-port=%s,x509-cacert-file=%s" %
1476 5ae4945a Iustin Pop
                     (spice_arg, instance.network_port,
1477 9d9bded1 Michael Hanselmann
                      pathutils.SPICE_CACERT_FILE))
1478 5ae4945a Iustin Pop
        spice_arg = ("%s,x509-key-file=%s,x509-cert-file=%s" %
1479 9d9bded1 Michael Hanselmann
                     (spice_arg, pathutils.SPICE_CERT_FILE,
1480 9d9bded1 Michael Hanselmann
                      pathutils.SPICE_CERT_FILE))
1481 3e40b587 Andrea Spadaccini
        tls_ciphers = hvp[constants.HV_KVM_SPICE_TLS_CIPHERS]
1482 3e40b587 Andrea Spadaccini
        if tls_ciphers:
1483 3e40b587 Andrea Spadaccini
          spice_arg = "%s,tls-ciphers=%s" % (spice_arg, tls_ciphers)
1484 bfe86c76 Andrea Spadaccini
      else:
1485 bfe86c76 Andrea Spadaccini
        spice_arg = "%s,port=%s" % (spice_arg, instance.network_port)
1486 bfe86c76 Andrea Spadaccini
1487 b451c4c7 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]:
1488 b451c4c7 Andrea Spadaccini
        spice_arg = "%s,disable-ticketing" % spice_arg
1489 b451c4c7 Andrea Spadaccini
1490 11ae7a0a Andrea Spadaccini
      if spice_ip_version:
1491 11ae7a0a Andrea Spadaccini
        spice_arg = "%s,ipv%s" % (spice_arg, spice_ip_version)
1492 b1cb62bd Andrea Spadaccini
1493 ea064d24 Andrea Spadaccini
      # Image compression options
1494 ea064d24 Andrea Spadaccini
      img_lossless = hvp[constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR]
1495 ea064d24 Andrea Spadaccini
      img_jpeg = hvp[constants.HV_KVM_SPICE_JPEG_IMG_COMPR]
1496 ea064d24 Andrea Spadaccini
      img_zlib_glz = hvp[constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR]
1497 ea064d24 Andrea Spadaccini
      if img_lossless:
1498 ea064d24 Andrea Spadaccini
        spice_arg = "%s,image-compression=%s" % (spice_arg, img_lossless)
1499 ea064d24 Andrea Spadaccini
      if img_jpeg:
1500 ea064d24 Andrea Spadaccini
        spice_arg = "%s,jpeg-wan-compression=%s" % (spice_arg, img_jpeg)
1501 ea064d24 Andrea Spadaccini
      if img_zlib_glz:
1502 ea064d24 Andrea Spadaccini
        spice_arg = "%s,zlib-glz-wan-compression=%s" % (spice_arg, img_zlib_glz)
1503 ea064d24 Andrea Spadaccini
1504 ea064d24 Andrea Spadaccini
      # Video stream detection
1505 ea064d24 Andrea Spadaccini
      video_streaming = hvp[constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION]
1506 ea064d24 Andrea Spadaccini
      if video_streaming:
1507 ea064d24 Andrea Spadaccini
        spice_arg = "%s,streaming-video=%s" % (spice_arg, video_streaming)
1508 ea064d24 Andrea Spadaccini
1509 ea064d24 Andrea Spadaccini
      # Audio compression, by default in qemu-kvm it is on
1510 ea064d24 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_AUDIO_COMPR]:
1511 ea064d24 Andrea Spadaccini
        spice_arg = "%s,playback-compression=off" % spice_arg
1512 3e40b587 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_USE_VDAGENT]:
1513 3e40b587 Andrea Spadaccini
        spice_arg = "%s,agent-mouse=off" % spice_arg
1514 447af814 Nikos Skalkotos
      else:
1515 447af814 Nikos Skalkotos
        # Enable the spice agent communication channel between the host and the
1516 447af814 Nikos Skalkotos
        # agent.
1517 447af814 Nikos Skalkotos
        kvm_cmd.extend(["-device", "virtio-serial-pci"])
1518 afa9bb2e Michael Hanselmann
        kvm_cmd.extend([
1519 afa9bb2e Michael Hanselmann
          "-device",
1520 afa9bb2e Michael Hanselmann
          "virtserialport,chardev=spicechannel0,name=com.redhat.spice.0",
1521 afa9bb2e Michael Hanselmann
          ])
1522 447af814 Nikos Skalkotos
        kvm_cmd.extend(["-chardev", "spicevmc,id=spicechannel0,name=vdagent"])
1523 ea064d24 Andrea Spadaccini
1524 b1cb62bd Andrea Spadaccini
      logging.info("KVM: SPICE will listen on port %s", instance.network_port)
1525 b1cb62bd Andrea Spadaccini
      kvm_cmd.extend(["-spice", spice_arg])
1526 b1cb62bd Andrea Spadaccini
1527 596b2459 Guido Trotter
    else:
1528 99c7cd5b Guido Trotter
      # From qemu 1.4 -nographic is incompatible with -daemonize. The new way
1529 99c7cd5b Guido Trotter
      # also works in earlier versions though (tested with 1.1 and 1.3)
1530 99c7cd5b Guido Trotter
      if self._DISPLAY_RE.search(kvmhelp):
1531 99c7cd5b Guido Trotter
        kvm_cmd.extend(["-display", "none"])
1532 99c7cd5b Guido Trotter
      else:
1533 99c7cd5b Guido Trotter
        kvm_cmd.extend(["-nographic"])
1534 596b2459 Guido Trotter
1535 6b970cef Jun Futagawa
    if hvp[constants.HV_USE_LOCALTIME]:
1536 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-localtime"])
1537 6b970cef Jun Futagawa
1538 547a63b7 Balazs Lecz
    if hvp[constants.HV_KVM_USE_CHROOT]:
1539 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-chroot", self._InstanceChrootDir(instance.name)])
1540 547a63b7 Balazs Lecz
1541 7cb42171 Nikita Staroverov
    # Add qemu-KVM -cpu param
1542 7cb42171 Nikita Staroverov
    if hvp[constants.HV_CPU_TYPE]:
1543 7cb42171 Nikita Staroverov
      kvm_cmd.extend(["-cpu", hvp[constants.HV_CPU_TYPE]])
1544 7cb42171 Nikita Staroverov
1545 2fddb144 Guido Trotter
    # As requested by music lovers
1546 2fddb144 Guido Trotter
    if hvp[constants.HV_SOUNDHW]:
1547 2fddb144 Guido Trotter
      kvm_cmd.extend(["-soundhw", hvp[constants.HV_SOUNDHW]])
1548 2fddb144 Guido Trotter
1549 7589346f Guido Trotter
    # Pass a -vga option if requested, or if spice is used, for backwards
1550 7589346f Guido Trotter
    # compatibility.
1551 7589346f Guido Trotter
    if hvp[constants.HV_VGA]:
1552 7589346f Guido Trotter
      kvm_cmd.extend(["-vga", hvp[constants.HV_VGA]])
1553 7589346f Guido Trotter
    elif spice_bind:
1554 7589346f Guido Trotter
      kvm_cmd.extend(["-vga", "qxl"])
1555 7589346f Guido Trotter
1556 156681c1 Guido Trotter
    # Various types of usb devices, comma separated
1557 156681c1 Guido Trotter
    if hvp[constants.HV_USB_DEVICES]:
1558 156681c1 Guido Trotter
      for dev in hvp[constants.HV_USB_DEVICES].split(","):
1559 156681c1 Guido Trotter
        kvm_cmd.extend(["-usbdevice", dev])
1560 156681c1 Guido Trotter
1561 e6f24d89 Guido Trotter
    if hvp[constants.HV_KVM_EXTRA]:
1562 a967416c Guido Trotter
      kvm_cmd.extend(hvp[constants.HV_KVM_EXTRA].split(" "))
1563 e6f24d89 Guido Trotter
1564 0288e7bf Dimitris Aragiorgis
    pci_reservations = bitarray(self._DEFAULT_PCI_RESERVATIONS)
1565 58502c9e Dimitris Aragiorgis
    kvm_disks = []
1566 0288e7bf Dimitris Aragiorgis
    for disk, link_name in block_devices:
1567 0288e7bf Dimitris Aragiorgis
      _UpdatePCISlots(disk, pci_reservations)
1568 0288e7bf Dimitris Aragiorgis
      kvm_disks.append((disk, link_name))
1569 58502c9e Dimitris Aragiorgis
1570 58502c9e Dimitris Aragiorgis
    kvm_nics = []
1571 58502c9e Dimitris Aragiorgis
    for nic in instance.nics:
1572 0288e7bf Dimitris Aragiorgis
      _UpdatePCISlots(nic, pci_reservations)
1573 58502c9e Dimitris Aragiorgis
      kvm_nics.append(nic)
1574 58502c9e Dimitris Aragiorgis
1575 a985b417 Iustin Pop
    hvparams = hvp
1576 ee5f20b0 Guido Trotter
1577 58502c9e Dimitris Aragiorgis
    return (kvm_cmd, kvm_nics, hvparams, kvm_disks)
1578 ee5f20b0 Guido Trotter
1579 38e250ba Guido Trotter
  def _WriteKVMRuntime(self, instance_name, data):
1580 38e250ba Guido Trotter
    """Write an instance's KVM runtime
1581 38e250ba Guido Trotter

1582 38e250ba Guido Trotter
    """
1583 38e250ba Guido Trotter
    try:
1584 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1585 38e250ba Guido Trotter
                      data=data)
1586 90c024f6 Guido Trotter
    except EnvironmentError, err:
1587 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1588 38e250ba Guido Trotter
1589 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
1590 38e250ba Guido Trotter
    """Read an instance's KVM runtime
1591 38e250ba Guido Trotter

1592 38e250ba Guido Trotter
    """
1593 38e250ba Guido Trotter
    try:
1594 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1595 90c024f6 Guido Trotter
    except EnvironmentError, err:
1596 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1597 38e250ba Guido Trotter
    return file_content
1598 38e250ba Guido Trotter
1599 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1600 38e250ba Guido Trotter
    """Save an instance's KVM runtime
1601 38e250ba Guido Trotter

1602 38e250ba Guido Trotter
    """
1603 58502c9e Dimitris Aragiorgis
    kvm_cmd, kvm_nics, hvparams, block_devices = kvm_runtime
1604 58502c9e Dimitris Aragiorgis
1605 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1606 277a9de7 Dimitris Aragiorgis
    serialized_blockdevs = [(blk.ToDict(), link)
1607 277a9de7 Dimitris Aragiorgis
                            for blk, link in block_devices]
1608 58502c9e Dimitris Aragiorgis
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams,
1609 58502c9e Dimitris Aragiorgis
                                      serialized_blockdevs))
1610 58502c9e Dimitris Aragiorgis
1611 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
1612 38e250ba Guido Trotter
1613 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1614 38e250ba Guido Trotter
    """Load an instance's KVM runtime
1615 38e250ba Guido Trotter

1616 38e250ba Guido Trotter
    """
1617 30e42c4e Guido Trotter
    if not serialized_runtime:
1618 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1619 58502c9e Dimitris Aragiorgis
1620 58502c9e Dimitris Aragiorgis
    return _AnalyzeSerializedRuntime(serialized_runtime)
1621 38e250ba Guido Trotter
1622 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1623 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
1624 76431533 Guido Trotter

1625 76431533 Guido Trotter
    @type name: string
1626 76431533 Guido Trotter
    @param name: instance name
1627 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1628 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1629 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1630 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1631 76431533 Guido Trotter

1632 76431533 Guido Trotter
    """
1633 5d9bfd87 Apollon Oikonomopoulos
    try:
1634 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1635 5d9bfd87 Apollon Oikonomopoulos
    finally:
1636 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
1637 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
1638 5d9bfd87 Apollon Oikonomopoulos
1639 76431533 Guido Trotter
    if result.failed:
1640 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1641 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
1642 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
1643 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
1644 76431533 Guido Trotter
1645 58502c9e Dimitris Aragiorgis
  # 52/50 local variables
1646 58502c9e Dimitris Aragiorgis
  # pylint: disable=R0914
1647 b73f1c59 Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1648 839642c2 Iustin Pop
    """Execute a KVM cmd, after completing it with some last minute data.
1649 ee5f20b0 Guido Trotter

1650 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1651 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1652 b73f1c59 Guido Trotter
    @type kvmhelp: string
1653 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1654 30e42c4e Guido Trotter

1655 ee5f20b0 Guido Trotter
    """
1656 297e6e53 Guido Trotter
    # Small _ExecuteKVMRuntime hv parameters programming howto:
1657 297e6e53 Guido Trotter
    #  - conf_hvp contains the parameters as configured on ganeti. they might
1658 297e6e53 Guido Trotter
    #    have changed since the instance started; only use them if the change
1659 297e6e53 Guido Trotter
    #    won't affect the inside of the instance (which hasn't been rebooted).
1660 297e6e53 Guido Trotter
    #  - up_hvp contains the parameters as they were when the instance was
1661 297e6e53 Guido Trotter
    #    started, plus any new parameter which has been added between ganeti
1662 297e6e53 Guido Trotter
    #    versions: it is paramount that those default to a value which won't
1663 297e6e53 Guido Trotter
    #    affect the inside of the instance as well.
1664 297e6e53 Guido Trotter
    conf_hvp = instance.hvparams
1665 5905901c Iustin Pop
    name = instance.name
1666 5905901c Iustin Pop
    self._CheckDown(name)
1667 ee5f20b0 Guido Trotter
1668 ee5f20b0 Guido Trotter
    temp_files = []
1669 ee5f20b0 Guido Trotter
1670 58502c9e Dimitris Aragiorgis
    kvm_cmd, kvm_nics, up_hvp, block_devices = kvm_runtime
1671 f0db563d Guido Trotter
    # the first element of kvm_cmd is always the path to the kvm binary
1672 f0db563d Guido Trotter
    kvm_path = kvm_cmd[0]
1673 297e6e53 Guido Trotter
    up_hvp = objects.FillDict(conf_hvp, up_hvp)
1674 ee5f20b0 Guido Trotter
1675 297e6e53 Guido Trotter
    # We know it's safe to run as a different user upon migration, so we'll use
1676 297e6e53 Guido Trotter
    # the latest conf, from conf_hvp.
1677 297e6e53 Guido Trotter
    security_model = conf_hvp[constants.HV_SECURITY_MODEL]
1678 cef34868 Guido Trotter
    if security_model == constants.HT_SM_USER:
1679 297e6e53 Guido Trotter
      kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
1680 cef34868 Guido Trotter
1681 839642c2 Iustin Pop
    keymap = conf_hvp[constants.HV_KEYMAP]
1682 839642c2 Iustin Pop
    if keymap:
1683 839642c2 Iustin Pop
      keymap_path = self._InstanceKeymapFile(name)
1684 839642c2 Iustin Pop
      # If a keymap file is specified, KVM won't use its internal defaults. By
1685 839642c2 Iustin Pop
      # first including the "en-us" layout, an error on loading the actual
1686 839642c2 Iustin Pop
      # layout (e.g. because it can't be found) won't lead to a non-functional
1687 839642c2 Iustin Pop
      # keyboard. A keyboard with incorrect keys is still better than none.
1688 839642c2 Iustin Pop
      utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
1689 839642c2 Iustin Pop
      kvm_cmd.extend(["-k", keymap_path])
1690 839642c2 Iustin Pop
1691 297e6e53 Guido Trotter
    # We have reasons to believe changing something like the nic driver/type
1692 297e6e53 Guido Trotter
    # upon migration won't exactly fly with the instance kernel, so for nic
1693 297e6e53 Guido Trotter
    # related parameters we'll use up_hvp
1694 5d9bfd87 Apollon Oikonomopoulos
    tapfds = []
1695 5d9bfd87 Apollon Oikonomopoulos
    taps = []
1696 ee5f20b0 Guido Trotter
    if not kvm_nics:
1697 fbe27e2b Guido Trotter
      kvm_cmd.extend(["-net", "none"])
1698 ee5f20b0 Guido Trotter
    else:
1699 5d9bfd87 Apollon Oikonomopoulos
      vnet_hdr = False
1700 fbe27e2b Guido Trotter
      tap_extra = ""
1701 297e6e53 Guido Trotter
      nic_type = up_hvp[constants.HV_NIC_TYPE]
1702 37f88dc6 Guido Trotter
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
1703 f0db563d Guido Trotter
        nic_model = self._VIRTIO
1704 f0db563d Guido Trotter
        try:
1705 f0db563d Guido Trotter
          devlist = self._GetKVMOutput(kvm_path, self._KVMOPT_DEVICELIST)
1706 994ccaf2 Dimitris Aragiorgis
          if self._VIRTIO_NET_RE.search(devlist):
1707 f0db563d Guido Trotter
            nic_model = self._VIRTIO_NET_PCI
1708 8a534fbe Stratos Psomdakis
            vnet_hdr = up_hvp[constants.HV_VNET_HDR]
1709 f0db563d Guido Trotter
        except errors.HypervisorError, _:
1710 f0db563d Guido Trotter
          # Older versions of kvm don't support DEVICE_LIST, but they don't
1711 f0db563d Guido Trotter
          # have new virtio syntax either.
1712 f0db563d Guido Trotter
          pass
1713 4b784cf8 Miguel Di Ciurcio Filho
1714 297e6e53 Guido Trotter
        if up_hvp[constants.HV_VHOST_NET]:
1715 3b59ec02 Guido Trotter
          # check for vhost_net support
1716 0ad7f5d8 Guido Trotter
          if self._VHOST_RE.search(kvmhelp):
1717 4b784cf8 Miguel Di Ciurcio Filho
            tap_extra = ",vhost=on"
1718 4b784cf8 Miguel Di Ciurcio Filho
          else:
1719 4b784cf8 Miguel Di Ciurcio Filho
            raise errors.HypervisorError("vhost_net is configured"
1720 5ae4945a Iustin Pop
                                         " but it is not available")
1721 37f88dc6 Guido Trotter
      else:
1722 4b784cf8 Miguel Di Ciurcio Filho
        nic_model = nic_type
1723 37f88dc6 Guido Trotter
1724 6f4070cd Guido Trotter
      kvm_supports_netdev = self._NETDEV_RE.search(kvmhelp)
1725 6f4070cd Guido Trotter
1726 ee5f20b0 Guido Trotter
      for nic_seq, nic in enumerate(kvm_nics):
1727 6f1e1921 Michael Hanselmann
        tapname, tapfd = _OpenTap(vnet_hdr=vnet_hdr)
1728 5d9bfd87 Apollon Oikonomopoulos
        tapfds.append(tapfd)
1729 5d9bfd87 Apollon Oikonomopoulos
        taps.append(tapname)
1730 6f4070cd Guido Trotter
        if kvm_supports_netdev:
1731 0288e7bf Dimitris Aragiorgis
          nic_val = "%s,mac=%s" % (nic_model, nic.mac)
1732 0288e7bf Dimitris Aragiorgis
          try:
1733 0288e7bf Dimitris Aragiorgis
            # kvm_nics already exist in old runtime files and thus there might
1734 0288e7bf Dimitris Aragiorgis
            # be some entries without pci slot (therefore try: except:)
1735 0288e7bf Dimitris Aragiorgis
            kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_NIC, nic)
1736 0288e7bf Dimitris Aragiorgis
            netdev = kvm_devid
1737 0288e7bf Dimitris Aragiorgis
            nic_val += (",id=%s,bus=pci.0,addr=%s" % (kvm_devid, hex(nic.pci)))
1738 0288e7bf Dimitris Aragiorgis
          except errors.HotplugError:
1739 0288e7bf Dimitris Aragiorgis
            netdev = "netdev%d" % nic_seq
1740 0288e7bf Dimitris Aragiorgis
          nic_val += (",netdev=%s" % netdev)
1741 0288e7bf Dimitris Aragiorgis
          tap_val = ("type=tap,id=%s,fd=%d%s" %
1742 0288e7bf Dimitris Aragiorgis
                     (netdev, tapfd, tap_extra))
1743 4b784cf8 Miguel Di Ciurcio Filho
          kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
1744 4b784cf8 Miguel Di Ciurcio Filho
        else:
1745 049383d9 Adeodato Simo
          nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq,
1746 049383d9 Adeodato Simo
                                                         nic.mac, nic_model)
1747 5d9bfd87 Apollon Oikonomopoulos
          tap_val = "tap,vlan=%s,fd=%d" % (nic_seq, tapfd)
1748 4b784cf8 Miguel Di Ciurcio Filho
          kvm_cmd.extend(["-net", tap_val, "-net", nic_val])
1749 ee5f20b0 Guido Trotter
1750 30e42c4e Guido Trotter
    if incoming:
1751 30e42c4e Guido Trotter
      target, port = incoming
1752 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])
1753 30e42c4e Guido Trotter
1754 297e6e53 Guido Trotter
    # Changing the vnc password doesn't bother the guest that much. At most it
1755 297e6e53 Guido Trotter
    # will surprise people who connect to it. Whether positively or negatively
1756 297e6e53 Guido Trotter
    # it's debatable.
1757 297e6e53 Guido Trotter
    vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
1758 6e6bb8d5 Guido Trotter
    vnc_pwd = None
1759 6e6bb8d5 Guido Trotter
    if vnc_pwd_file:
1760 6e6bb8d5 Guido Trotter
      try:
1761 682f7601 Guido Trotter
        vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
1762 6e6bb8d5 Guido Trotter
      except EnvironmentError, err:
1763 6e6bb8d5 Guido Trotter
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
1764 6e6bb8d5 Guido Trotter
                                     % (vnc_pwd_file, err))
1765 6e6bb8d5 Guido Trotter
1766 297e6e53 Guido Trotter
    if conf_hvp[constants.HV_KVM_USE_CHROOT]:
1767 547a63b7 Balazs Lecz
      utils.EnsureDirs([(self._InstanceChrootDir(name),
1768 547a63b7 Balazs Lecz
                         constants.SECURE_DIR_MODE)])
1769 547a63b7 Balazs Lecz
1770 91c10532 Andrea Spadaccini
    # Automatically enable QMP if version is >= 0.14
1771 0ad7f5d8 Guido Trotter
    if self._QMP_RE.search(kvmhelp):
1772 91c10532 Andrea Spadaccini
      logging.debug("Enabling QMP")
1773 91c10532 Andrea Spadaccini
      kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
1774 5ae4945a Iustin Pop
                      self._InstanceQmpMonitor(instance.name)])
1775 91c10532 Andrea Spadaccini
1776 cc8a8ed7 Apollon Oikonomopoulos
    # Configure the network now for starting instances and bridged interfaces,
1777 cc8a8ed7 Apollon Oikonomopoulos
    # during FinalizeMigration for incoming instances' routed interfaces
1778 cc8a8ed7 Apollon Oikonomopoulos
    for nic_seq, nic in enumerate(kvm_nics):
1779 cc8a8ed7 Apollon Oikonomopoulos
      if (incoming and
1780 cc8a8ed7 Apollon Oikonomopoulos
          nic.nicparams[constants.NIC_MODE] != constants.NIC_MODE_BRIDGED):
1781 cc8a8ed7 Apollon Oikonomopoulos
        continue
1782 cc8a8ed7 Apollon Oikonomopoulos
      self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
1783 5d9bfd87 Apollon Oikonomopoulos
1784 58502c9e Dimitris Aragiorgis
    bdev_opts = self._GenerateKVMBlockDevicesOptions(instance,
1785 58502c9e Dimitris Aragiorgis
                                                     block_devices,
1786 58502c9e Dimitris Aragiorgis
                                                     kvmhelp)
1787 58502c9e Dimitris Aragiorgis
    kvm_cmd.extend(bdev_opts)
1788 1d8a7812 Andrea Spadaccini
    # CPU affinity requires kvm to start paused, so we set this flag if the
1789 1d8a7812 Andrea Spadaccini
    # instance is not already paused and if we are not going to accept a
1790 1d8a7812 Andrea Spadaccini
    # migrating instance. In the latter case, pausing is not needed.
1791 1d8a7812 Andrea Spadaccini
    start_kvm_paused = not (_KVM_START_PAUSED_FLAG in kvm_cmd) and not incoming
1792 945a7e67 Guido Trotter
    if start_kvm_paused:
1793 945a7e67 Guido Trotter
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1794 b693125f Tsachy Shacham
1795 b693125f Tsachy Shacham
    # Note: CPU pinning is using up_hvp since changes take effect
1796 b693125f Tsachy Shacham
    # during instance startup anyway, and to avoid problems when soft
1797 b693125f Tsachy Shacham
    # rebooting the instance.
1798 c607b1f7 Tsachy Shacham
    cpu_pinning = False
1799 b693125f Tsachy Shacham
    if up_hvp.get(constants.HV_CPU_MASK, None):
1800 b693125f Tsachy Shacham
      cpu_pinning = True
1801 b693125f Tsachy Shacham
1802 76431533 Guido Trotter
    if security_model == constants.HT_SM_POOL:
1803 76431533 Guido Trotter
      ss = ssconf.SimpleStore()
1804 76431533 Guido Trotter
      uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
1805 76431533 Guido Trotter
      all_uids = set(uidpool.ExpandUidPool(uid_pool))
1806 76431533 Guido Trotter
      uid = uidpool.RequestUnusedUid(all_uids)
1807 76431533 Guido Trotter
      try:
1808 76431533 Guido Trotter
        username = pwd.getpwuid(uid.GetUid()).pw_name
1809 76431533 Guido Trotter
        kvm_cmd.extend(["-runas", username])
1810 5d9bfd87 Apollon Oikonomopoulos
        self._RunKVMCmd(name, kvm_cmd, tapfds)
1811 76431533 Guido Trotter
      except:
1812 76431533 Guido Trotter
        uidpool.ReleaseUid(uid)
1813 76431533 Guido Trotter
        raise
1814 76431533 Guido Trotter
      else:
1815 76431533 Guido Trotter
        uid.Unlock()
1816 3af16328 Apollon Oikonomopoulos
        utils.WriteFile(self._InstanceUidFile(name), data=uid.AsStr())
1817 76431533 Guido Trotter
    else:
1818 5d9bfd87 Apollon Oikonomopoulos
      self._RunKVMCmd(name, kvm_cmd, tapfds)
1819 5d9bfd87 Apollon Oikonomopoulos
1820 5d9bfd87 Apollon Oikonomopoulos
    utils.EnsureDirs([(self._InstanceNICDir(instance.name),
1821 5d9bfd87 Apollon Oikonomopoulos
                     constants.RUN_DIRS_MODE)])
1822 5d9bfd87 Apollon Oikonomopoulos
    for nic_seq, tap in enumerate(taps):
1823 5d9bfd87 Apollon Oikonomopoulos
      utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
1824 5d9bfd87 Apollon Oikonomopoulos
                      data=tap)
1825 eb58f9b1 Guido Trotter
1826 6e6bb8d5 Guido Trotter
    if vnc_pwd:
1827 d0c8c01d Iustin Pop
      change_cmd = "change vnc password %s" % vnc_pwd
1828 6e6bb8d5 Guido Trotter
      self._CallMonitorCommand(instance.name, change_cmd)
1829 6e6bb8d5 Guido Trotter
1830 b451c4c7 Andrea Spadaccini
    # Setting SPICE password. We are not vulnerable to malicious passwordless
1831 b451c4c7 Andrea Spadaccini
    # connection attempts because SPICE by default does not allow connections
1832 b451c4c7 Andrea Spadaccini
    # if neither a password nor the "disable_ticketing" options are specified.
1833 b451c4c7 Andrea Spadaccini
    # As soon as we send the password via QMP, that password is a valid ticket
1834 b451c4c7 Andrea Spadaccini
    # for connection.
1835 b451c4c7 Andrea Spadaccini
    spice_password_file = conf_hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]
1836 b451c4c7 Andrea Spadaccini
    if spice_password_file:
1837 fc84cd5d Guido Trotter
      spice_pwd = ""
1838 b451c4c7 Andrea Spadaccini
      try:
1839 b451c4c7 Andrea Spadaccini
        spice_pwd = utils.ReadOneLineFile(spice_password_file, strict=True)
1840 b451c4c7 Andrea Spadaccini
      except EnvironmentError, err:
1841 b451c4c7 Andrea Spadaccini
        raise errors.HypervisorError("Failed to open SPICE password file %s: %s"
1842 b451c4c7 Andrea Spadaccini
                                     % (spice_password_file, err))
1843 b451c4c7 Andrea Spadaccini
1844 fc84cd5d Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
1845 fc84cd5d Guido Trotter
      qmp.connect()
1846 fc84cd5d Guido Trotter
      arguments = {
1847 fc84cd5d Guido Trotter
          "protocol": "spice",
1848 fc84cd5d Guido Trotter
          "password": spice_pwd,
1849 fc84cd5d Guido Trotter
      }
1850 fc84cd5d Guido Trotter
      qmp.Execute("set_password", arguments)
1851 fc84cd5d Guido Trotter
1852 08137f9e Iustin Pop
    for filename in temp_files:
1853 08137f9e Iustin Pop
      utils.RemoveFile(filename)
1854 eb58f9b1 Guido Trotter
1855 b693125f Tsachy Shacham
    # If requested, set CPU affinity and resume instance execution
1856 b693125f Tsachy Shacham
    if cpu_pinning:
1857 945a7e67 Guido Trotter
      self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK])
1858 945a7e67 Guido Trotter
1859 61eb1a46 Guido Trotter
    start_memory = self._InstanceStartupMemory(instance)
1860 61eb1a46 Guido Trotter
    if start_memory < instance.beparams[constants.BE_MAXMEM]:
1861 61eb1a46 Guido Trotter
      self.BalloonInstanceMemory(instance, start_memory)
1862 61eb1a46 Guido Trotter
1863 945a7e67 Guido Trotter
    if start_kvm_paused:
1864 2ed0e208 Iustin Pop
      # To control CPU pinning, ballooning, and vnc/spice passwords
1865 2ed0e208 Iustin Pop
      # the VM was started in a frozen state. If freezing was not
1866 2ed0e208 Iustin Pop
      # explicitly requested resume the vm status.
1867 945a7e67 Guido Trotter
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1868 b693125f Tsachy Shacham
1869 323f9095 Stephen Shirley
  def StartInstance(self, instance, block_devices, startup_paused):
1870 ee5f20b0 Guido Trotter
    """Start an instance.
1871 ee5f20b0 Guido Trotter

1872 ee5f20b0 Guido Trotter
    """
1873 5905901c Iustin Pop
    self._CheckDown(instance.name)
1874 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1875 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1876 7238edb5 Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1877 b73f1c59 Guido Trotter
                                           startup_paused, kvmhelp)
1878 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1879 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1880 ee5f20b0 Guido Trotter
1881 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
1882 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
1883 6567aff3 Guido Trotter

1884 6567aff3 Guido Trotter
    """
1885 eace6157 Michael Hanselmann
    # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
1886 eace6157 Michael Hanselmann
    # version. The monitor protocol is designed for human consumption, whereas
1887 eace6157 Michael Hanselmann
    # QMP is made for programmatic usage. In the worst case QMP can also
1888 eace6157 Michael Hanselmann
    # execute monitor commands. As it is, all calls to socat take at least
1889 eace6157 Michael Hanselmann
    # 500ms and likely more: socat can't detect the end of the reply and waits
1890 eace6157 Michael Hanselmann
    # for 500ms of no data received before exiting (500 ms is the default for
1891 eace6157 Michael Hanselmann
    # the "-t" parameter).
1892 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1893 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
1894 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
1895 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1896 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
1897 6567aff3 Guido Trotter
    if result.failed:
1898 afa9bb2e Michael Hanselmann
      msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
1899 afa9bb2e Michael Hanselmann
             " output: %s" %
1900 afa9bb2e Michael Hanselmann
             (command, instance_name, result.fail_reason, result.output))
1901 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
1902 6567aff3 Guido Trotter
1903 6567aff3 Guido Trotter
    return result
1904 6567aff3 Guido Trotter
1905 8b7be6f2 Dimitris Aragiorgis
  def _GetFreePCISlot(self, instance, dev):
1906 8b7be6f2 Dimitris Aragiorgis
    """Get the first available pci slot of a runnung instance.
1907 8b7be6f2 Dimitris Aragiorgis

1908 8b7be6f2 Dimitris Aragiorgis
    """
1909 8b7be6f2 Dimitris Aragiorgis
    slots = bitarray(32)
1910 8b7be6f2 Dimitris Aragiorgis
    slots.setall(False) # pylint: disable=E1101
1911 8b7be6f2 Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance.name, self._INFO_PCI_CMD)
1912 8b7be6f2 Dimitris Aragiorgis
    for line in output.stdout.splitlines():
1913 8b7be6f2 Dimitris Aragiorgis
      match = self._INFO_PCI_RE.search(line)
1914 8b7be6f2 Dimitris Aragiorgis
      if match:
1915 8b7be6f2 Dimitris Aragiorgis
        slot = int(match.group(1))
1916 8b7be6f2 Dimitris Aragiorgis
        slots[slot] = True
1917 8b7be6f2 Dimitris Aragiorgis
1918 8b7be6f2 Dimitris Aragiorgis
    [free] = slots.search(_AVAILABLE_PCI_SLOT, 1) # pylint: disable=E1101
1919 8b7be6f2 Dimitris Aragiorgis
    if not free:
1920 8b7be6f2 Dimitris Aragiorgis
      raise errors.HypervisorError("All PCI slots occupied")
1921 8b7be6f2 Dimitris Aragiorgis
1922 8b7be6f2 Dimitris Aragiorgis
    dev.pci = int(free)
1923 8b7be6f2 Dimitris Aragiorgis
1924 b52d85c1 Guido Trotter
  @classmethod
1925 585c8187 Guido Trotter
  def _ParseKVMVersion(cls, text):
1926 585c8187 Guido Trotter
    """Parse the KVM version from the --help output.
1927 585c8187 Guido Trotter

1928 585c8187 Guido Trotter
    @type text: string
1929 585c8187 Guido Trotter
    @param text: output of kvm --help
1930 585c8187 Guido Trotter
    @return: (version, v_maj, v_min, v_rev)
1931 5c3d5dfd Iustin Pop
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1932 585c8187 Guido Trotter

1933 585c8187 Guido Trotter
    """
1934 585c8187 Guido Trotter
    match = cls._VERSION_RE.search(text.splitlines()[0])
1935 585c8187 Guido Trotter
    if not match:
1936 585c8187 Guido Trotter
      raise errors.HypervisorError("Unable to get KVM version")
1937 585c8187 Guido Trotter
1938 585c8187 Guido Trotter
    v_all = match.group(0)
1939 585c8187 Guido Trotter
    v_maj = int(match.group(1))
1940 585c8187 Guido Trotter
    v_min = int(match.group(2))
1941 585c8187 Guido Trotter
    if match.group(4):
1942 585c8187 Guido Trotter
      v_rev = int(match.group(4))
1943 585c8187 Guido Trotter
    else:
1944 585c8187 Guido Trotter
      v_rev = 0
1945 585c8187 Guido Trotter
    return (v_all, v_maj, v_min, v_rev)
1946 585c8187 Guido Trotter
1947 585c8187 Guido Trotter
  @classmethod
1948 6e043e60 Guido Trotter
  def _GetKVMOutput(cls, kvm_path, option):
1949 6e043e60 Guido Trotter
    """Return the output of a kvm invocation
1950 e3b89628 Guido Trotter

1951 bc0fed4b Guido Trotter
    @type kvm_path: string
1952 bc0fed4b Guido Trotter
    @param kvm_path: path to the kvm executable
1953 bc0fed4b Guido Trotter
    @type option: a key of _KVMOPTS_CMDS
1954 bc0fed4b Guido Trotter
    @param option: kvm option to fetch the output from
1955 6e043e60 Guido Trotter
    @return: output a supported kvm invocation
1956 e3b89628 Guido Trotter
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
1957 e3b89628 Guido Trotter

1958 e3b89628 Guido Trotter
    """
1959 6e043e60 Guido Trotter
    assert option in cls._KVMOPTS_CMDS, "Invalid output option"
1960 6e043e60 Guido Trotter
1961 bc0fed4b Guido Trotter
    optlist, can_fail = cls._KVMOPTS_CMDS[option]
1962 bc0fed4b Guido Trotter
1963 bc0fed4b Guido Trotter
    result = utils.RunCmd([kvm_path] + optlist)
1964 bc0fed4b Guido Trotter
    if result.failed and not can_fail:
1965 af89fa76 Helga Velroyen
      raise errors.HypervisorError("Unable to get KVM %s output" %
1966 3ddc7650 Jose A. Lopes
                                    " ".join(optlist))
1967 e3b89628 Guido Trotter
    return result.output
1968 e3b89628 Guido Trotter
1969 e3b89628 Guido Trotter
  @classmethod
1970 3b59ec02 Guido Trotter
  def _GetKVMVersion(cls, kvm_path):
1971 d7e4a2b1 Andrea Spadaccini
    """Return the installed KVM version.
1972 b52d85c1 Guido Trotter

1973 440351f8 Andrea Spadaccini
    @return: (version, v_maj, v_min, v_rev)
1974 5c3d5dfd Iustin Pop
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1975 b52d85c1 Guido Trotter

1976 b52d85c1 Guido Trotter
    """
1977 6e043e60 Guido Trotter
    return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
1978 82e3bf85 Dimitris Aragiorgis
1979 82e3bf85 Dimitris Aragiorgis
  @classmethod
1980 82e3bf85 Dimitris Aragiorgis
  def _GetDefaultMachineVersion(cls, kvm_path):
1981 82e3bf85 Dimitris Aragiorgis
    """Return the default hardware revision (e.g. pc-1.1)
1982 82e3bf85 Dimitris Aragiorgis

1983 82e3bf85 Dimitris Aragiorgis
    """
1984 6e043e60 Guido Trotter
    output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
1985 82e3bf85 Dimitris Aragiorgis
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
1986 82e3bf85 Dimitris Aragiorgis
    if match:
1987 82e3bf85 Dimitris Aragiorgis
      return match.group(1)
1988 82e3bf85 Dimitris Aragiorgis
    else:
1989 82e3bf85 Dimitris Aragiorgis
      return "pc"
1990 82e3bf85 Dimitris Aragiorgis
1991 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
1992 eb58f9b1 Guido Trotter
    """Stop an instance.
1993 eb58f9b1 Guido Trotter

1994 eb58f9b1 Guido Trotter
    """
1995 bbcf7ad0 Iustin Pop
    if name is not None and not force:
1996 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
1997 bbcf7ad0 Iustin Pop
    if name is None:
1998 bbcf7ad0 Iustin Pop
      name = instance.name
1999 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
2000 bbcf7ad0 Iustin Pop
    else:
2001 bbcf7ad0 Iustin Pop
      acpi = False
2002 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
2003 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
2004 bbcf7ad0 Iustin Pop
      if force or not acpi:
2005 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
2006 eb58f9b1 Guido Trotter
      else:
2007 d0c8c01d Iustin Pop
        self._CallMonitorCommand(name, "system_powerdown")
2008 eb58f9b1 Guido Trotter
2009 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
2010 8904b35c Guido Trotter
    """Cleanup after a stopped instance
2011 8904b35c Guido Trotter

2012 8904b35c Guido Trotter
    """
2013 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
2014 8904b35c Guido Trotter
    if pid > 0 and alive:
2015 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
2016 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
2017 eb58f9b1 Guido Trotter
2018 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
2019 eb58f9b1 Guido Trotter
    """Reboot an instance.
2020 eb58f9b1 Guido Trotter

2021 eb58f9b1 Guido Trotter
    """
2022 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
2023 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
2024 eb58f9b1 Guido Trotter
    # to shutdown and restart.
2025 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
2026 1f8b3a27 Guido Trotter
    if not alive:
2027 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
2028 78411c60 Iustin Pop
                                   " not running" % instance.name)
2029 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
2030 f02881e0 Guido Trotter
    # ...first load it...
2031 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
2032 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
2033 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
2034 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
2035 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
2036 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
2037 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2038 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2039 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
2040 eb58f9b1 Guido Trotter
2041 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
2042 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
2043 30e42c4e Guido Trotter

2044 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2045 30e42c4e Guido Trotter
    @param instance: instance to be migrated
2046 30e42c4e Guido Trotter
    @rtype: string
2047 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
2048 30e42c4e Guido Trotter

2049 30e42c4e Guido Trotter
    """
2050 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
2051 30e42c4e Guido Trotter
2052 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
2053 30e42c4e Guido Trotter
    """Prepare to accept an instance.
2054 30e42c4e Guido Trotter

2055 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2056 30e42c4e Guido Trotter
    @param instance: instance to be accepted
2057 30e42c4e Guido Trotter
    @type info: string
2058 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
2059 30e42c4e Guido Trotter
    @type target: string
2060 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
2061 30e42c4e Guido Trotter

2062 30e42c4e Guido Trotter
    """
2063 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2064 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
2065 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2066 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2067 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
2068 b73f1c59 Guido Trotter
                            incoming=incoming_address)
2069 30e42c4e Guido Trotter
2070 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
2071 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
2072 30e42c4e Guido Trotter

2073 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
2074 30e42c4e Guido Trotter

2075 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2076 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
2077 30e42c4e Guido Trotter

2078 30e42c4e Guido Trotter
    """
2079 30e42c4e Guido Trotter
    if success:
2080 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2081 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
2082 5d9bfd87 Apollon Oikonomopoulos
2083 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
2084 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
2085 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
2086 cc8a8ed7 Apollon Oikonomopoulos
          continue
2087 5d9bfd87 Apollon Oikonomopoulos
        try:
2088 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
2089 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
2090 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
2091 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
2092 5d9bfd87 Apollon Oikonomopoulos
          continue
2093 5d9bfd87 Apollon Oikonomopoulos
        try:
2094 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
2095 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
2096 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
2097 5d9bfd87 Apollon Oikonomopoulos
2098 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
2099 30e42c4e Guido Trotter
    else:
2100 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
2101 30e42c4e Guido Trotter
2102 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
2103 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
2104 30e42c4e Guido Trotter

2105 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
2106 30e42c4e Guido Trotter
    currently running.
2107 30e42c4e Guido Trotter

2108 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
2109 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
2110 30e42c4e Guido Trotter
    @type target: string
2111 30e42c4e Guido Trotter
    @param target: ip address of the target node
2112 30e42c4e Guido Trotter
    @type live: boolean
2113 30e42c4e Guido Trotter
    @param live: perform a live migration
2114 30e42c4e Guido Trotter

2115 30e42c4e Guido Trotter
    """
2116 58d38b02 Iustin Pop
    instance_name = instance.name
2117 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
2118 6a1434d7 Andrea Spadaccini
    _, _, alive = self._InstancePidAlive(instance_name)
2119 30e42c4e Guido Trotter
    if not alive:
2120 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
2121 30e42c4e Guido Trotter
2122 30e42c4e Guido Trotter
    if not live:
2123 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
2124 30e42c4e Guido Trotter
2125 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
2126 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
2127 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2128 e43d4f9f Apollon Oikonomopoulos
2129 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
2130 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
2131 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2132 e43d4f9f Apollon Oikonomopoulos
2133 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
2134 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
2135 30e42c4e Guido Trotter
2136 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
2137 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
2138 6a1434d7 Andrea Spadaccini

2139 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2140 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
2141 6a1434d7 Andrea Spadaccini
    @type success: bool
2142 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
2143 6a1434d7 Andrea Spadaccini
    @type live: bool
2144 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
2145 6a1434d7 Andrea Spadaccini

2146 6a1434d7 Andrea Spadaccini
    """
2147 6a1434d7 Andrea Spadaccini
    if success:
2148 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
2149 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
2150 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
2151 6a1434d7 Andrea Spadaccini
    elif live:
2152 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
2153 6a1434d7 Andrea Spadaccini
2154 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
2155 6a1434d7 Andrea Spadaccini
    """Get the migration status
2156 6a1434d7 Andrea Spadaccini

2157 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2158 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
2159 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
2160 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
2161 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
2162 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
2163 6a1434d7 Andrea Spadaccini

2164 6a1434d7 Andrea Spadaccini
    """
2165 d0c8c01d Iustin Pop
    info_command = "info migrate"
2166 6a1434d7 Andrea Spadaccini
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
2167 6a1434d7 Andrea Spadaccini
      result = self._CallMonitorCommand(instance.name, info_command)
2168 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
2169 30e42c4e Guido Trotter
      if not match:
2170 c4e388a5 Guido Trotter
        if not result.stdout:
2171 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
2172 c4e388a5 Guido Trotter
        else:
2173 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
2174 c4e388a5 Guido Trotter
                          result.stdout)
2175 30e42c4e Guido Trotter
      else:
2176 30e42c4e Guido Trotter
        status = match.group(1)
2177 6a1434d7 Andrea Spadaccini
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
2178 6a1434d7 Andrea Spadaccini
          migration_status = objects.MigrationStatus(status=status)
2179 61643226 Andrea Spadaccini
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
2180 61643226 Andrea Spadaccini
          if match:
2181 61643226 Andrea Spadaccini
            migration_status.transferred_ram = match.group("transferred")
2182 61643226 Andrea Spadaccini
            migration_status.total_ram = match.group("total")
2183 61643226 Andrea Spadaccini
2184 6a1434d7 Andrea Spadaccini
          return migration_status
2185 30e42c4e Guido Trotter
2186 6a1434d7 Andrea Spadaccini
        logging.warning("KVM: unknown migration status '%s'", status)
2187 6a1434d7 Andrea Spadaccini
2188 6a1434d7 Andrea Spadaccini
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
2189 6a1434d7 Andrea Spadaccini
2190 62457f51 Iustin Pop
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
2191 30e42c4e Guido Trotter
2192 3d836750 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
2193 3d836750 Guido Trotter
    """Balloon an instance memory to a certain value.
2194 3d836750 Guido Trotter

2195 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
2196 3d836750 Guido Trotter
    @param instance: instance to be accepted
2197 3d836750 Guido Trotter
    @type mem: int
2198 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
2199 3d836750 Guido Trotter

2200 3d836750 Guido Trotter
    """
2201 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2202 3d836750 Guido Trotter
2203 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
2204 eb58f9b1 Guido Trotter
    """Return information about the node.
2205 eb58f9b1 Guido Trotter

2206 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
2207 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
2208 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
2209 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
2210 34fbc862 Andrea Spadaccini
          - hv_version: the hypervisor version in the form (major, minor,
2211 34fbc862 Andrea Spadaccini
                        revision)
2212 eb58f9b1 Guido Trotter

2213 eb58f9b1 Guido Trotter
    """
2214 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
2215 4b9638dc Guido Trotter
    # FIXME: this is the global kvm version, but the actual version can be
2216 4b9638dc Guido Trotter
    # customized as an hv parameter. we should use the nodegroup's default kvm
2217 4b9638dc Guido Trotter
    # path parameter here.
2218 3b59ec02 Guido Trotter
    _, v_major, v_min, v_rev = self._GetKVMVersion(constants.KVM_PATH)
2219 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2220 34fbc862 Andrea Spadaccini
    return result
2221 eb58f9b1 Guido Trotter
2222 637ce7f9 Guido Trotter
  @classmethod
2223 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
2224 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
2225 eb58f9b1 Guido Trotter

2226 eb58f9b1 Guido Trotter
    """
2227 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2228 9d9bded1 Michael Hanselmann
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2229 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2230 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2231 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
2232 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2233 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2234 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
2235 55cc0a44 Michael Hanselmann
                                     host=instance.primary_node,
2236 052783ff Michael Hanselmann
                                     user=constants.SSH_CONSOLE_USER,
2237 55cc0a44 Michael Hanselmann
                                     command=cmd)
2238 3be34f57 Guido Trotter
2239 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2240 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2241 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
2242 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2243 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
2244 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
2245 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
2246 55cc0a44 Michael Hanselmann
                                     display=display)
2247 55cc0a44 Michael Hanselmann
2248 4d2cdb5a Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2249 4d2cdb5a Andrea Spadaccini
    if spice_bind:
2250 4d2cdb5a Andrea Spadaccini
      return objects.InstanceConsole(instance=instance.name,
2251 4d2cdb5a Andrea Spadaccini
                                     kind=constants.CONS_SPICE,
2252 4d2cdb5a Andrea Spadaccini
                                     host=spice_bind,
2253 4d2cdb5a Andrea Spadaccini
                                     port=instance.network_port)
2254 4d2cdb5a Andrea Spadaccini
2255 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
2256 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
2257 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
2258 55cc0a44 Michael Hanselmann
                                            instance.name))
2259 eb58f9b1 Guido Trotter
2260 eb58f9b1 Guido Trotter
  def Verify(self):
2261 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
2262 eb58f9b1 Guido Trotter

2263 cd04dfd2 Michael Hanselmann
    Check that the required binaries exist.
2264 cd04dfd2 Michael Hanselmann

2265 cd04dfd2 Michael Hanselmann
    @return: Problem description if something is wrong, C{None} otherwise
2266 eb58f9b1 Guido Trotter

2267 eb58f9b1 Guido Trotter
    """
2268 1f4b9d39 Iustin Pop
    msgs = []
2269 1f4b9d39 Iustin Pop
    # FIXME: this is the global kvm binary, but the actual path can be
2270 1f4b9d39 Iustin Pop
    # customized as an hv parameter; we should use the nodegroup's
2271 1f4b9d39 Iustin Pop
    # default kvm path parameter here.
2272 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
2273 1f4b9d39 Iustin Pop
      msgs.append("The KVM binary ('%s') does not exist" % constants.KVM_PATH)
2274 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2275 1f4b9d39 Iustin Pop
      msgs.append("The socat binary ('%s') does not exist" %
2276 1f4b9d39 Iustin Pop
                  constants.SOCAT_PATH)
2277 1f4b9d39 Iustin Pop
2278 1f4b9d39 Iustin Pop
    return self._FormatVerifyResults(msgs)
2279 14aa53cb Guido Trotter
2280 6b5605e8 Iustin Pop
  @classmethod
2281 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2282 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2283 6b5605e8 Iustin Pop

2284 6b5605e8 Iustin Pop
    @type hvparams:  dict
2285 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2286 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2287 6b5605e8 Iustin Pop

2288 6b5605e8 Iustin Pop
    """
2289 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2290 6b5605e8 Iustin Pop
2291 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
2292 df5ab9f0 Guido Trotter
    if kernel_path:
2293 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
2294 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
2295 205ab586 Iustin Pop
                                     " if a kernel is defined")
2296 6b5605e8 Iustin Pop
2297 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
2298 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
2299 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
2300 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
2301 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
2302 66d5dbef Guido Trotter
2303 14fd6c81 Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2304 14fd6c81 Guido Trotter
      serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2305 14fd6c81 Guido Trotter
      valid_speeds = constants.VALID_SERIAL_SPEEDS
2306 14fd6c81 Guido Trotter
      if not serial_speed or serial_speed not in valid_speeds:
2307 14fd6c81 Guido Trotter
        raise errors.HypervisorError("Invalid serial console speed, must be"
2308 14fd6c81 Guido Trotter
                                     " one of: %s" %
2309 14fd6c81 Guido Trotter
                                     utils.CommaJoin(valid_speeds))
2310 14fd6c81 Guido Trotter
2311 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2312 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
2313 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2314 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2315 835528af Iustin Pop
                                   " ISO path")
2316 f5118ade Iustin Pop
2317 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2318 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2319 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
2320 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
2321 d19d94db Guido Trotter
                                     " must be specified")
2322 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
2323 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
2324 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
2325 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
2326 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
2327 d19d94db Guido Trotter
2328 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2329 b451c4c7 Andrea Spadaccini
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2330 b1cb62bd Andrea Spadaccini
    if spice_bind:
2331 b1cb62bd Andrea Spadaccini
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2332 b1cb62bd Andrea Spadaccini
        # if an IP version is specified, the spice_bind parameter must be an
2333 b1cb62bd Andrea Spadaccini
        # IP of that family
2334 b1cb62bd Andrea Spadaccini
        if (netutils.IP4Address.IsValid(spice_bind) and
2335 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP4_VERSION):
2336 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv4 address (%s), but"
2337 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2338 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2339 b1cb62bd Andrea Spadaccini
2340 b1cb62bd Andrea Spadaccini
        if (netutils.IP6Address.IsValid(spice_bind) and
2341 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP6_VERSION):
2342 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv6 address (%s), but"
2343 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2344 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2345 b451c4c7 Andrea Spadaccini
    else:
2346 0e1b03b9 Andrea Spadaccini
      # All the other SPICE parameters depend on spice_bind being set. Raise an
2347 0e1b03b9 Andrea Spadaccini
      # error if any of them is set without it.
2348 07788a0b Michael Hanselmann
      for param in _SPICE_ADDITIONAL_PARAMS:
2349 0e1b03b9 Andrea Spadaccini
        if hvparams[param]:
2350 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: %s requires %s to be set" %
2351 0e1b03b9 Andrea Spadaccini
                                       (param, constants.HV_KVM_SPICE_BIND))
2352 b1cb62bd Andrea Spadaccini
2353 d19d94db Guido Trotter
  @classmethod
2354 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
2355 d19d94db Guido Trotter
    """Check the given parameters for validity.
2356 d19d94db Guido Trotter

2357 d19d94db Guido Trotter
    @type hvparams:  dict
2358 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2359 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2360 d19d94db Guido Trotter

2361 d19d94db Guido Trotter
    """
2362 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2363 d19d94db Guido Trotter
2364 82e3bf85 Dimitris Aragiorgis
    kvm_path = hvparams[constants.HV_KVM_PATH]
2365 82e3bf85 Dimitris Aragiorgis
2366 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2367 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2368 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2369 d19d94db Guido Trotter
      try:
2370 1feb39ec Guido Trotter
        pwd.getpwnam(username)
2371 d19d94db Guido Trotter
      except KeyError:
2372 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
2373 d19d94db Guido Trotter
                                     % username)
2374 d19d94db Guido Trotter
2375 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2376 b1cb62bd Andrea Spadaccini
    if spice_bind:
2377 b1cb62bd Andrea Spadaccini
      # only one of VNC and SPICE can be used currently.
2378 b1cb62bd Andrea Spadaccini
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2379 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("Both SPICE and VNC are configured, but"
2380 b1cb62bd Andrea Spadaccini
                                     " only one of them can be used at a"
2381 afa9bb2e Michael Hanselmann
                                     " given time")
2382 b1cb62bd Andrea Spadaccini
2383 3b59ec02 Guido Trotter
      # check that KVM supports SPICE
2384 6e043e60 Guido Trotter
      kvmhelp = cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP)
2385 0ad7f5d8 Guido Trotter
      if not cls._SPICE_RE.search(kvmhelp):
2386 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE is configured, but it is not"
2387 afa9bb2e Michael Hanselmann
                                     " supported according to 'kvm --help'")
2388 b1cb62bd Andrea Spadaccini
2389 b1cb62bd Andrea Spadaccini
      # if spice_bind is not an IP address, it must be a valid interface
2390 afa9bb2e Michael Hanselmann
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind) or
2391 afa9bb2e Michael Hanselmann
                       netutils.IP6Address.IsValid(spice_bind))
2392 b1cb62bd Andrea Spadaccini
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2393 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE: The %s parameter must be either"
2394 b1cb62bd Andrea Spadaccini
                                     " a valid IP address or interface name" %
2395 b1cb62bd Andrea Spadaccini
                                     constants.HV_KVM_SPICE_BIND)
2396 b1cb62bd Andrea Spadaccini
2397 82e3bf85 Dimitris Aragiorgis
    machine_version = hvparams[constants.HV_KVM_MACHINE_VERSION]
2398 82e3bf85 Dimitris Aragiorgis
    if machine_version:
2399 6e043e60 Guido Trotter
      output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2400 82e3bf85 Dimitris Aragiorgis
      if not cls._CHECK_MACHINE_VERSION_RE(machine_version).search(output):
2401 82e3bf85 Dimitris Aragiorgis
        raise errors.HypervisorError("Unsupported machine version: %s" %
2402 82e3bf85 Dimitris Aragiorgis
                                     machine_version)
2403 82e3bf85 Dimitris Aragiorgis
2404 f5118ade Iustin Pop
  @classmethod
2405 f5118ade Iustin Pop
  def PowercycleNode(cls):
2406 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
2407 f5118ade Iustin Pop

2408 f5118ade Iustin Pop
    """
2409 f5118ade Iustin Pop
    cls.LinuxPowercycle()