Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 172a75dc

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

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

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

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

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

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

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

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

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

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

193 58502c9e Dimitris Aragiorgis
  @type serialized_runtime: string
194 58502c9e Dimitris Aragiorgis
  @param serialized_runtime: raw text data read from actual runtime file
195 58502c9e Dimitris Aragiorgis
  @return: (cmd, nics, hvparams, bdevs)
196 58502c9e Dimitris Aragiorgis
  @rtype: list
197 58502c9e Dimitris Aragiorgis

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

216 ea2bcb82 Michael Hanselmann
  @see: L{_ProbeTapVnetHdr}
217 ea2bcb82 Michael Hanselmann

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

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

243 199b2053 Apollon Oikonomopoulos
   @type fd: int
244 199b2053 Apollon Oikonomopoulos
   @param fd: the file descriptor of /dev/net/tun
245 199b2053 Apollon Oikonomopoulos

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

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

267 199b2053 Apollon Oikonomopoulos
  @type vnet_hdr: boolean
268 199b2053 Apollon Oikonomopoulos
  @param vnet_hdr: Enable the VNET Header
269 199b2053 Apollon Oikonomopoulos
  @return: (ifname, tapfd)
270 199b2053 Apollon Oikonomopoulos
  @rtype: tuple
271 199b2053 Apollon Oikonomopoulos

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

300 91c10532 Andrea Spadaccini
  """
301 91c10532 Andrea Spadaccini
  def __init__(self, data):
302 91c10532 Andrea Spadaccini
    """Creates a new QMP message based on the passed data.
303 91c10532 Andrea Spadaccini

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

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

318 91c10532 Andrea Spadaccini
    """
319 9b87c2cf Michael Hanselmann
    return self.data.get(field_name, None)
320 91c10532 Andrea Spadaccini
321 91c10532 Andrea Spadaccini
  def __setitem__(self, field_name, field_value):
322 91c10532 Andrea Spadaccini
    """Set the value of the required field_name to field_value.
323 91c10532 Andrea Spadaccini

324 91c10532 Andrea Spadaccini
    """
325 91c10532 Andrea Spadaccini
    self.data[field_name] = field_value
326 91c10532 Andrea Spadaccini
327 91c10532 Andrea Spadaccini
  @staticmethod
328 91c10532 Andrea Spadaccini
  def BuildFromJsonString(json_string):
329 91c10532 Andrea Spadaccini
    """Build a QmpMessage from a JSON encoded string.
330 91c10532 Andrea Spadaccini

331 91c10532 Andrea Spadaccini
    @type json_string: str
332 91c10532 Andrea Spadaccini
    @param json_string: JSON string representing the message
333 91c10532 Andrea Spadaccini
    @rtype: L{QmpMessage}
334 91c10532 Andrea Spadaccini
    @return: a L{QmpMessage} built from json_string
335 91c10532 Andrea Spadaccini

336 91c10532 Andrea Spadaccini
    """
337 91c10532 Andrea Spadaccini
    # Parse the string
338 91c10532 Andrea Spadaccini
    data = serializer.LoadJson(json_string)
339 91c10532 Andrea Spadaccini
    return QmpMessage(data)
340 91c10532 Andrea Spadaccini
341 91c10532 Andrea Spadaccini
  def __str__(self):
342 a182a3ed Michael Hanselmann
    # The protocol expects the JSON object to be sent as a single line.
343 a182a3ed Michael Hanselmann
    return serializer.DumpJson(self.data)
344 91c10532 Andrea Spadaccini
345 91c10532 Andrea Spadaccini
  def __eq__(self, other):
346 91c10532 Andrea Spadaccini
    # When comparing two QmpMessages, we are interested in comparing
347 91c10532 Andrea Spadaccini
    # their internal representation of the message data
348 91c10532 Andrea Spadaccini
    return self.data == other.data
349 91c10532 Andrea Spadaccini
350 91c10532 Andrea Spadaccini
351 172a75dc Dimitris Aragiorgis
class MonitorSocket(object):
352 91c10532 Andrea Spadaccini
  _SOCKET_TIMEOUT = 5
353 91c10532 Andrea Spadaccini
354 91c10532 Andrea Spadaccini
  def __init__(self, monitor_filename):
355 172a75dc Dimitris Aragiorgis
    """Instantiates the MonitorSocket object.
356 91c10532 Andrea Spadaccini

357 91c10532 Andrea Spadaccini
    @type monitor_filename: string
358 91c10532 Andrea Spadaccini
    @param monitor_filename: the filename of the UNIX raw socket on which the
359 172a75dc Dimitris Aragiorgis
                             monitor (QMP or simple one) is listening
360 91c10532 Andrea Spadaccini

361 91c10532 Andrea Spadaccini
    """
362 91c10532 Andrea Spadaccini
    self.monitor_filename = monitor_filename
363 91c10532 Andrea Spadaccini
    self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
364 91c10532 Andrea Spadaccini
    # We want to fail if the server doesn't send a complete message
365 91c10532 Andrea Spadaccini
    # in a reasonable amount of time
366 91c10532 Andrea Spadaccini
    self.sock.settimeout(self._SOCKET_TIMEOUT)
367 91c10532 Andrea Spadaccini
    self._connected = False
368 91c10532 Andrea Spadaccini
369 fc84cd5d Guido Trotter
  def _check_socket(self):
370 fc84cd5d Guido Trotter
    sock_stat = None
371 fc84cd5d Guido Trotter
    try:
372 fc84cd5d Guido Trotter
      sock_stat = os.stat(self.monitor_filename)
373 fc84cd5d Guido Trotter
    except EnvironmentError, err:
374 fc84cd5d Guido Trotter
      if err.errno == errno.ENOENT:
375 172a75dc Dimitris Aragiorgis
        raise errors.HypervisorError("No monitor socket found")
376 fc84cd5d Guido Trotter
      else:
377 172a75dc Dimitris Aragiorgis
        raise errors.HypervisorError("Error checking monitor socket: %s",
378 fc84cd5d Guido Trotter
                                     utils.ErrnoOrStr(err))
379 fc84cd5d Guido Trotter
    if not stat.S_ISSOCK(sock_stat.st_mode):
380 172a75dc Dimitris Aragiorgis
      raise errors.HypervisorError("Monitor socket is not a socket")
381 fc84cd5d Guido Trotter
382 91c10532 Andrea Spadaccini
  def _check_connection(self):
383 91c10532 Andrea Spadaccini
    """Make sure that the connection is established.
384 91c10532 Andrea Spadaccini

385 91c10532 Andrea Spadaccini
    """
386 91c10532 Andrea Spadaccini
    if not self._connected:
387 172a75dc Dimitris Aragiorgis
      raise errors.ProgrammerError("To use a MonitorSocket you need to first"
388 91c10532 Andrea Spadaccini
                                   " invoke connect() on it")
389 91c10532 Andrea Spadaccini
390 91c10532 Andrea Spadaccini
  def connect(self):
391 172a75dc Dimitris Aragiorgis
    """Connects to the monitor.
392 91c10532 Andrea Spadaccini

393 172a75dc Dimitris Aragiorgis
    Connects to the UNIX socket
394 91c10532 Andrea Spadaccini

395 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
396 91c10532 Andrea Spadaccini

397 91c10532 Andrea Spadaccini
    """
398 fc84cd5d Guido Trotter
    if self._connected:
399 fc84cd5d Guido Trotter
      raise errors.ProgrammerError("Cannot connect twice")
400 fc84cd5d Guido Trotter
401 fc84cd5d Guido Trotter
    self._check_socket()
402 fc84cd5d Guido Trotter
403 fc84cd5d Guido Trotter
    # Check file existance/stuff
404 fc84cd5d Guido Trotter
    try:
405 fc84cd5d Guido Trotter
      self.sock.connect(self.monitor_filename)
406 fc84cd5d Guido Trotter
    except EnvironmentError:
407 fc84cd5d Guido Trotter
      raise errors.HypervisorError("Can't connect to qmp socket")
408 91c10532 Andrea Spadaccini
    self._connected = True
409 91c10532 Andrea Spadaccini
410 172a75dc Dimitris Aragiorgis
  def close(self):
411 172a75dc Dimitris Aragiorgis
    """Closes the socket
412 172a75dc Dimitris Aragiorgis

413 172a75dc Dimitris Aragiorgis
    It cannot be used after this call.
414 172a75dc Dimitris Aragiorgis

415 172a75dc Dimitris Aragiorgis
    """
416 172a75dc Dimitris Aragiorgis
    self.sock.close()
417 172a75dc Dimitris Aragiorgis
418 172a75dc Dimitris Aragiorgis
419 172a75dc Dimitris Aragiorgis
class QmpConnection(MonitorSocket):
420 172a75dc Dimitris Aragiorgis
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
421 172a75dc Dimitris Aragiorgis

422 172a75dc Dimitris Aragiorgis
  """
423 172a75dc Dimitris Aragiorgis
  _FIRST_MESSAGE_KEY = "QMP"
424 172a75dc Dimitris Aragiorgis
  _EVENT_KEY = "event"
425 172a75dc Dimitris Aragiorgis
  _ERROR_KEY = "error"
426 172a75dc Dimitris Aragiorgis
  _RETURN_KEY = RETURN_KEY = "return"
427 172a75dc Dimitris Aragiorgis
  _ACTUAL_KEY = ACTUAL_KEY = "actual"
428 172a75dc Dimitris Aragiorgis
  _ERROR_CLASS_KEY = "class"
429 172a75dc Dimitris Aragiorgis
  _ERROR_DATA_KEY = "data"
430 172a75dc Dimitris Aragiorgis
  _ERROR_DESC_KEY = "desc"
431 172a75dc Dimitris Aragiorgis
  _EXECUTE_KEY = "execute"
432 172a75dc Dimitris Aragiorgis
  _ARGUMENTS_KEY = "arguments"
433 172a75dc Dimitris Aragiorgis
  _CAPABILITIES_COMMAND = "qmp_capabilities"
434 172a75dc Dimitris Aragiorgis
  _MESSAGE_END_TOKEN = "\r\n"
435 172a75dc Dimitris Aragiorgis
436 172a75dc Dimitris Aragiorgis
  def __init__(self, monitor_filename):
437 172a75dc Dimitris Aragiorgis
    super(QmpConnection, self).__init__(monitor_filename)
438 172a75dc Dimitris Aragiorgis
    self._buf = ""
439 172a75dc Dimitris Aragiorgis
440 172a75dc Dimitris Aragiorgis
  def connect(self):
441 172a75dc Dimitris Aragiorgis
    """Connects to the QMP monitor.
442 172a75dc Dimitris Aragiorgis

443 172a75dc Dimitris Aragiorgis
    Connects to the UNIX socket and makes sure that we can actually send and
444 172a75dc Dimitris Aragiorgis
    receive data to the kvm instance via QMP.
445 172a75dc Dimitris Aragiorgis

446 172a75dc Dimitris Aragiorgis
    @raise errors.HypervisorError: when there are communication errors
447 172a75dc Dimitris Aragiorgis
    @raise errors.ProgrammerError: when there are data serialization errors
448 172a75dc Dimitris Aragiorgis

449 172a75dc Dimitris Aragiorgis
    """
450 172a75dc Dimitris Aragiorgis
    super(QmpConnection, self).connect()
451 91c10532 Andrea Spadaccini
    # Check if we receive a correct greeting message from the server
452 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 2.2)
453 91c10532 Andrea Spadaccini
    greeting = self._Recv()
454 91c10532 Andrea Spadaccini
    if not greeting[self._FIRST_MESSAGE_KEY]:
455 91c10532 Andrea Spadaccini
      self._connected = False
456 afa9bb2e Michael Hanselmann
      raise errors.HypervisorError("kvm: QMP communication error (wrong"
457 91c10532 Andrea Spadaccini
                                   " server greeting")
458 91c10532 Andrea Spadaccini
459 91c10532 Andrea Spadaccini
    # Let's put the monitor in command mode using the qmp_capabilities
460 91c10532 Andrea Spadaccini
    # command, or else no command will be executable.
461 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 4)
462 91c10532 Andrea Spadaccini
    self.Execute(self._CAPABILITIES_COMMAND)
463 91c10532 Andrea Spadaccini
464 91c10532 Andrea Spadaccini
  def _ParseMessage(self, buf):
465 91c10532 Andrea Spadaccini
    """Extract and parse a QMP message from the given buffer.
466 91c10532 Andrea Spadaccini

467 91c10532 Andrea Spadaccini
    Seeks for a QMP message in the given buf. If found, it parses it and
468 91c10532 Andrea Spadaccini
    returns it together with the rest of the characters in the buf.
469 91c10532 Andrea Spadaccini
    If no message is found, returns None and the whole buffer.
470 91c10532 Andrea Spadaccini

471 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
472 91c10532 Andrea Spadaccini

473 91c10532 Andrea Spadaccini
    """
474 91c10532 Andrea Spadaccini
    message = None
475 91c10532 Andrea Spadaccini
    # Check if we got the message end token (CRLF, as per the QEMU Protocol
476 91c10532 Andrea Spadaccini
    # Specification 0.1 - Section 2.1.1)
477 91c10532 Andrea Spadaccini
    pos = buf.find(self._MESSAGE_END_TOKEN)
478 91c10532 Andrea Spadaccini
    if pos >= 0:
479 91c10532 Andrea Spadaccini
      try:
480 91c10532 Andrea Spadaccini
        message = QmpMessage.BuildFromJsonString(buf[:pos + 1])
481 91c10532 Andrea Spadaccini
      except Exception, err:
482 91c10532 Andrea Spadaccini
        raise errors.ProgrammerError("QMP data serialization error: %s" % err)
483 91c10532 Andrea Spadaccini
      buf = buf[pos + 1:]
484 91c10532 Andrea Spadaccini
485 91c10532 Andrea Spadaccini
    return (message, buf)
486 91c10532 Andrea Spadaccini
487 91c10532 Andrea Spadaccini
  def _Recv(self):
488 91c10532 Andrea Spadaccini
    """Receives a message from QMP and decodes the received JSON object.
489 91c10532 Andrea Spadaccini

490 91c10532 Andrea Spadaccini
    @rtype: QmpMessage
491 91c10532 Andrea Spadaccini
    @return: the received message
492 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
493 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
494 91c10532 Andrea Spadaccini

495 91c10532 Andrea Spadaccini
    """
496 91c10532 Andrea Spadaccini
    self._check_connection()
497 91c10532 Andrea Spadaccini
498 91c10532 Andrea Spadaccini
    # Check if there is already a message in the buffer
499 91c10532 Andrea Spadaccini
    (message, self._buf) = self._ParseMessage(self._buf)
500 91c10532 Andrea Spadaccini
    if message:
501 91c10532 Andrea Spadaccini
      return message
502 91c10532 Andrea Spadaccini
503 91c10532 Andrea Spadaccini
    recv_buffer = StringIO.StringIO(self._buf)
504 91c10532 Andrea Spadaccini
    recv_buffer.seek(len(self._buf))
505 91c10532 Andrea Spadaccini
    try:
506 91c10532 Andrea Spadaccini
      while True:
507 91c10532 Andrea Spadaccini
        data = self.sock.recv(4096)
508 91c10532 Andrea Spadaccini
        if not data:
509 91c10532 Andrea Spadaccini
          break
510 91c10532 Andrea Spadaccini
        recv_buffer.write(data)
511 91c10532 Andrea Spadaccini
512 91c10532 Andrea Spadaccini
        (message, self._buf) = self._ParseMessage(recv_buffer.getvalue())
513 91c10532 Andrea Spadaccini
        if message:
514 91c10532 Andrea Spadaccini
          return message
515 91c10532 Andrea Spadaccini
516 91c10532 Andrea Spadaccini
    except socket.timeout, err:
517 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while receiving a QMP message: "
518 91c10532 Andrea Spadaccini
                                   "%s" % (err))
519 91c10532 Andrea Spadaccini
    except socket.error, err:
520 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to receive data from KVM using the"
521 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
522 91c10532 Andrea Spadaccini
523 91c10532 Andrea Spadaccini
  def _Send(self, message):
524 91c10532 Andrea Spadaccini
    """Encodes and sends a message to KVM using QMP.
525 91c10532 Andrea Spadaccini

526 91c10532 Andrea Spadaccini
    @type message: QmpMessage
527 91c10532 Andrea Spadaccini
    @param message: message to send to KVM
528 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
529 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
530 91c10532 Andrea Spadaccini

531 91c10532 Andrea Spadaccini
    """
532 91c10532 Andrea Spadaccini
    self._check_connection()
533 91c10532 Andrea Spadaccini
    try:
534 91c10532 Andrea Spadaccini
      message_str = str(message)
535 91c10532 Andrea Spadaccini
    except Exception, err:
536 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("QMP data deserialization error: %s" % err)
537 91c10532 Andrea Spadaccini
538 91c10532 Andrea Spadaccini
    try:
539 91c10532 Andrea Spadaccini
      self.sock.sendall(message_str)
540 91c10532 Andrea Spadaccini
    except socket.timeout, err:
541 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while sending a QMP message: "
542 91c10532 Andrea Spadaccini
                                   "%s (%s)" % (err.string, err.errno))
543 91c10532 Andrea Spadaccini
    except socket.error, err:
544 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to send data from KVM using the"
545 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
546 91c10532 Andrea Spadaccini
547 91c10532 Andrea Spadaccini
  def Execute(self, command, arguments=None):
548 91c10532 Andrea Spadaccini
    """Executes a QMP command and returns the response of the server.
549 91c10532 Andrea Spadaccini

550 91c10532 Andrea Spadaccini
    @type command: str
551 91c10532 Andrea Spadaccini
    @param command: the command to execute
552 91c10532 Andrea Spadaccini
    @type arguments: dict
553 91c10532 Andrea Spadaccini
    @param arguments: dictionary of arguments to be passed to the command
554 91c10532 Andrea Spadaccini
    @rtype: dict
555 91c10532 Andrea Spadaccini
    @return: dictionary representing the received JSON object
556 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
557 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
558 91c10532 Andrea Spadaccini

559 91c10532 Andrea Spadaccini
    """
560 91c10532 Andrea Spadaccini
    self._check_connection()
561 91c10532 Andrea Spadaccini
    message = QmpMessage({self._EXECUTE_KEY: command})
562 91c10532 Andrea Spadaccini
    if arguments:
563 91c10532 Andrea Spadaccini
      message[self._ARGUMENTS_KEY] = arguments
564 91c10532 Andrea Spadaccini
    self._Send(message)
565 91c10532 Andrea Spadaccini
566 91c10532 Andrea Spadaccini
    # Events can occur between the sending of the command and the reception
567 91c10532 Andrea Spadaccini
    # of the response, so we need to filter out messages with the event key.
568 91c10532 Andrea Spadaccini
    while True:
569 91c10532 Andrea Spadaccini
      response = self._Recv()
570 91c10532 Andrea Spadaccini
      err = response[self._ERROR_KEY]
571 91c10532 Andrea Spadaccini
      if err:
572 91c10532 Andrea Spadaccini
        raise errors.HypervisorError("kvm: error executing the %s"
573 91c10532 Andrea Spadaccini
                                     " command: %s (%s, %s):" %
574 91c10532 Andrea Spadaccini
                                     (command,
575 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DESC_KEY],
576 91c10532 Andrea Spadaccini
                                      err[self._ERROR_CLASS_KEY],
577 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DATA_KEY]))
578 91c10532 Andrea Spadaccini
579 91c10532 Andrea Spadaccini
      elif not response[self._EVENT_KEY]:
580 91c10532 Andrea Spadaccini
        return response
581 91c10532 Andrea Spadaccini
582 91c10532 Andrea Spadaccini
583 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
584 65107a2f Michael Hanselmann
  """KVM hypervisor interface
585 65107a2f Michael Hanselmann

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

770 98ec75d6 Iustin Pop
    """
771 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
772 98ec75d6 Iustin Pop
773 263b8de6 Guido Trotter
  @classmethod
774 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
775 7548396c Guido Trotter
    """Returns the instance uidfile.
776 7548396c Guido Trotter

777 7548396c Guido Trotter
    """
778 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
779 7548396c Guido Trotter
780 7548396c Guido Trotter
  @classmethod
781 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
782 263b8de6 Guido Trotter
    """Check pid file for instance information.
783 263b8de6 Guido Trotter

784 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
785 263b8de6 Guido Trotter
    information from its command line.
786 263b8de6 Guido Trotter

787 263b8de6 Guido Trotter
    @type pid: string or int
788 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
789 263b8de6 Guido Trotter
    @rtype: tuple
790 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
791 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
792 263b8de6 Guido Trotter

793 263b8de6 Guido Trotter
    """
794 263b8de6 Guido Trotter
    alive = utils.IsProcessAlive(pid)
795 263b8de6 Guido Trotter
    if not alive:
796 263b8de6 Guido Trotter
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
797 263b8de6 Guido Trotter
798 263b8de6 Guido Trotter
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
799 263b8de6 Guido Trotter
    try:
800 263b8de6 Guido Trotter
      cmdline = utils.ReadFile(cmdline_file)
801 263b8de6 Guido Trotter
    except EnvironmentError, err:
802 263b8de6 Guido Trotter
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
803 263b8de6 Guido Trotter
                                   (pid, err))
804 263b8de6 Guido Trotter
805 263b8de6 Guido Trotter
    instance = None
806 263b8de6 Guido Trotter
    memory = 0
807 263b8de6 Guido Trotter
    vcpus = 0
808 263b8de6 Guido Trotter
809 d0c8c01d Iustin Pop
    arg_list = cmdline.split("\x00")
810 263b8de6 Guido Trotter
    while arg_list:
811 e687ec01 Michael Hanselmann
      arg = arg_list.pop(0)
812 263b8de6 Guido Trotter
      if arg == "-name":
813 263b8de6 Guido Trotter
        instance = arg_list.pop(0)
814 263b8de6 Guido Trotter
      elif arg == "-m":
815 263b8de6 Guido Trotter
        memory = int(arg_list.pop(0))
816 263b8de6 Guido Trotter
      elif arg == "-smp":
817 4888a609 Guido Trotter
        vcpus = int(arg_list.pop(0).split(",")[0])
818 263b8de6 Guido Trotter
819 263b8de6 Guido Trotter
    if instance is None:
820 263b8de6 Guido Trotter
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
821 263b8de6 Guido Trotter
                                   " instance" % pid)
822 263b8de6 Guido Trotter
823 263b8de6 Guido Trotter
    return (instance, memory, vcpus)
824 263b8de6 Guido Trotter
825 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
826 263b8de6 Guido Trotter
    """Returns the instance pidfile, pid, and liveness.
827 263b8de6 Guido Trotter

828 263b8de6 Guido Trotter
    @type instance_name: string
829 263b8de6 Guido Trotter
    @param instance_name: instance name
830 263b8de6 Guido Trotter
    @rtype: tuple
831 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
832 1f8b3a27 Guido Trotter

833 1f8b3a27 Guido Trotter
    """
834 98ec75d6 Iustin Pop
    pidfile = self._InstancePidFile(instance_name)
835 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
836 263b8de6 Guido Trotter
837 263b8de6 Guido Trotter
    alive = False
838 263b8de6 Guido Trotter
    try:
839 263b8de6 Guido Trotter
      cmd_instance = self._InstancePidInfo(pid)[0]
840 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
841 263b8de6 Guido Trotter
    except errors.HypervisorError:
842 263b8de6 Guido Trotter
      pass
843 1f8b3a27 Guido Trotter
844 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
845 1f8b3a27 Guido Trotter
846 5905901c Iustin Pop
  def _CheckDown(self, instance_name):
847 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
848 5905901c Iustin Pop

849 5905901c Iustin Pop
    """
850 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
851 5905901c Iustin Pop
    if alive:
852 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
853 5905901c Iustin Pop
                                   (instance_name, "already running"))
854 5905901c Iustin Pop
855 0df4d98a Guido Trotter
  @classmethod
856 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
857 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
858 c4fbefc8 Guido Trotter

859 c4fbefc8 Guido Trotter
    """
860 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
861 c4fbefc8 Guido Trotter
862 0df4d98a Guido Trotter
  @classmethod
863 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
864 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
865 c4fbefc8 Guido Trotter

866 c4fbefc8 Guido Trotter
    """
867 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
868 c4fbefc8 Guido Trotter
869 91c10532 Andrea Spadaccini
  @classmethod
870 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
871 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
872 91c10532 Andrea Spadaccini

873 91c10532 Andrea Spadaccini
    """
874 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
875 91c10532 Andrea Spadaccini
876 86d6bc2a Guido Trotter
  @staticmethod
877 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
878 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
879 86d6bc2a Guido Trotter

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

882 86d6bc2a Guido Trotter
    """
883 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
884 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
885 86d6bc2a Guido Trotter
    else:
886 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
887 86d6bc2a Guido Trotter
888 0df4d98a Guido Trotter
  @classmethod
889 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
890 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
891 38e250ba Guido Trotter

892 38e250ba Guido Trotter
    """
893 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
894 38e250ba Guido Trotter
895 7e66c35b Guido Trotter
  @classmethod
896 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
897 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
898 547a63b7 Balazs Lecz

899 547a63b7 Balazs Lecz
    """
900 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
901 547a63b7 Balazs Lecz
902 547a63b7 Balazs Lecz
  @classmethod
903 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
904 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
905 5d9bfd87 Apollon Oikonomopoulos
    given instance.
906 5d9bfd87 Apollon Oikonomopoulos

907 5d9bfd87 Apollon Oikonomopoulos
    """
908 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
909 5d9bfd87 Apollon Oikonomopoulos
910 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
911 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
912 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
913 5d9bfd87 Apollon Oikonomopoulos

914 5d9bfd87 Apollon Oikonomopoulos
    """
915 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
916 5d9bfd87 Apollon Oikonomopoulos
917 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
918 4f580fef Sébastien Bocahu
  def _InstanceKeymapFile(cls, instance_name):
919 4f580fef Sébastien Bocahu
    """Returns the name of the file containing the keymap for a given instance
920 4f580fef Sébastien Bocahu

921 4f580fef Sébastien Bocahu
    """
922 4f580fef Sébastien Bocahu
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
923 4f580fef Sébastien Bocahu
924 4f580fef Sébastien Bocahu
  @classmethod
925 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
926 7548396c Guido Trotter
    """Try to read a uid file
927 7548396c Guido Trotter

928 7548396c Guido Trotter
    """
929 7548396c Guido Trotter
    if os.path.exists(uid_file):
930 7548396c Guido Trotter
      try:
931 682f7601 Guido Trotter
        uid = int(utils.ReadOneLineFile(uid_file))
932 aa0b600b Guido Trotter
        return uid
933 7548396c Guido Trotter
      except EnvironmentError:
934 7548396c Guido Trotter
        logging.warning("Can't read uid file", exc_info=True)
935 7548396c Guido Trotter
      except (TypeError, ValueError):
936 7548396c Guido Trotter
        logging.warning("Can't parse uid file contents", exc_info=True)
937 aa0b600b Guido Trotter
    return None
938 7548396c Guido Trotter
939 7548396c Guido Trotter
  @classmethod
940 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
941 547a63b7 Balazs Lecz
    """Removes an instance's rutime sockets/files/dirs.
942 7e66c35b Guido Trotter

943 7e66c35b Guido Trotter
    """
944 7e66c35b Guido Trotter
    utils.RemoveFile(pidfile)
945 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
946 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceSerial(instance_name))
947 91c10532 Andrea Spadaccini
    utils.RemoveFile(cls._InstanceQmpMonitor(instance_name))
948 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
949 4f580fef Sébastien Bocahu
    utils.RemoveFile(cls._InstanceKeymapFile(instance_name))
950 7548396c Guido Trotter
    uid_file = cls._InstanceUidFile(instance_name)
951 7548396c Guido Trotter
    uid = cls._TryReadUidFile(uid_file)
952 7548396c Guido Trotter
    utils.RemoveFile(uid_file)
953 7548396c Guido Trotter
    if uid is not None:
954 7548396c Guido Trotter
      uidpool.ReleaseUid(uid)
955 7be85163 Guido Trotter
    try:
956 7be85163 Guido Trotter
      shutil.rmtree(cls._InstanceNICDir(instance_name))
957 7be85163 Guido Trotter
    except OSError, err:
958 7be85163 Guido Trotter
      if err.errno != errno.ENOENT:
959 7be85163 Guido Trotter
        raise
960 547a63b7 Balazs Lecz
    try:
961 547a63b7 Balazs Lecz
      chroot_dir = cls._InstanceChrootDir(instance_name)
962 547a63b7 Balazs Lecz
      utils.RemoveDir(chroot_dir)
963 547a63b7 Balazs Lecz
    except OSError, err:
964 547a63b7 Balazs Lecz
      if err.errno == errno.ENOTEMPTY:
965 547a63b7 Balazs Lecz
        # The chroot directory is expected to be empty, but it isn't.
966 547a63b7 Balazs Lecz
        new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
967 547a63b7 Balazs Lecz
                                          prefix="%s-%s-" %
968 547a63b7 Balazs Lecz
                                          (instance_name,
969 547a63b7 Balazs Lecz
                                           utils.TimestampForFilename()))
970 547a63b7 Balazs Lecz
        logging.warning("The chroot directory of instance %s can not be"
971 547a63b7 Balazs Lecz
                        " removed as it is not empty. Moving it to the"
972 547a63b7 Balazs Lecz
                        " quarantine instead. Please investigate the"
973 547a63b7 Balazs Lecz
                        " contents (%s) and clean up manually",
974 547a63b7 Balazs Lecz
                        instance_name, new_chroot_dir)
975 547a63b7 Balazs Lecz
        utils.RenameFile(chroot_dir, new_chroot_dir)
976 547a63b7 Balazs Lecz
      else:
977 547a63b7 Balazs Lecz
        raise
978 7e66c35b Guido Trotter
979 748e4b5a Michael Hanselmann
  @staticmethod
980 5d9bfd87 Apollon Oikonomopoulos
  def _ConfigureNIC(instance, seq, nic, tap):
981 5d9bfd87 Apollon Oikonomopoulos
    """Run the network configuration script for a specified NIC
982 eb58f9b1 Guido Trotter

983 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
984 eb58f9b1 Guido Trotter
    @type instance: instance object
985 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
986 eb58f9b1 Guido Trotter
    @type seq: int
987 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
988 eb58f9b1 Guido Trotter
    @type nic: nic object
989 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
990 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
991 eb58f9b1 Guido Trotter

992 eb58f9b1 Guido Trotter
    """
993 5d9bfd87 Apollon Oikonomopoulos
    if instance.tags:
994 5d9bfd87 Apollon Oikonomopoulos
      tags = " ".join(instance.tags)
995 5d9bfd87 Apollon Oikonomopoulos
    else:
996 5d9bfd87 Apollon Oikonomopoulos
      tags = ""
997 5d9bfd87 Apollon Oikonomopoulos
998 5d9bfd87 Apollon Oikonomopoulos
    env = {
999 5d9bfd87 Apollon Oikonomopoulos
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
1000 5d9bfd87 Apollon Oikonomopoulos
      "INSTANCE": instance.name,
1001 5d9bfd87 Apollon Oikonomopoulos
      "MAC": nic.mac,
1002 5d9bfd87 Apollon Oikonomopoulos
      "MODE": nic.nicparams[constants.NIC_MODE],
1003 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE": tap,
1004 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE_INDEX": str(seq),
1005 5d9bfd87 Apollon Oikonomopoulos
      "TAGS": tags,
1006 5d9bfd87 Apollon Oikonomopoulos
    }
1007 5d9bfd87 Apollon Oikonomopoulos
1008 5d9bfd87 Apollon Oikonomopoulos
    if nic.ip:
1009 5d9bfd87 Apollon Oikonomopoulos
      env["IP"] = nic.ip
1010 5d9bfd87 Apollon Oikonomopoulos
1011 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_LINK]:
1012 5d9bfd87 Apollon Oikonomopoulos
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
1013 5d9bfd87 Apollon Oikonomopoulos
1014 a5ad5e58 Apollon Oikonomopoulos
    if nic.network:
1015 cbe4a0a5 Dimitris Aragiorgis
      n = objects.Network.FromDict(nic.netinfo)
1016 7e8f03e3 Dimitris Aragiorgis
      env.update(n.HooksDict())
1017 a5ad5e58 Apollon Oikonomopoulos
1018 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1019 5d9bfd87 Apollon Oikonomopoulos
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
1020 5d9bfd87 Apollon Oikonomopoulos
1021 9d9bded1 Michael Hanselmann
    result = utils.RunCmd([pathutils.KVM_IFUP, tap], env=env)
1022 5d9bfd87 Apollon Oikonomopoulos
    if result.failed:
1023 afa9bb2e Michael Hanselmann
      raise errors.HypervisorError("Failed to configure interface %s: %s;"
1024 afa9bb2e Michael Hanselmann
                                   " network configuration script output: %s" %
1025 5d9bfd87 Apollon Oikonomopoulos
                                   (tap, result.fail_reason, result.output))
1026 eb58f9b1 Guido Trotter
1027 b693125f Tsachy Shacham
  @staticmethod
1028 b693125f Tsachy Shacham
  def _VerifyAffinityPackage():
1029 b693125f Tsachy Shacham
    if affinity is None:
1030 b693125f Tsachy Shacham
      raise errors.HypervisorError("affinity Python package not"
1031 5ae4945a Iustin Pop
                                   " found; cannot use CPU pinning under KVM")
1032 b693125f Tsachy Shacham
1033 b693125f Tsachy Shacham
  @staticmethod
1034 b693125f Tsachy Shacham
  def _BuildAffinityCpuMask(cpu_list):
1035 b693125f Tsachy Shacham
    """Create a CPU mask suitable for sched_setaffinity from a list of
1036 b693125f Tsachy Shacham
    CPUs.
1037 b693125f Tsachy Shacham

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

1041 b693125f Tsachy Shacham
    @type cpu_list: list of int
1042 b693125f Tsachy Shacham
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
1043 b693125f Tsachy Shacham
    @rtype: int
1044 b693125f Tsachy Shacham
    @return: a bit mask of CPU affinities
1045 b693125f Tsachy Shacham

1046 b693125f Tsachy Shacham
    """
1047 b693125f Tsachy Shacham
    if cpu_list == constants.CPU_PINNING_OFF:
1048 b693125f Tsachy Shacham
      return constants.CPU_PINNING_ALL_KVM
1049 b693125f Tsachy Shacham
    else:
1050 b693125f Tsachy Shacham
      return sum(2 ** cpu for cpu in cpu_list)
1051 b693125f Tsachy Shacham
1052 b693125f Tsachy Shacham
  @classmethod
1053 b693125f Tsachy Shacham
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
1054 b693125f Tsachy Shacham
    """Change CPU affinity for running VM according to given CPU mask.
1055 b693125f Tsachy Shacham

1056 b693125f Tsachy Shacham
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
1057 b693125f Tsachy Shacham
    @type cpu_mask: string
1058 b693125f Tsachy Shacham
    @param process_id: process ID of KVM process. Used to pin entire VM
1059 b693125f Tsachy Shacham
                       to physical CPUs.
1060 b693125f Tsachy Shacham
    @type process_id: int
1061 b693125f Tsachy Shacham
    @param thread_dict: map of virtual CPUs to KVM thread IDs
1062 b693125f Tsachy Shacham
    @type thread_dict: dict int:int
1063 b693125f Tsachy Shacham

1064 b693125f Tsachy Shacham
    """
1065 b693125f Tsachy Shacham
    # Convert the string CPU mask to a list of list of int's
1066 b693125f Tsachy Shacham
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
1067 b693125f Tsachy Shacham
1068 b693125f Tsachy Shacham
    if len(cpu_list) == 1:
1069 b693125f Tsachy Shacham
      all_cpu_mapping = cpu_list[0]
1070 b693125f Tsachy Shacham
      if all_cpu_mapping == constants.CPU_PINNING_OFF:
1071 b693125f Tsachy Shacham
        # If CPU pinning has 1 entry that's "all", then do nothing
1072 b693125f Tsachy Shacham
        pass
1073 b693125f Tsachy Shacham
      else:
1074 b693125f Tsachy Shacham
        # If CPU pinning has one non-all entry, map the entire VM to
1075 b693125f Tsachy Shacham
        # one set of physical CPUs
1076 b693125f Tsachy Shacham
        cls._VerifyAffinityPackage()
1077 5ae4945a Iustin Pop
        affinity.set_process_affinity_mask(
1078 5ae4945a Iustin Pop
          process_id, cls._BuildAffinityCpuMask(all_cpu_mapping))
1079 b693125f Tsachy Shacham
    else:
1080 b693125f Tsachy Shacham
      # The number of vCPUs mapped should match the number of vCPUs
1081 b693125f Tsachy Shacham
      # reported by KVM. This was already verified earlier, so
1082 b693125f Tsachy Shacham
      # here only as a sanity check.
1083 b693125f Tsachy Shacham
      assert len(thread_dict) == len(cpu_list)
1084 b693125f Tsachy Shacham
      cls._VerifyAffinityPackage()
1085 b693125f Tsachy Shacham
1086 b693125f Tsachy Shacham
      # For each vCPU, map it to the proper list of physical CPUs
1087 b693125f Tsachy Shacham
      for vcpu, i in zip(cpu_list, range(len(cpu_list))):
1088 b693125f Tsachy Shacham
        affinity.set_process_affinity_mask(thread_dict[i],
1089 5ae4945a Iustin Pop
                                           cls._BuildAffinityCpuMask(vcpu))
1090 b693125f Tsachy Shacham
1091 b693125f Tsachy Shacham
  def _GetVcpuThreadIds(self, instance_name):
1092 b693125f Tsachy Shacham
    """Get a mapping of vCPU no. to thread IDs for the instance
1093 b693125f Tsachy Shacham

1094 b693125f Tsachy Shacham
    @type instance_name: string
1095 b693125f Tsachy Shacham
    @param instance_name: instance in question
1096 b693125f Tsachy Shacham
    @rtype: dictionary of int:int
1097 b693125f Tsachy Shacham
    @return: a dictionary mapping vCPU numbers to thread IDs
1098 b693125f Tsachy Shacham

1099 b693125f Tsachy Shacham
    """
1100 b693125f Tsachy Shacham
    result = {}
1101 b693125f Tsachy Shacham
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
1102 b693125f Tsachy Shacham
    for line in output.stdout.splitlines():
1103 b693125f Tsachy Shacham
      match = self._CPU_INFO_RE.search(line)
1104 b693125f Tsachy Shacham
      if not match:
1105 b693125f Tsachy Shacham
        continue
1106 b693125f Tsachy Shacham
      grp = map(int, match.groups())
1107 b693125f Tsachy Shacham
      result[grp[0]] = grp[1]
1108 b693125f Tsachy Shacham
1109 b693125f Tsachy Shacham
    return result
1110 b693125f Tsachy Shacham
1111 1d8a7812 Andrea Spadaccini
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
1112 1d8a7812 Andrea Spadaccini
    """Complete CPU pinning.
1113 b693125f Tsachy Shacham

1114 b693125f Tsachy Shacham
    @type instance_name: string
1115 b693125f Tsachy Shacham
    @param instance_name: name of instance
1116 b693125f Tsachy Shacham
    @type cpu_mask: string
1117 b693125f Tsachy Shacham
    @param cpu_mask: CPU pinning mask as entered by user
1118 b693125f Tsachy Shacham

1119 b693125f Tsachy Shacham
    """
1120 1d8a7812 Andrea Spadaccini
    # Get KVM process ID, to be used if need to pin entire VM
1121 1d8a7812 Andrea Spadaccini
    _, pid, _ = self._InstancePidAlive(instance_name)
1122 1d8a7812 Andrea Spadaccini
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
1123 1d8a7812 Andrea Spadaccini
    thread_dict = self._GetVcpuThreadIds(instance_name)
1124 1d8a7812 Andrea Spadaccini
    # Run CPU pinning, based on configured mask
1125 1d8a7812 Andrea Spadaccini
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
1126 b693125f Tsachy Shacham
1127 eb58f9b1 Guido Trotter
  def ListInstances(self):
1128 eb58f9b1 Guido Trotter
    """Get the list of running instances.
1129 eb58f9b1 Guido Trotter

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

1133 eb58f9b1 Guido Trotter
    """
1134 eb58f9b1 Guido Trotter
    result = []
1135 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1136 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
1137 eb58f9b1 Guido Trotter
        result.append(name)
1138 eb58f9b1 Guido Trotter
    return result
1139 eb58f9b1 Guido Trotter
1140 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
1141 eb58f9b1 Guido Trotter
    """Get instance properties.
1142 eb58f9b1 Guido Trotter

1143 4fbb3c60 Guido Trotter
    @type instance_name: string
1144 c41eea6e Iustin Pop
    @param instance_name: the instance name
1145 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
1146 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
1147 eb58f9b1 Guido Trotter

1148 eb58f9b1 Guido Trotter
    """
1149 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
1150 1f8b3a27 Guido Trotter
    if not alive:
1151 eb58f9b1 Guido Trotter
      return None
1152 eb58f9b1 Guido Trotter
1153 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
1154 fc84cd5d Guido Trotter
    istat = "---b-"
1155 eb58f9b1 Guido Trotter
    times = "0"
1156 eb58f9b1 Guido Trotter
1157 89da2ff3 Guido Trotter
    try:
1158 89da2ff3 Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
1159 89da2ff3 Guido Trotter
      qmp.connect()
1160 89da2ff3 Guido Trotter
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
1161 89da2ff3 Guido Trotter
      # Will fail if ballooning is not enabled, but we can then just resort to
1162 89da2ff3 Guido Trotter
      # the value above.
1163 89da2ff3 Guido Trotter
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
1164 89da2ff3 Guido Trotter
      memory = mem_bytes / 1048576
1165 89da2ff3 Guido Trotter
    except errors.HypervisorError:
1166 89da2ff3 Guido Trotter
      pass
1167 89da2ff3 Guido Trotter
1168 fc84cd5d Guido Trotter
    return (instance_name, pid, memory, vcpus, istat, times)
1169 eb58f9b1 Guido Trotter
1170 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
1171 eb58f9b1 Guido Trotter
    """Get properties of all instances.
1172 eb58f9b1 Guido Trotter

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

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

1259 b73f1c59 Guido Trotter
    @type kvmhelp: string
1260 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1261 839642c2 Iustin Pop
    @attention: this function must not have any side-effects; for
1262 839642c2 Iustin Pop
        example, it must not write to the filesystem, or read values
1263 839642c2 Iustin Pop
        from the current system the are expected to differ between
1264 839642c2 Iustin Pop
        nodes, since it is only run once at instance startup;
1265 839642c2 Iustin Pop
        actions/kvm arguments that can vary between systems should be
1266 839642c2 Iustin Pop
        done in L{_ExecuteKVMRuntime}
1267 839642c2 Iustin Pop

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

1609 38e250ba Guido Trotter
    """
1610 38e250ba Guido Trotter
    try:
1611 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1612 38e250ba Guido Trotter
                      data=data)
1613 90c024f6 Guido Trotter
    except EnvironmentError, err:
1614 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1615 38e250ba Guido Trotter
1616 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
1617 38e250ba Guido Trotter
    """Read an instance's KVM runtime
1618 38e250ba Guido Trotter

1619 38e250ba Guido Trotter
    """
1620 38e250ba Guido Trotter
    try:
1621 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1622 90c024f6 Guido Trotter
    except EnvironmentError, err:
1623 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1624 38e250ba Guido Trotter
    return file_content
1625 38e250ba Guido Trotter
1626 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1627 38e250ba Guido Trotter
    """Save an instance's KVM runtime
1628 38e250ba Guido Trotter

1629 38e250ba Guido Trotter
    """
1630 58502c9e Dimitris Aragiorgis
    kvm_cmd, kvm_nics, hvparams, block_devices = kvm_runtime
1631 58502c9e Dimitris Aragiorgis
1632 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1633 277a9de7 Dimitris Aragiorgis
    serialized_blockdevs = [(blk.ToDict(), link)
1634 277a9de7 Dimitris Aragiorgis
                            for blk, link in block_devices]
1635 58502c9e Dimitris Aragiorgis
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams,
1636 58502c9e Dimitris Aragiorgis
                                      serialized_blockdevs))
1637 58502c9e Dimitris Aragiorgis
1638 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
1639 38e250ba Guido Trotter
1640 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1641 38e250ba Guido Trotter
    """Load an instance's KVM runtime
1642 38e250ba Guido Trotter

1643 38e250ba Guido Trotter
    """
1644 30e42c4e Guido Trotter
    if not serialized_runtime:
1645 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1646 58502c9e Dimitris Aragiorgis
1647 58502c9e Dimitris Aragiorgis
    return _AnalyzeSerializedRuntime(serialized_runtime)
1648 38e250ba Guido Trotter
1649 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1650 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
1651 76431533 Guido Trotter

1652 76431533 Guido Trotter
    @type name: string
1653 76431533 Guido Trotter
    @param name: instance name
1654 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1655 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1656 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1657 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1658 76431533 Guido Trotter

1659 76431533 Guido Trotter
    """
1660 5d9bfd87 Apollon Oikonomopoulos
    try:
1661 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1662 5d9bfd87 Apollon Oikonomopoulos
    finally:
1663 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
1664 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
1665 5d9bfd87 Apollon Oikonomopoulos
1666 76431533 Guido Trotter
    if result.failed:
1667 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1668 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
1669 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
1670 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
1671 76431533 Guido Trotter
1672 58502c9e Dimitris Aragiorgis
  # 52/50 local variables
1673 58502c9e Dimitris Aragiorgis
  # pylint: disable=R0914
1674 b73f1c59 Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1675 839642c2 Iustin Pop
    """Execute a KVM cmd, after completing it with some last minute data.
1676 ee5f20b0 Guido Trotter

1677 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1678 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1679 b73f1c59 Guido Trotter
    @type kvmhelp: string
1680 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1681 30e42c4e Guido Trotter

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

1899 ee5f20b0 Guido Trotter
    """
1900 5905901c Iustin Pop
    self._CheckDown(instance.name)
1901 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1902 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1903 7238edb5 Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1904 b73f1c59 Guido Trotter
                                           startup_paused, kvmhelp)
1905 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1906 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1907 ee5f20b0 Guido Trotter
1908 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
1909 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
1910 6567aff3 Guido Trotter

1911 6567aff3 Guido Trotter
    """
1912 eace6157 Michael Hanselmann
    # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
1913 eace6157 Michael Hanselmann
    # version. The monitor protocol is designed for human consumption, whereas
1914 eace6157 Michael Hanselmann
    # QMP is made for programmatic usage. In the worst case QMP can also
1915 eace6157 Michael Hanselmann
    # execute monitor commands. As it is, all calls to socat take at least
1916 eace6157 Michael Hanselmann
    # 500ms and likely more: socat can't detect the end of the reply and waits
1917 eace6157 Michael Hanselmann
    # for 500ms of no data received before exiting (500 ms is the default for
1918 eace6157 Michael Hanselmann
    # the "-t" parameter).
1919 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1920 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
1921 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
1922 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1923 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
1924 6567aff3 Guido Trotter
    if result.failed:
1925 afa9bb2e Michael Hanselmann
      msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
1926 afa9bb2e Michael Hanselmann
             " output: %s" %
1927 afa9bb2e Michael Hanselmann
             (command, instance_name, result.fail_reason, result.output))
1928 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
1929 6567aff3 Guido Trotter
1930 6567aff3 Guido Trotter
    return result
1931 6567aff3 Guido Trotter
1932 8b7be6f2 Dimitris Aragiorgis
  def _GetFreePCISlot(self, instance, dev):
1933 8b7be6f2 Dimitris Aragiorgis
    """Get the first available pci slot of a runnung instance.
1934 8b7be6f2 Dimitris Aragiorgis

1935 8b7be6f2 Dimitris Aragiorgis
    """
1936 8b7be6f2 Dimitris Aragiorgis
    slots = bitarray(32)
1937 8b7be6f2 Dimitris Aragiorgis
    slots.setall(False) # pylint: disable=E1101
1938 8b7be6f2 Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance.name, self._INFO_PCI_CMD)
1939 8b7be6f2 Dimitris Aragiorgis
    for line in output.stdout.splitlines():
1940 8b7be6f2 Dimitris Aragiorgis
      match = self._INFO_PCI_RE.search(line)
1941 8b7be6f2 Dimitris Aragiorgis
      if match:
1942 8b7be6f2 Dimitris Aragiorgis
        slot = int(match.group(1))
1943 8b7be6f2 Dimitris Aragiorgis
        slots[slot] = True
1944 8b7be6f2 Dimitris Aragiorgis
1945 8b7be6f2 Dimitris Aragiorgis
    [free] = slots.search(_AVAILABLE_PCI_SLOT, 1) # pylint: disable=E1101
1946 8b7be6f2 Dimitris Aragiorgis
    if not free:
1947 8b7be6f2 Dimitris Aragiorgis
      raise errors.HypervisorError("All PCI slots occupied")
1948 8b7be6f2 Dimitris Aragiorgis
1949 8b7be6f2 Dimitris Aragiorgis
    dev.pci = int(free)
1950 8b7be6f2 Dimitris Aragiorgis
1951 d7583563 Dimitris Aragiorgis
  def HotplugSupported(self, instance, action, dev_type):
1952 d7583563 Dimitris Aragiorgis
    """Check if hotplug is supported.
1953 d7583563 Dimitris Aragiorgis

1954 d7583563 Dimitris Aragiorgis
    Hotplug is *not* supported in case of:
1955 d7583563 Dimitris Aragiorgis
     - qemu versions < 1.0
1956 d7583563 Dimitris Aragiorgis
     - security models and chroot (disk hotplug)
1957 d7583563 Dimitris Aragiorgis
     - fdsend module is missing (nic hot-add)
1958 d7583563 Dimitris Aragiorgis

1959 d7583563 Dimitris Aragiorgis
    @raise errors.HypervisorError: in previous cases
1960 d7583563 Dimitris Aragiorgis

1961 d7583563 Dimitris Aragiorgis
    """
1962 d7583563 Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD)
1963 d7583563 Dimitris Aragiorgis
    # TODO: search for netdev_add, drive_add, device_add.....
1964 d7583563 Dimitris Aragiorgis
    match = self._INFO_VERSION_RE.search(output.stdout)
1965 d7583563 Dimitris Aragiorgis
    if not match:
1966 d7583563 Dimitris Aragiorgis
      raise errors.HotplugError("Try hotplug only in running instances.")
1967 d7583563 Dimitris Aragiorgis
    v_major, v_min, _, _ = match.groups()
1968 d7583563 Dimitris Aragiorgis
    if (v_major, v_min) < (1, 0):
1969 d7583563 Dimitris Aragiorgis
      raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0")
1970 d7583563 Dimitris Aragiorgis
1971 d7583563 Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
1972 d7583563 Dimitris Aragiorgis
      hvp = instance.hvparams
1973 d7583563 Dimitris Aragiorgis
      security_model = hvp[constants.HV_SECURITY_MODEL]
1974 d7583563 Dimitris Aragiorgis
      use_chroot = hvp[constants.HV_KVM_USE_CHROOT]
1975 d7583563 Dimitris Aragiorgis
      if use_chroot:
1976 d7583563 Dimitris Aragiorgis
        raise errors.HotplugError("Disk hotplug is not supported"
1977 d7583563 Dimitris Aragiorgis
                                  " in case of chroot.")
1978 d7583563 Dimitris Aragiorgis
      if security_model != constants.HT_SM_NONE:
1979 d7583563 Dimitris Aragiorgis
        raise errors.HotplugError("Disk Hotplug is not supported in case"
1980 d7583563 Dimitris Aragiorgis
                                  " security models are used.")
1981 d7583563 Dimitris Aragiorgis
1982 d7583563 Dimitris Aragiorgis
    if (dev_type == constants.HOTPLUG_TARGET_NIC and
1983 d7583563 Dimitris Aragiorgis
        action == constants.HOTPLUG_ACTION_ADD and not fdsend):
1984 d7583563 Dimitris Aragiorgis
      raise errors.HotplugError("Cannot hot-add NIC."
1985 d7583563 Dimitris Aragiorgis
                                " fdsend python module is missing.")
1986 d7583563 Dimitris Aragiorgis
    return True
1987 d7583563 Dimitris Aragiorgis
1988 d7583563 Dimitris Aragiorgis
  def _CallHotplugCommand(self, name, cmd):
1989 d7583563 Dimitris Aragiorgis
    output = self._CallMonitorCommand(name, cmd)
1990 d7583563 Dimitris Aragiorgis
    # TODO: parse output and check if succeeded
1991 d7583563 Dimitris Aragiorgis
    for line in output.stdout.splitlines():
1992 d7583563 Dimitris Aragiorgis
      logging.info("%s", line)
1993 d7583563 Dimitris Aragiorgis
1994 b52d85c1 Guido Trotter
  @classmethod
1995 585c8187 Guido Trotter
  def _ParseKVMVersion(cls, text):
1996 585c8187 Guido Trotter
    """Parse the KVM version from the --help output.
1997 585c8187 Guido Trotter

1998 585c8187 Guido Trotter
    @type text: string
1999 585c8187 Guido Trotter
    @param text: output of kvm --help
2000 585c8187 Guido Trotter
    @return: (version, v_maj, v_min, v_rev)
2001 5c3d5dfd Iustin Pop
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
2002 585c8187 Guido Trotter

2003 585c8187 Guido Trotter
    """
2004 585c8187 Guido Trotter
    match = cls._VERSION_RE.search(text.splitlines()[0])
2005 585c8187 Guido Trotter
    if not match:
2006 585c8187 Guido Trotter
      raise errors.HypervisorError("Unable to get KVM version")
2007 585c8187 Guido Trotter
2008 585c8187 Guido Trotter
    v_all = match.group(0)
2009 585c8187 Guido Trotter
    v_maj = int(match.group(1))
2010 585c8187 Guido Trotter
    v_min = int(match.group(2))
2011 585c8187 Guido Trotter
    if match.group(4):
2012 585c8187 Guido Trotter
      v_rev = int(match.group(4))
2013 585c8187 Guido Trotter
    else:
2014 585c8187 Guido Trotter
      v_rev = 0
2015 585c8187 Guido Trotter
    return (v_all, v_maj, v_min, v_rev)
2016 585c8187 Guido Trotter
2017 585c8187 Guido Trotter
  @classmethod
2018 6e043e60 Guido Trotter
  def _GetKVMOutput(cls, kvm_path, option):
2019 6e043e60 Guido Trotter
    """Return the output of a kvm invocation
2020 e3b89628 Guido Trotter

2021 bc0fed4b Guido Trotter
    @type kvm_path: string
2022 bc0fed4b Guido Trotter
    @param kvm_path: path to the kvm executable
2023 bc0fed4b Guido Trotter
    @type option: a key of _KVMOPTS_CMDS
2024 bc0fed4b Guido Trotter
    @param option: kvm option to fetch the output from
2025 6e043e60 Guido Trotter
    @return: output a supported kvm invocation
2026 e3b89628 Guido Trotter
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
2027 e3b89628 Guido Trotter

2028 e3b89628 Guido Trotter
    """
2029 6e043e60 Guido Trotter
    assert option in cls._KVMOPTS_CMDS, "Invalid output option"
2030 6e043e60 Guido Trotter
2031 bc0fed4b Guido Trotter
    optlist, can_fail = cls._KVMOPTS_CMDS[option]
2032 bc0fed4b Guido Trotter
2033 bc0fed4b Guido Trotter
    result = utils.RunCmd([kvm_path] + optlist)
2034 bc0fed4b Guido Trotter
    if result.failed and not can_fail:
2035 af89fa76 Helga Velroyen
      raise errors.HypervisorError("Unable to get KVM %s output" %
2036 3ddc7650 Jose A. Lopes
                                    " ".join(optlist))
2037 e3b89628 Guido Trotter
    return result.output
2038 e3b89628 Guido Trotter
2039 e3b89628 Guido Trotter
  @classmethod
2040 3b59ec02 Guido Trotter
  def _GetKVMVersion(cls, kvm_path):
2041 d7e4a2b1 Andrea Spadaccini
    """Return the installed KVM version.
2042 b52d85c1 Guido Trotter

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

2046 b52d85c1 Guido Trotter
    """
2047 6e043e60 Guido Trotter
    return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
2048 82e3bf85 Dimitris Aragiorgis
2049 82e3bf85 Dimitris Aragiorgis
  @classmethod
2050 82e3bf85 Dimitris Aragiorgis
  def _GetDefaultMachineVersion(cls, kvm_path):
2051 82e3bf85 Dimitris Aragiorgis
    """Return the default hardware revision (e.g. pc-1.1)
2052 82e3bf85 Dimitris Aragiorgis

2053 82e3bf85 Dimitris Aragiorgis
    """
2054 6e043e60 Guido Trotter
    output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2055 82e3bf85 Dimitris Aragiorgis
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
2056 82e3bf85 Dimitris Aragiorgis
    if match:
2057 82e3bf85 Dimitris Aragiorgis
      return match.group(1)
2058 82e3bf85 Dimitris Aragiorgis
    else:
2059 82e3bf85 Dimitris Aragiorgis
      return "pc"
2060 82e3bf85 Dimitris Aragiorgis
2061 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
2062 eb58f9b1 Guido Trotter
    """Stop an instance.
2063 eb58f9b1 Guido Trotter

2064 eb58f9b1 Guido Trotter
    """
2065 bbcf7ad0 Iustin Pop
    if name is not None and not force:
2066 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
2067 bbcf7ad0 Iustin Pop
    if name is None:
2068 bbcf7ad0 Iustin Pop
      name = instance.name
2069 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
2070 bbcf7ad0 Iustin Pop
    else:
2071 bbcf7ad0 Iustin Pop
      acpi = False
2072 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
2073 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
2074 bbcf7ad0 Iustin Pop
      if force or not acpi:
2075 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
2076 eb58f9b1 Guido Trotter
      else:
2077 d0c8c01d Iustin Pop
        self._CallMonitorCommand(name, "system_powerdown")
2078 eb58f9b1 Guido Trotter
2079 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
2080 8904b35c Guido Trotter
    """Cleanup after a stopped instance
2081 8904b35c Guido Trotter

2082 8904b35c Guido Trotter
    """
2083 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
2084 8904b35c Guido Trotter
    if pid > 0 and alive:
2085 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
2086 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
2087 eb58f9b1 Guido Trotter
2088 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
2089 eb58f9b1 Guido Trotter
    """Reboot an instance.
2090 eb58f9b1 Guido Trotter

2091 eb58f9b1 Guido Trotter
    """
2092 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
2093 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
2094 eb58f9b1 Guido Trotter
    # to shutdown and restart.
2095 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
2096 1f8b3a27 Guido Trotter
    if not alive:
2097 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
2098 78411c60 Iustin Pop
                                   " not running" % instance.name)
2099 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
2100 f02881e0 Guido Trotter
    # ...first load it...
2101 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
2102 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
2103 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
2104 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
2105 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
2106 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
2107 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2108 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2109 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
2110 eb58f9b1 Guido Trotter
2111 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
2112 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
2113 30e42c4e Guido Trotter

2114 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2115 30e42c4e Guido Trotter
    @param instance: instance to be migrated
2116 30e42c4e Guido Trotter
    @rtype: string
2117 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
2118 30e42c4e Guido Trotter

2119 30e42c4e Guido Trotter
    """
2120 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
2121 30e42c4e Guido Trotter
2122 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
2123 30e42c4e Guido Trotter
    """Prepare to accept an instance.
2124 30e42c4e Guido Trotter

2125 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2126 30e42c4e Guido Trotter
    @param instance: instance to be accepted
2127 30e42c4e Guido Trotter
    @type info: string
2128 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
2129 30e42c4e Guido Trotter
    @type target: string
2130 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
2131 30e42c4e Guido Trotter

2132 30e42c4e Guido Trotter
    """
2133 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2134 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
2135 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2136 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2137 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
2138 b73f1c59 Guido Trotter
                            incoming=incoming_address)
2139 30e42c4e Guido Trotter
2140 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
2141 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
2142 30e42c4e Guido Trotter

2143 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
2144 30e42c4e Guido Trotter

2145 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2146 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
2147 30e42c4e Guido Trotter

2148 30e42c4e Guido Trotter
    """
2149 30e42c4e Guido Trotter
    if success:
2150 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2151 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
2152 5d9bfd87 Apollon Oikonomopoulos
2153 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
2154 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
2155 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
2156 cc8a8ed7 Apollon Oikonomopoulos
          continue
2157 5d9bfd87 Apollon Oikonomopoulos
        try:
2158 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
2159 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
2160 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
2161 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
2162 5d9bfd87 Apollon Oikonomopoulos
          continue
2163 5d9bfd87 Apollon Oikonomopoulos
        try:
2164 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
2165 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
2166 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
2167 5d9bfd87 Apollon Oikonomopoulos
2168 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
2169 30e42c4e Guido Trotter
    else:
2170 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
2171 30e42c4e Guido Trotter
2172 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
2173 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
2174 30e42c4e Guido Trotter

2175 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
2176 30e42c4e Guido Trotter
    currently running.
2177 30e42c4e Guido Trotter

2178 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
2179 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
2180 30e42c4e Guido Trotter
    @type target: string
2181 30e42c4e Guido Trotter
    @param target: ip address of the target node
2182 30e42c4e Guido Trotter
    @type live: boolean
2183 30e42c4e Guido Trotter
    @param live: perform a live migration
2184 30e42c4e Guido Trotter

2185 30e42c4e Guido Trotter
    """
2186 58d38b02 Iustin Pop
    instance_name = instance.name
2187 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
2188 6a1434d7 Andrea Spadaccini
    _, _, alive = self._InstancePidAlive(instance_name)
2189 30e42c4e Guido Trotter
    if not alive:
2190 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
2191 30e42c4e Guido Trotter
2192 30e42c4e Guido Trotter
    if not live:
2193 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
2194 30e42c4e Guido Trotter
2195 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
2196 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
2197 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2198 e43d4f9f Apollon Oikonomopoulos
2199 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
2200 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
2201 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2202 e43d4f9f Apollon Oikonomopoulos
2203 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
2204 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
2205 30e42c4e Guido Trotter
2206 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
2207 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
2208 6a1434d7 Andrea Spadaccini

2209 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2210 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
2211 6a1434d7 Andrea Spadaccini
    @type success: bool
2212 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
2213 6a1434d7 Andrea Spadaccini
    @type live: bool
2214 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
2215 6a1434d7 Andrea Spadaccini

2216 6a1434d7 Andrea Spadaccini
    """
2217 6a1434d7 Andrea Spadaccini
    if success:
2218 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
2219 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
2220 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
2221 6a1434d7 Andrea Spadaccini
    elif live:
2222 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
2223 6a1434d7 Andrea Spadaccini
2224 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
2225 6a1434d7 Andrea Spadaccini
    """Get the migration status
2226 6a1434d7 Andrea Spadaccini

2227 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2228 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
2229 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
2230 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
2231 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
2232 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
2233 6a1434d7 Andrea Spadaccini

2234 6a1434d7 Andrea Spadaccini
    """
2235 d0c8c01d Iustin Pop
    info_command = "info migrate"
2236 6a1434d7 Andrea Spadaccini
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
2237 6a1434d7 Andrea Spadaccini
      result = self._CallMonitorCommand(instance.name, info_command)
2238 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
2239 30e42c4e Guido Trotter
      if not match:
2240 c4e388a5 Guido Trotter
        if not result.stdout:
2241 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
2242 c4e388a5 Guido Trotter
        else:
2243 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
2244 c4e388a5 Guido Trotter
                          result.stdout)
2245 30e42c4e Guido Trotter
      else:
2246 30e42c4e Guido Trotter
        status = match.group(1)
2247 6a1434d7 Andrea Spadaccini
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
2248 6a1434d7 Andrea Spadaccini
          migration_status = objects.MigrationStatus(status=status)
2249 61643226 Andrea Spadaccini
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
2250 61643226 Andrea Spadaccini
          if match:
2251 61643226 Andrea Spadaccini
            migration_status.transferred_ram = match.group("transferred")
2252 61643226 Andrea Spadaccini
            migration_status.total_ram = match.group("total")
2253 61643226 Andrea Spadaccini
2254 6a1434d7 Andrea Spadaccini
          return migration_status
2255 30e42c4e Guido Trotter
2256 6a1434d7 Andrea Spadaccini
        logging.warning("KVM: unknown migration status '%s'", status)
2257 6a1434d7 Andrea Spadaccini
2258 6a1434d7 Andrea Spadaccini
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
2259 6a1434d7 Andrea Spadaccini
2260 62457f51 Iustin Pop
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
2261 30e42c4e Guido Trotter
2262 3d836750 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
2263 3d836750 Guido Trotter
    """Balloon an instance memory to a certain value.
2264 3d836750 Guido Trotter

2265 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
2266 3d836750 Guido Trotter
    @param instance: instance to be accepted
2267 3d836750 Guido Trotter
    @type mem: int
2268 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
2269 3d836750 Guido Trotter

2270 3d836750 Guido Trotter
    """
2271 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2272 3d836750 Guido Trotter
2273 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
2274 eb58f9b1 Guido Trotter
    """Return information about the node.
2275 eb58f9b1 Guido Trotter

2276 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
2277 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
2278 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
2279 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
2280 34fbc862 Andrea Spadaccini
          - hv_version: the hypervisor version in the form (major, minor,
2281 34fbc862 Andrea Spadaccini
                        revision)
2282 eb58f9b1 Guido Trotter

2283 eb58f9b1 Guido Trotter
    """
2284 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
2285 4b9638dc Guido Trotter
    # FIXME: this is the global kvm version, but the actual version can be
2286 4b9638dc Guido Trotter
    # customized as an hv parameter. we should use the nodegroup's default kvm
2287 4b9638dc Guido Trotter
    # path parameter here.
2288 3b59ec02 Guido Trotter
    _, v_major, v_min, v_rev = self._GetKVMVersion(constants.KVM_PATH)
2289 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2290 34fbc862 Andrea Spadaccini
    return result
2291 eb58f9b1 Guido Trotter
2292 637ce7f9 Guido Trotter
  @classmethod
2293 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
2294 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
2295 eb58f9b1 Guido Trotter

2296 eb58f9b1 Guido Trotter
    """
2297 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2298 9d9bded1 Michael Hanselmann
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2299 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2300 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2301 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
2302 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2303 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2304 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
2305 55cc0a44 Michael Hanselmann
                                     host=instance.primary_node,
2306 052783ff Michael Hanselmann
                                     user=constants.SSH_CONSOLE_USER,
2307 55cc0a44 Michael Hanselmann
                                     command=cmd)
2308 3be34f57 Guido Trotter
2309 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2310 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2311 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
2312 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2313 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
2314 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
2315 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
2316 55cc0a44 Michael Hanselmann
                                     display=display)
2317 55cc0a44 Michael Hanselmann
2318 4d2cdb5a Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2319 4d2cdb5a Andrea Spadaccini
    if spice_bind:
2320 4d2cdb5a Andrea Spadaccini
      return objects.InstanceConsole(instance=instance.name,
2321 4d2cdb5a Andrea Spadaccini
                                     kind=constants.CONS_SPICE,
2322 4d2cdb5a Andrea Spadaccini
                                     host=spice_bind,
2323 4d2cdb5a Andrea Spadaccini
                                     port=instance.network_port)
2324 4d2cdb5a Andrea Spadaccini
2325 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
2326 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
2327 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
2328 55cc0a44 Michael Hanselmann
                                            instance.name))
2329 eb58f9b1 Guido Trotter
2330 eb58f9b1 Guido Trotter
  def Verify(self):
2331 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
2332 eb58f9b1 Guido Trotter

2333 cd04dfd2 Michael Hanselmann
    Check that the required binaries exist.
2334 cd04dfd2 Michael Hanselmann

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

2337 eb58f9b1 Guido Trotter
    """
2338 1f4b9d39 Iustin Pop
    msgs = []
2339 1f4b9d39 Iustin Pop
    # FIXME: this is the global kvm binary, but the actual path can be
2340 1f4b9d39 Iustin Pop
    # customized as an hv parameter; we should use the nodegroup's
2341 1f4b9d39 Iustin Pop
    # default kvm path parameter here.
2342 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
2343 1f4b9d39 Iustin Pop
      msgs.append("The KVM binary ('%s') does not exist" % constants.KVM_PATH)
2344 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2345 1f4b9d39 Iustin Pop
      msgs.append("The socat binary ('%s') does not exist" %
2346 1f4b9d39 Iustin Pop
                  constants.SOCAT_PATH)
2347 1f4b9d39 Iustin Pop
2348 1f4b9d39 Iustin Pop
    return self._FormatVerifyResults(msgs)
2349 14aa53cb Guido Trotter
2350 6b5605e8 Iustin Pop
  @classmethod
2351 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2352 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2353 6b5605e8 Iustin Pop

2354 6b5605e8 Iustin Pop
    @type hvparams:  dict
2355 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2356 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2357 6b5605e8 Iustin Pop

2358 6b5605e8 Iustin Pop
    """
2359 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2360 6b5605e8 Iustin Pop
2361 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
2362 df5ab9f0 Guido Trotter
    if kernel_path:
2363 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
2364 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
2365 205ab586 Iustin Pop
                                     " if a kernel is defined")
2366 6b5605e8 Iustin Pop
2367 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
2368 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
2369 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
2370 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
2371 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
2372 66d5dbef Guido Trotter
2373 14fd6c81 Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2374 14fd6c81 Guido Trotter
      serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2375 14fd6c81 Guido Trotter
      valid_speeds = constants.VALID_SERIAL_SPEEDS
2376 14fd6c81 Guido Trotter
      if not serial_speed or serial_speed not in valid_speeds:
2377 14fd6c81 Guido Trotter
        raise errors.HypervisorError("Invalid serial console speed, must be"
2378 14fd6c81 Guido Trotter
                                     " one of: %s" %
2379 14fd6c81 Guido Trotter
                                     utils.CommaJoin(valid_speeds))
2380 14fd6c81 Guido Trotter
2381 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2382 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
2383 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2384 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2385 835528af Iustin Pop
                                   " ISO path")
2386 f5118ade Iustin Pop
2387 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2388 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2389 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
2390 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
2391 d19d94db Guido Trotter
                                     " must be specified")
2392 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
2393 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
2394 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
2395 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
2396 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
2397 d19d94db Guido Trotter
2398 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2399 b451c4c7 Andrea Spadaccini
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2400 b1cb62bd Andrea Spadaccini
    if spice_bind:
2401 b1cb62bd Andrea Spadaccini
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2402 b1cb62bd Andrea Spadaccini
        # if an IP version is specified, the spice_bind parameter must be an
2403 b1cb62bd Andrea Spadaccini
        # IP of that family
2404 b1cb62bd Andrea Spadaccini
        if (netutils.IP4Address.IsValid(spice_bind) and
2405 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP4_VERSION):
2406 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv4 address (%s), but"
2407 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2408 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2409 b1cb62bd Andrea Spadaccini
2410 b1cb62bd Andrea Spadaccini
        if (netutils.IP6Address.IsValid(spice_bind) and
2411 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP6_VERSION):
2412 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv6 address (%s), but"
2413 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2414 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2415 b451c4c7 Andrea Spadaccini
    else:
2416 0e1b03b9 Andrea Spadaccini
      # All the other SPICE parameters depend on spice_bind being set. Raise an
2417 0e1b03b9 Andrea Spadaccini
      # error if any of them is set without it.
2418 07788a0b Michael Hanselmann
      for param in _SPICE_ADDITIONAL_PARAMS:
2419 0e1b03b9 Andrea Spadaccini
        if hvparams[param]:
2420 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: %s requires %s to be set" %
2421 0e1b03b9 Andrea Spadaccini
                                       (param, constants.HV_KVM_SPICE_BIND))
2422 b1cb62bd Andrea Spadaccini
2423 d19d94db Guido Trotter
  @classmethod
2424 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
2425 d19d94db Guido Trotter
    """Check the given parameters for validity.
2426 d19d94db Guido Trotter

2427 d19d94db Guido Trotter
    @type hvparams:  dict
2428 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2429 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2430 d19d94db Guido Trotter

2431 d19d94db Guido Trotter
    """
2432 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2433 d19d94db Guido Trotter
2434 82e3bf85 Dimitris Aragiorgis
    kvm_path = hvparams[constants.HV_KVM_PATH]
2435 82e3bf85 Dimitris Aragiorgis
2436 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2437 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2438 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2439 d19d94db Guido Trotter
      try:
2440 1feb39ec Guido Trotter
        pwd.getpwnam(username)
2441 d19d94db Guido Trotter
      except KeyError:
2442 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
2443 d19d94db Guido Trotter
                                     % username)
2444 d19d94db Guido Trotter
2445 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2446 b1cb62bd Andrea Spadaccini
    if spice_bind:
2447 b1cb62bd Andrea Spadaccini
      # only one of VNC and SPICE can be used currently.
2448 b1cb62bd Andrea Spadaccini
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2449 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("Both SPICE and VNC are configured, but"
2450 b1cb62bd Andrea Spadaccini
                                     " only one of them can be used at a"
2451 afa9bb2e Michael Hanselmann
                                     " given time")
2452 b1cb62bd Andrea Spadaccini
2453 3b59ec02 Guido Trotter
      # check that KVM supports SPICE
2454 6e043e60 Guido Trotter
      kvmhelp = cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP)
2455 0ad7f5d8 Guido Trotter
      if not cls._SPICE_RE.search(kvmhelp):
2456 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE is configured, but it is not"
2457 afa9bb2e Michael Hanselmann
                                     " supported according to 'kvm --help'")
2458 b1cb62bd Andrea Spadaccini
2459 b1cb62bd Andrea Spadaccini
      # if spice_bind is not an IP address, it must be a valid interface
2460 afa9bb2e Michael Hanselmann
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind) or
2461 afa9bb2e Michael Hanselmann
                       netutils.IP6Address.IsValid(spice_bind))
2462 b1cb62bd Andrea Spadaccini
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2463 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE: The %s parameter must be either"
2464 b1cb62bd Andrea Spadaccini
                                     " a valid IP address or interface name" %
2465 b1cb62bd Andrea Spadaccini
                                     constants.HV_KVM_SPICE_BIND)
2466 b1cb62bd Andrea Spadaccini
2467 82e3bf85 Dimitris Aragiorgis
    machine_version = hvparams[constants.HV_KVM_MACHINE_VERSION]
2468 82e3bf85 Dimitris Aragiorgis
    if machine_version:
2469 6e043e60 Guido Trotter
      output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2470 82e3bf85 Dimitris Aragiorgis
      if not cls._CHECK_MACHINE_VERSION_RE(machine_version).search(output):
2471 82e3bf85 Dimitris Aragiorgis
        raise errors.HypervisorError("Unsupported machine version: %s" %
2472 82e3bf85 Dimitris Aragiorgis
                                     machine_version)
2473 82e3bf85 Dimitris Aragiorgis
2474 f5118ade Iustin Pop
  @classmethod
2475 f5118ade Iustin Pop
  def PowercycleNode(cls):
2476 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
2477 f5118ade Iustin Pop

2478 f5118ade Iustin Pop
    """
2479 f5118ade Iustin Pop
    cls.LinuxPowercycle()