Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ e7a77eb8

History | View | Annotate | Download (94.1 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 4a44d8aa Dimitris Aragiorgis
# moreover disk entries are stored as a list of in tuples
94 4a44d8aa Dimitris Aragiorgis
# (L{objects.Disk}, link_name)
95 58502c9e Dimitris Aragiorgis
_KVM_NICS_RUNTIME_INDEX = 1
96 58502c9e Dimitris Aragiorgis
_KVM_DISKS_RUNTIME_INDEX = 3
97 58502c9e Dimitris Aragiorgis
_DEVICE_RUNTIME_INDEX = {
98 58502c9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK: _KVM_DISKS_RUNTIME_INDEX,
99 58502c9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC: _KVM_NICS_RUNTIME_INDEX
100 58502c9e Dimitris Aragiorgis
  }
101 58502c9e Dimitris Aragiorgis
_FIND_RUNTIME_ENTRY = {
102 58502c9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC:
103 58502c9e Dimitris Aragiorgis
    lambda nic, kvm_nics: [n for n in kvm_nics if n.uuid == nic.uuid],
104 58502c9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK:
105 277a9de7 Dimitris Aragiorgis
    lambda disk, kvm_disks: [(d, l) for (d, l) in kvm_disks
106 58502c9e Dimitris Aragiorgis
                             if d.uuid == disk.uuid]
107 58502c9e Dimitris Aragiorgis
  }
108 58502c9e Dimitris Aragiorgis
_RUNTIME_DEVICE = {
109 58502c9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC: lambda d: d,
110 277a9de7 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK: lambda (d, e): d
111 58502c9e Dimitris Aragiorgis
  }
112 58502c9e Dimitris Aragiorgis
_RUNTIME_ENTRY = {
113 58502c9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC: lambda d, e: d,
114 277a9de7 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK: lambda d, e: (d, e)
115 58502c9e Dimitris Aragiorgis
  }
116 58502c9e Dimitris Aragiorgis
117 58502c9e Dimitris Aragiorgis
118 8b7be6f2 Dimitris Aragiorgis
def _GenerateDeviceKVMId(dev_type, dev):
119 8b7be6f2 Dimitris Aragiorgis
  """Helper function to generate a unique device name used by KVM
120 8b7be6f2 Dimitris Aragiorgis

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1176 eb58f9b1 Guido Trotter
    """
1177 eb58f9b1 Guido Trotter
    data = []
1178 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1179 263b8de6 Guido Trotter
      try:
1180 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
1181 263b8de6 Guido Trotter
      except errors.HypervisorError:
1182 3bc145d8 Bernardo Dal Seno
        # Ignore exceptions due to instances being shut down
1183 263b8de6 Guido Trotter
        continue
1184 263b8de6 Guido Trotter
      if info:
1185 263b8de6 Guido Trotter
        data.append(info)
1186 eb58f9b1 Guido Trotter
    return data
1187 eb58f9b1 Guido Trotter
1188 4a44d8aa Dimitris Aragiorgis
  def _GenerateKVMBlockDevicesOptions(self, instance, kvm_disks,
1189 e419e42f Dimitris Aragiorgis
                                      kvmhelp, devlist):
1190 e419e42f Dimitris Aragiorgis
    """Generate KVM options regarding instance's block devices.
1191 e419e42f Dimitris Aragiorgis

1192 e419e42f Dimitris Aragiorgis
    @type instance: L{objects.Instance}
1193 e419e42f Dimitris Aragiorgis
    @param instance: the instance object
1194 4a44d8aa Dimitris Aragiorgis
    @type kvm_disks: list of tuples
1195 4a44d8aa Dimitris Aragiorgis
    @param kvm_disks: list of tuples [(disk, link_name)..]
1196 e419e42f Dimitris Aragiorgis
    @type kvmhelp: string
1197 e419e42f Dimitris Aragiorgis
    @param kvmhelp: output of kvm --help
1198 e419e42f Dimitris Aragiorgis
    @type devlist: string
1199 e419e42f Dimitris Aragiorgis
    @param devlist: output of kvm -device ?
1200 e419e42f Dimitris Aragiorgis
    @rtype: list
1201 e419e42f Dimitris Aragiorgis
    @return: list of command line options eventually used by kvm executable
1202 ece1057c Dimitris Aragiorgis

1203 e419e42f Dimitris Aragiorgis
    """
1204 ece1057c Dimitris Aragiorgis
    hvp = instance.hvparams
1205 e419e42f Dimitris Aragiorgis
    kernel_path = hvp[constants.HV_KERNEL_PATH]
1206 e419e42f Dimitris Aragiorgis
    if kernel_path:
1207 e419e42f Dimitris Aragiorgis
      boot_disk = False
1208 e419e42f Dimitris Aragiorgis
    else:
1209 e419e42f Dimitris Aragiorgis
      boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
1210 ece1057c Dimitris Aragiorgis
1211 ece1057c Dimitris Aragiorgis
    # whether this is an older KVM version that uses the boot=on flag
1212 ece1057c Dimitris Aragiorgis
    # on devices
1213 ece1057c Dimitris Aragiorgis
    needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1214 ece1057c Dimitris Aragiorgis
1215 ece1057c Dimitris Aragiorgis
    dev_opts = []
1216 994ccaf2 Dimitris Aragiorgis
    device_driver = None
1217 ece1057c Dimitris Aragiorgis
    disk_type = hvp[constants.HV_DISK_TYPE]
1218 ece1057c Dimitris Aragiorgis
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
1219 ece1057c Dimitris Aragiorgis
      if_val = ",if=%s" % self._VIRTIO
1220 994ccaf2 Dimitris Aragiorgis
      try:
1221 994ccaf2 Dimitris Aragiorgis
        if self._VIRTIO_BLK_RE.search(devlist):
1222 0288e7bf Dimitris Aragiorgis
          if_val = ",if=none"
1223 994ccaf2 Dimitris Aragiorgis
          # will be passed in -device option as driver
1224 994ccaf2 Dimitris Aragiorgis
          device_driver = self._VIRTIO_BLK_PCI
1225 994ccaf2 Dimitris Aragiorgis
      except errors.HypervisorError, _:
1226 994ccaf2 Dimitris Aragiorgis
        pass
1227 ece1057c Dimitris Aragiorgis
    else:
1228 ece1057c Dimitris Aragiorgis
      if_val = ",if=%s" % disk_type
1229 ece1057c Dimitris Aragiorgis
    # Cache mode
1230 ece1057c Dimitris Aragiorgis
    disk_cache = hvp[constants.HV_DISK_CACHE]
1231 ece1057c Dimitris Aragiorgis
    if instance.disk_template in constants.DTS_EXT_MIRROR:
1232 ece1057c Dimitris Aragiorgis
      if disk_cache != "none":
1233 ece1057c Dimitris Aragiorgis
        # TODO: make this a hard error, instead of a silent overwrite
1234 ece1057c Dimitris Aragiorgis
        logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
1235 ece1057c Dimitris Aragiorgis
                        " to prevent shared storage corruption on migration",
1236 ece1057c Dimitris Aragiorgis
                        disk_cache)
1237 ece1057c Dimitris Aragiorgis
      cache_val = ",cache=none"
1238 ece1057c Dimitris Aragiorgis
    elif disk_cache != constants.HT_CACHE_DEFAULT:
1239 ece1057c Dimitris Aragiorgis
      cache_val = ",cache=%s" % disk_cache
1240 ece1057c Dimitris Aragiorgis
    else:
1241 ece1057c Dimitris Aragiorgis
      cache_val = ""
1242 4a44d8aa Dimitris Aragiorgis
    for cfdev, link_name in kvm_disks:
1243 ece1057c Dimitris Aragiorgis
      if cfdev.mode != constants.DISK_RDWR:
1244 ece1057c Dimitris Aragiorgis
        raise errors.HypervisorError("Instance has read-only disks which"
1245 ece1057c Dimitris Aragiorgis
                                     " are not supported by KVM")
1246 ece1057c Dimitris Aragiorgis
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
1247 ece1057c Dimitris Aragiorgis
      boot_val = ""
1248 ece1057c Dimitris Aragiorgis
      if boot_disk:
1249 ece1057c Dimitris Aragiorgis
        dev_opts.extend(["-boot", "c"])
1250 ece1057c Dimitris Aragiorgis
        boot_disk = False
1251 ece1057c Dimitris Aragiorgis
        if needs_boot_flag and disk_type != constants.HT_DISK_IDE:
1252 ece1057c Dimitris Aragiorgis
          boot_val = ",boot=on"
1253 ece1057c Dimitris Aragiorgis
      drive_val = "file=%s,format=raw%s%s%s" % \
1254 ece1057c Dimitris Aragiorgis
                  (dev_path, if_val, boot_val, cache_val)
1255 ece1057c Dimitris Aragiorgis
1256 994ccaf2 Dimitris Aragiorgis
      if device_driver:
1257 4a44d8aa Dimitris Aragiorgis
        # kvm_disks are the 4th entry of runtime file that did not exist in
1258 0288e7bf Dimitris Aragiorgis
        # the past. That means that cfdev should always have pci slot and
1259 0288e7bf Dimitris Aragiorgis
        # _GenerateDeviceKVMId() will not raise a exception.
1260 0288e7bf Dimitris Aragiorgis
        kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_DISK, cfdev)
1261 0288e7bf Dimitris Aragiorgis
        drive_val += (",id=%s" % kvm_devid)
1262 0288e7bf Dimitris Aragiorgis
        drive_val += (",bus=0,unit=%d" % cfdev.pci)
1263 0288e7bf Dimitris Aragiorgis
        dev_val = ("%s,drive=%s,id=%s" %
1264 0288e7bf Dimitris Aragiorgis
                   (device_driver, kvm_devid, kvm_devid))
1265 0288e7bf Dimitris Aragiorgis
        dev_val += ",bus=pci.0,addr=%s" % hex(cfdev.pci)
1266 0288e7bf Dimitris Aragiorgis
        dev_opts.extend(["-device", dev_val])
1267 0288e7bf Dimitris Aragiorgis
1268 ece1057c Dimitris Aragiorgis
      dev_opts.extend(["-drive", drive_val])
1269 ece1057c Dimitris Aragiorgis
1270 ece1057c Dimitris Aragiorgis
    return dev_opts
1271 ece1057c Dimitris Aragiorgis
1272 b73f1c59 Guido Trotter
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused,
1273 b73f1c59 Guido Trotter
                          kvmhelp):
1274 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
1275 eb58f9b1 Guido Trotter

1276 b73f1c59 Guido Trotter
    @type kvmhelp: string
1277 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1278 839642c2 Iustin Pop
    @attention: this function must not have any side-effects; for
1279 839642c2 Iustin Pop
        example, it must not write to the filesystem, or read values
1280 839642c2 Iustin Pop
        from the current system the are expected to differ between
1281 839642c2 Iustin Pop
        nodes, since it is only run once at instance startup;
1282 839642c2 Iustin Pop
        actions/kvm arguments that can vary between systems should be
1283 839642c2 Iustin Pop
        done in L{_ExecuteKVMRuntime}
1284 839642c2 Iustin Pop

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

1626 38e250ba Guido Trotter
    """
1627 38e250ba Guido Trotter
    try:
1628 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1629 38e250ba Guido Trotter
                      data=data)
1630 90c024f6 Guido Trotter
    except EnvironmentError, err:
1631 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1632 38e250ba Guido Trotter
1633 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
1634 38e250ba Guido Trotter
    """Read an instance's KVM runtime
1635 38e250ba Guido Trotter

1636 38e250ba Guido Trotter
    """
1637 38e250ba Guido Trotter
    try:
1638 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1639 90c024f6 Guido Trotter
    except EnvironmentError, err:
1640 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1641 38e250ba Guido Trotter
    return file_content
1642 38e250ba Guido Trotter
1643 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1644 38e250ba Guido Trotter
    """Save an instance's KVM runtime
1645 38e250ba Guido Trotter

1646 38e250ba Guido Trotter
    """
1647 4a44d8aa Dimitris Aragiorgis
    kvm_cmd, kvm_nics, hvparams, kvm_disks = kvm_runtime
1648 58502c9e Dimitris Aragiorgis
1649 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1650 4a44d8aa Dimitris Aragiorgis
    serialized_disks = [(blk.ToDict(), link)
1651 4a44d8aa Dimitris Aragiorgis
                            for blk, link in kvm_disks]
1652 58502c9e Dimitris Aragiorgis
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams,
1653 4a44d8aa Dimitris Aragiorgis
                                      serialized_disks))
1654 58502c9e Dimitris Aragiorgis
1655 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
1656 38e250ba Guido Trotter
1657 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1658 38e250ba Guido Trotter
    """Load an instance's KVM runtime
1659 38e250ba Guido Trotter

1660 38e250ba Guido Trotter
    """
1661 30e42c4e Guido Trotter
    if not serialized_runtime:
1662 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1663 58502c9e Dimitris Aragiorgis
1664 58502c9e Dimitris Aragiorgis
    return _AnalyzeSerializedRuntime(serialized_runtime)
1665 38e250ba Guido Trotter
1666 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1667 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
1668 76431533 Guido Trotter

1669 76431533 Guido Trotter
    @type name: string
1670 76431533 Guido Trotter
    @param name: instance name
1671 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1672 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1673 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1674 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1675 76431533 Guido Trotter

1676 76431533 Guido Trotter
    """
1677 5d9bfd87 Apollon Oikonomopoulos
    try:
1678 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1679 5d9bfd87 Apollon Oikonomopoulos
    finally:
1680 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
1681 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
1682 5d9bfd87 Apollon Oikonomopoulos
1683 76431533 Guido Trotter
    if result.failed:
1684 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1685 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
1686 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
1687 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
1688 76431533 Guido Trotter
1689 4a44d8aa Dimitris Aragiorgis
  # too many local variables
1690 58502c9e Dimitris Aragiorgis
  # pylint: disable=R0914
1691 b73f1c59 Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1692 839642c2 Iustin Pop
    """Execute a KVM cmd, after completing it with some last minute data.
1693 ee5f20b0 Guido Trotter

1694 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1695 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1696 b73f1c59 Guido Trotter
    @type kvmhelp: string
1697 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1698 30e42c4e Guido Trotter

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

1917 ee5f20b0 Guido Trotter
    """
1918 5905901c Iustin Pop
    self._CheckDown(instance.name)
1919 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1920 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1921 7238edb5 Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1922 b73f1c59 Guido Trotter
                                           startup_paused, kvmhelp)
1923 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1924 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1925 ee5f20b0 Guido Trotter
1926 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
1927 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
1928 6567aff3 Guido Trotter

1929 6567aff3 Guido Trotter
    """
1930 eace6157 Michael Hanselmann
    # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
1931 eace6157 Michael Hanselmann
    # version. The monitor protocol is designed for human consumption, whereas
1932 eace6157 Michael Hanselmann
    # QMP is made for programmatic usage. In the worst case QMP can also
1933 eace6157 Michael Hanselmann
    # execute monitor commands. As it is, all calls to socat take at least
1934 eace6157 Michael Hanselmann
    # 500ms and likely more: socat can't detect the end of the reply and waits
1935 eace6157 Michael Hanselmann
    # for 500ms of no data received before exiting (500 ms is the default for
1936 eace6157 Michael Hanselmann
    # the "-t" parameter).
1937 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1938 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
1939 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
1940 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1941 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
1942 6567aff3 Guido Trotter
    if result.failed:
1943 afa9bb2e Michael Hanselmann
      msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
1944 afa9bb2e Michael Hanselmann
             " output: %s" %
1945 afa9bb2e Michael Hanselmann
             (command, instance_name, result.fail_reason, result.output))
1946 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
1947 6567aff3 Guido Trotter
1948 6567aff3 Guido Trotter
    return result
1949 6567aff3 Guido Trotter
1950 8b7be6f2 Dimitris Aragiorgis
  def _GetFreePCISlot(self, instance, dev):
1951 8b7be6f2 Dimitris Aragiorgis
    """Get the first available pci slot of a runnung instance.
1952 8b7be6f2 Dimitris Aragiorgis

1953 8b7be6f2 Dimitris Aragiorgis
    """
1954 8b7be6f2 Dimitris Aragiorgis
    slots = bitarray(32)
1955 8b7be6f2 Dimitris Aragiorgis
    slots.setall(False) # pylint: disable=E1101
1956 8b7be6f2 Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance.name, self._INFO_PCI_CMD)
1957 8b7be6f2 Dimitris Aragiorgis
    for line in output.stdout.splitlines():
1958 8b7be6f2 Dimitris Aragiorgis
      match = self._INFO_PCI_RE.search(line)
1959 8b7be6f2 Dimitris Aragiorgis
      if match:
1960 8b7be6f2 Dimitris Aragiorgis
        slot = int(match.group(1))
1961 8b7be6f2 Dimitris Aragiorgis
        slots[slot] = True
1962 8b7be6f2 Dimitris Aragiorgis
1963 8b7be6f2 Dimitris Aragiorgis
    [free] = slots.search(_AVAILABLE_PCI_SLOT, 1) # pylint: disable=E1101
1964 8b7be6f2 Dimitris Aragiorgis
    if not free:
1965 8b7be6f2 Dimitris Aragiorgis
      raise errors.HypervisorError("All PCI slots occupied")
1966 8b7be6f2 Dimitris Aragiorgis
1967 8b7be6f2 Dimitris Aragiorgis
    dev.pci = int(free)
1968 8b7be6f2 Dimitris Aragiorgis
1969 9f395c32 Dimitris Aragiorgis
  def VerifyHotplugSupport(self, instance, action, dev_type):
1970 9f395c32 Dimitris Aragiorgis
    """Verifies that hotplug is supported.
1971 d7583563 Dimitris Aragiorgis

1972 d7583563 Dimitris Aragiorgis
    Hotplug is *not* supported in case of:
1973 d7583563 Dimitris Aragiorgis
     - security models and chroot (disk hotplug)
1974 d7583563 Dimitris Aragiorgis
     - fdsend module is missing (nic hot-add)
1975 d7583563 Dimitris Aragiorgis

1976 9f395c32 Dimitris Aragiorgis
    @raise errors.HypervisorError: in one of the previous cases
1977 d7583563 Dimitris Aragiorgis

1978 d7583563 Dimitris Aragiorgis
    """
1979 d7583563 Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
1980 d7583563 Dimitris Aragiorgis
      hvp = instance.hvparams
1981 d7583563 Dimitris Aragiorgis
      security_model = hvp[constants.HV_SECURITY_MODEL]
1982 d7583563 Dimitris Aragiorgis
      use_chroot = hvp[constants.HV_KVM_USE_CHROOT]
1983 d7583563 Dimitris Aragiorgis
      if use_chroot:
1984 d7583563 Dimitris Aragiorgis
        raise errors.HotplugError("Disk hotplug is not supported"
1985 d7583563 Dimitris Aragiorgis
                                  " in case of chroot.")
1986 d7583563 Dimitris Aragiorgis
      if security_model != constants.HT_SM_NONE:
1987 d7583563 Dimitris Aragiorgis
        raise errors.HotplugError("Disk Hotplug is not supported in case"
1988 d7583563 Dimitris Aragiorgis
                                  " security models are used.")
1989 d7583563 Dimitris Aragiorgis
1990 d7583563 Dimitris Aragiorgis
    if (dev_type == constants.HOTPLUG_TARGET_NIC and
1991 d7583563 Dimitris Aragiorgis
        action == constants.HOTPLUG_ACTION_ADD and not fdsend):
1992 d7583563 Dimitris Aragiorgis
      raise errors.HotplugError("Cannot hot-add NIC."
1993 d7583563 Dimitris Aragiorgis
                                " fdsend python module is missing.")
1994 d7583563 Dimitris Aragiorgis
1995 caf74756 Dimitris Aragiorgis
  def HotplugSupported(self, instance):
1996 caf74756 Dimitris Aragiorgis
    """Checks if hotplug is generally supported.
1997 caf74756 Dimitris Aragiorgis

1998 caf74756 Dimitris Aragiorgis
    Hotplug is *not* supported in case of:
1999 caf74756 Dimitris Aragiorgis
     - qemu versions < 1.0
2000 caf74756 Dimitris Aragiorgis
     - for stopped instances
2001 caf74756 Dimitris Aragiorgis

2002 caf74756 Dimitris Aragiorgis
    @raise errors.HypervisorError: in one of the previous cases
2003 caf74756 Dimitris Aragiorgis

2004 caf74756 Dimitris Aragiorgis
    """
2005 e7a77eb8 Dimitris Aragiorgis
    try:
2006 e7a77eb8 Dimitris Aragiorgis
      output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD)
2007 e7a77eb8 Dimitris Aragiorgis
    except errors.HypervisorError:
2008 e7a77eb8 Dimitris Aragiorgis
      raise errors.HotplugError("Instance is probably down")
2009 e7a77eb8 Dimitris Aragiorgis
2010 caf74756 Dimitris Aragiorgis
    # TODO: search for netdev_add, drive_add, device_add.....
2011 caf74756 Dimitris Aragiorgis
    match = self._INFO_VERSION_RE.search(output.stdout)
2012 caf74756 Dimitris Aragiorgis
    if not match:
2013 e7a77eb8 Dimitris Aragiorgis
      raise errors.HotplugError("Cannot parse qemu version via monitor")
2014 e7a77eb8 Dimitris Aragiorgis
2015 caf74756 Dimitris Aragiorgis
    v_major, v_min, _, _ = match.groups()
2016 caf74756 Dimitris Aragiorgis
    if (int(v_major), int(v_min)) < (1, 0):
2017 caf74756 Dimitris Aragiorgis
      raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0")
2018 caf74756 Dimitris Aragiorgis
2019 d7583563 Dimitris Aragiorgis
  def _CallHotplugCommand(self, name, cmd):
2020 d7583563 Dimitris Aragiorgis
    output = self._CallMonitorCommand(name, cmd)
2021 d7583563 Dimitris Aragiorgis
    # TODO: parse output and check if succeeded
2022 d7583563 Dimitris Aragiorgis
    for line in output.stdout.splitlines():
2023 d7583563 Dimitris Aragiorgis
      logging.info("%s", line)
2024 d7583563 Dimitris Aragiorgis
2025 af2f716d Dimitris Aragiorgis
  def HotAddDevice(self, instance, dev_type, device, extra, seq):
2026 af2f716d Dimitris Aragiorgis
    """ Helper method to hot-add a new device
2027 af2f716d Dimitris Aragiorgis

2028 af2f716d Dimitris Aragiorgis
    It gets free pci slot generates the device name and invokes the
2029 af2f716d Dimitris Aragiorgis
    device specific method.
2030 af2f716d Dimitris Aragiorgis

2031 af2f716d Dimitris Aragiorgis
    """
2032 af2f716d Dimitris Aragiorgis
    # in case of hot-mod this is given
2033 af2f716d Dimitris Aragiorgis
    if device.pci is None:
2034 af2f716d Dimitris Aragiorgis
      self._GetFreePCISlot(instance, device)
2035 af2f716d Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, device)
2036 af2f716d Dimitris Aragiorgis
    runtime = self._LoadKVMRuntime(instance)
2037 af2f716d Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2038 af2f716d Dimitris Aragiorgis
      command = "drive_add dummy file=%s,if=none,id=%s,format=raw\n" % \
2039 af2f716d Dimitris Aragiorgis
                 (extra, kvm_devid)
2040 af2f716d Dimitris Aragiorgis
      command += ("device_add virtio-blk-pci,bus=pci.0,addr=%s,drive=%s,id=%s" %
2041 af2f716d Dimitris Aragiorgis
                  (hex(device.pci), kvm_devid, kvm_devid))
2042 af2f716d Dimitris Aragiorgis
    elif dev_type == constants.HOTPLUG_TARGET_NIC:
2043 af2f716d Dimitris Aragiorgis
      (tap, fd) = _OpenTap()
2044 af2f716d Dimitris Aragiorgis
      self._ConfigureNIC(instance, seq, device, tap)
2045 af2f716d Dimitris Aragiorgis
      self._PassTapFd(instance, fd, device)
2046 af2f716d Dimitris Aragiorgis
      command = "netdev_add tap,id=%s,fd=%s\n" % (kvm_devid, kvm_devid)
2047 af2f716d Dimitris Aragiorgis
      args = "virtio-net-pci,bus=pci.0,addr=%s,mac=%s,netdev=%s,id=%s" % \
2048 af2f716d Dimitris Aragiorgis
               (hex(device.pci), device.mac, kvm_devid, kvm_devid)
2049 af2f716d Dimitris Aragiorgis
      command += "device_add %s" % args
2050 af2f716d Dimitris Aragiorgis
      utils.WriteFile(self._InstanceNICFile(instance.name, seq), data=tap)
2051 af2f716d Dimitris Aragiorgis
2052 af2f716d Dimitris Aragiorgis
    self._CallHotplugCommand(instance.name, command)
2053 af2f716d Dimitris Aragiorgis
    # update relevant entries in runtime file
2054 af2f716d Dimitris Aragiorgis
    index = _DEVICE_RUNTIME_INDEX[dev_type]
2055 af2f716d Dimitris Aragiorgis
    entry = _RUNTIME_ENTRY[dev_type](device, extra)
2056 af2f716d Dimitris Aragiorgis
    runtime[index].append(entry)
2057 af2f716d Dimitris Aragiorgis
    self._SaveKVMRuntime(instance, runtime)
2058 af2f716d Dimitris Aragiorgis
2059 af2f716d Dimitris Aragiorgis
  def HotDelDevice(self, instance, dev_type, device, _, seq):
2060 af2f716d Dimitris Aragiorgis
    """ Helper method for hot-del device
2061 af2f716d Dimitris Aragiorgis

2062 af2f716d Dimitris Aragiorgis
    It gets device info from runtime file, generates the device name and
2063 af2f716d Dimitris Aragiorgis
    invokes the device specific method.
2064 af2f716d Dimitris Aragiorgis

2065 af2f716d Dimitris Aragiorgis
    """
2066 af2f716d Dimitris Aragiorgis
    runtime = self._LoadKVMRuntime(instance)
2067 af2f716d Dimitris Aragiorgis
    entry = _GetExistingDeviceInfo(dev_type, device, runtime)
2068 af2f716d Dimitris Aragiorgis
    kvm_device = _RUNTIME_DEVICE[dev_type](entry)
2069 af2f716d Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, kvm_device)
2070 af2f716d Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2071 1c6c4d6d Dimitris Aragiorgis
      command = "device_del %s\n" % kvm_devid
2072 1c6c4d6d Dimitris Aragiorgis
      command += "drive_del %s" % kvm_devid
2073 af2f716d Dimitris Aragiorgis
    elif dev_type == constants.HOTPLUG_TARGET_NIC:
2074 af2f716d Dimitris Aragiorgis
      command = "device_del %s\n" % kvm_devid
2075 af2f716d Dimitris Aragiorgis
      command += "netdev_del %s" % kvm_devid
2076 af2f716d Dimitris Aragiorgis
      utils.RemoveFile(self._InstanceNICFile(instance.name, seq))
2077 af2f716d Dimitris Aragiorgis
    self._CallHotplugCommand(instance.name, command)
2078 af2f716d Dimitris Aragiorgis
    index = _DEVICE_RUNTIME_INDEX[dev_type]
2079 af2f716d Dimitris Aragiorgis
    runtime[index].remove(entry)
2080 af2f716d Dimitris Aragiorgis
    self._SaveKVMRuntime(instance, runtime)
2081 af2f716d Dimitris Aragiorgis
2082 af2f716d Dimitris Aragiorgis
    return kvm_device.pci
2083 af2f716d Dimitris Aragiorgis
2084 af2f716d Dimitris Aragiorgis
  def HotModDevice(self, instance, dev_type, device, _, seq):
2085 af2f716d Dimitris Aragiorgis
    """ Helper method for hot-mod device
2086 af2f716d Dimitris Aragiorgis

2087 af2f716d Dimitris Aragiorgis
    It gets device info from runtime file, generates the device name and
2088 af2f716d Dimitris Aragiorgis
    invokes the device specific method. Currently only NICs support hot-mod
2089 af2f716d Dimitris Aragiorgis

2090 af2f716d Dimitris Aragiorgis
    """
2091 af2f716d Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_NIC:
2092 af2f716d Dimitris Aragiorgis
      # putting it back in the same pci slot
2093 af2f716d Dimitris Aragiorgis
      device.pci = self.HotDelDevice(instance, dev_type, device, _, seq)
2094 af2f716d Dimitris Aragiorgis
      # TODO: remove sleep when socat gets removed
2095 af2f716d Dimitris Aragiorgis
      time.sleep(2)
2096 af2f716d Dimitris Aragiorgis
      self.HotAddDevice(instance, dev_type, device, _, seq)
2097 af2f716d Dimitris Aragiorgis
2098 af2f716d Dimitris Aragiorgis
  def _PassTapFd(self, instance, fd, nic):
2099 af2f716d Dimitris Aragiorgis
    """Pass file descriptor to kvm process via monitor socket using SCM_RIGHTS
2100 af2f716d Dimitris Aragiorgis

2101 af2f716d Dimitris Aragiorgis
    """
2102 af2f716d Dimitris Aragiorgis
    # TODO: factor out code related to unix sockets.
2103 af2f716d Dimitris Aragiorgis
    #       squash common parts between monitor and qmp
2104 af2f716d Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_NIC, nic)
2105 af2f716d Dimitris Aragiorgis
    command = "getfd %s\n" % kvm_devid
2106 af2f716d Dimitris Aragiorgis
    fds = [fd]
2107 af2f716d Dimitris Aragiorgis
    logging.info("%s", fds)
2108 af2f716d Dimitris Aragiorgis
    try:
2109 af2f716d Dimitris Aragiorgis
      monsock = MonitorSocket(self._InstanceMonitor(instance.name))
2110 af2f716d Dimitris Aragiorgis
      monsock.connect()
2111 af2f716d Dimitris Aragiorgis
      fdsend.sendfds(monsock.sock, command, fds=fds)
2112 af2f716d Dimitris Aragiorgis
    finally:
2113 af2f716d Dimitris Aragiorgis
      monsock.close()
2114 af2f716d Dimitris Aragiorgis
2115 b52d85c1 Guido Trotter
  @classmethod
2116 585c8187 Guido Trotter
  def _ParseKVMVersion(cls, text):
2117 585c8187 Guido Trotter
    """Parse the KVM version from the --help output.
2118 585c8187 Guido Trotter

2119 585c8187 Guido Trotter
    @type text: string
2120 585c8187 Guido Trotter
    @param text: output of kvm --help
2121 585c8187 Guido Trotter
    @return: (version, v_maj, v_min, v_rev)
2122 5c3d5dfd Iustin Pop
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
2123 585c8187 Guido Trotter

2124 585c8187 Guido Trotter
    """
2125 585c8187 Guido Trotter
    match = cls._VERSION_RE.search(text.splitlines()[0])
2126 585c8187 Guido Trotter
    if not match:
2127 585c8187 Guido Trotter
      raise errors.HypervisorError("Unable to get KVM version")
2128 585c8187 Guido Trotter
2129 585c8187 Guido Trotter
    v_all = match.group(0)
2130 585c8187 Guido Trotter
    v_maj = int(match.group(1))
2131 585c8187 Guido Trotter
    v_min = int(match.group(2))
2132 585c8187 Guido Trotter
    if match.group(4):
2133 585c8187 Guido Trotter
      v_rev = int(match.group(4))
2134 585c8187 Guido Trotter
    else:
2135 585c8187 Guido Trotter
      v_rev = 0
2136 585c8187 Guido Trotter
    return (v_all, v_maj, v_min, v_rev)
2137 585c8187 Guido Trotter
2138 585c8187 Guido Trotter
  @classmethod
2139 6e043e60 Guido Trotter
  def _GetKVMOutput(cls, kvm_path, option):
2140 6e043e60 Guido Trotter
    """Return the output of a kvm invocation
2141 e3b89628 Guido Trotter

2142 bc0fed4b Guido Trotter
    @type kvm_path: string
2143 bc0fed4b Guido Trotter
    @param kvm_path: path to the kvm executable
2144 bc0fed4b Guido Trotter
    @type option: a key of _KVMOPTS_CMDS
2145 bc0fed4b Guido Trotter
    @param option: kvm option to fetch the output from
2146 6e043e60 Guido Trotter
    @return: output a supported kvm invocation
2147 e3b89628 Guido Trotter
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
2148 e3b89628 Guido Trotter

2149 e3b89628 Guido Trotter
    """
2150 6e043e60 Guido Trotter
    assert option in cls._KVMOPTS_CMDS, "Invalid output option"
2151 6e043e60 Guido Trotter
2152 bc0fed4b Guido Trotter
    optlist, can_fail = cls._KVMOPTS_CMDS[option]
2153 bc0fed4b Guido Trotter
2154 bc0fed4b Guido Trotter
    result = utils.RunCmd([kvm_path] + optlist)
2155 bc0fed4b Guido Trotter
    if result.failed and not can_fail:
2156 af89fa76 Helga Velroyen
      raise errors.HypervisorError("Unable to get KVM %s output" %
2157 3ddc7650 Jose A. Lopes
                                    " ".join(optlist))
2158 e3b89628 Guido Trotter
    return result.output
2159 e3b89628 Guido Trotter
2160 e3b89628 Guido Trotter
  @classmethod
2161 3b59ec02 Guido Trotter
  def _GetKVMVersion(cls, kvm_path):
2162 d7e4a2b1 Andrea Spadaccini
    """Return the installed KVM version.
2163 b52d85c1 Guido Trotter

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

2167 b52d85c1 Guido Trotter
    """
2168 6e043e60 Guido Trotter
    return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
2169 82e3bf85 Dimitris Aragiorgis
2170 82e3bf85 Dimitris Aragiorgis
  @classmethod
2171 82e3bf85 Dimitris Aragiorgis
  def _GetDefaultMachineVersion(cls, kvm_path):
2172 82e3bf85 Dimitris Aragiorgis
    """Return the default hardware revision (e.g. pc-1.1)
2173 82e3bf85 Dimitris Aragiorgis

2174 82e3bf85 Dimitris Aragiorgis
    """
2175 6e043e60 Guido Trotter
    output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2176 82e3bf85 Dimitris Aragiorgis
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
2177 82e3bf85 Dimitris Aragiorgis
    if match:
2178 82e3bf85 Dimitris Aragiorgis
      return match.group(1)
2179 82e3bf85 Dimitris Aragiorgis
    else:
2180 82e3bf85 Dimitris Aragiorgis
      return "pc"
2181 82e3bf85 Dimitris Aragiorgis
2182 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
2183 eb58f9b1 Guido Trotter
    """Stop an instance.
2184 eb58f9b1 Guido Trotter

2185 eb58f9b1 Guido Trotter
    """
2186 bbcf7ad0 Iustin Pop
    if name is not None and not force:
2187 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
2188 bbcf7ad0 Iustin Pop
    if name is None:
2189 bbcf7ad0 Iustin Pop
      name = instance.name
2190 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
2191 bbcf7ad0 Iustin Pop
    else:
2192 bbcf7ad0 Iustin Pop
      acpi = False
2193 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
2194 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
2195 bbcf7ad0 Iustin Pop
      if force or not acpi:
2196 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
2197 eb58f9b1 Guido Trotter
      else:
2198 d0c8c01d Iustin Pop
        self._CallMonitorCommand(name, "system_powerdown")
2199 eb58f9b1 Guido Trotter
2200 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
2201 8904b35c Guido Trotter
    """Cleanup after a stopped instance
2202 8904b35c Guido Trotter

2203 8904b35c Guido Trotter
    """
2204 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
2205 8904b35c Guido Trotter
    if pid > 0 and alive:
2206 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
2207 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
2208 eb58f9b1 Guido Trotter
2209 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
2210 eb58f9b1 Guido Trotter
    """Reboot an instance.
2211 eb58f9b1 Guido Trotter

2212 eb58f9b1 Guido Trotter
    """
2213 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
2214 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
2215 eb58f9b1 Guido Trotter
    # to shutdown and restart.
2216 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
2217 1f8b3a27 Guido Trotter
    if not alive:
2218 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
2219 78411c60 Iustin Pop
                                   " not running" % instance.name)
2220 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
2221 f02881e0 Guido Trotter
    # ...first load it...
2222 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
2223 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
2224 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
2225 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
2226 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
2227 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
2228 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2229 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2230 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
2231 eb58f9b1 Guido Trotter
2232 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
2233 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
2234 30e42c4e Guido Trotter

2235 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2236 30e42c4e Guido Trotter
    @param instance: instance to be migrated
2237 30e42c4e Guido Trotter
    @rtype: string
2238 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
2239 30e42c4e Guido Trotter

2240 30e42c4e Guido Trotter
    """
2241 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
2242 30e42c4e Guido Trotter
2243 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
2244 30e42c4e Guido Trotter
    """Prepare to accept an instance.
2245 30e42c4e Guido Trotter

2246 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2247 30e42c4e Guido Trotter
    @param instance: instance to be accepted
2248 30e42c4e Guido Trotter
    @type info: string
2249 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
2250 30e42c4e Guido Trotter
    @type target: string
2251 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
2252 30e42c4e Guido Trotter

2253 30e42c4e Guido Trotter
    """
2254 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2255 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
2256 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2257 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2258 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
2259 b73f1c59 Guido Trotter
                            incoming=incoming_address)
2260 30e42c4e Guido Trotter
2261 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
2262 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
2263 30e42c4e Guido Trotter

2264 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
2265 30e42c4e Guido Trotter

2266 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2267 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
2268 30e42c4e Guido Trotter

2269 30e42c4e Guido Trotter
    """
2270 30e42c4e Guido Trotter
    if success:
2271 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2272 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
2273 5d9bfd87 Apollon Oikonomopoulos
2274 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
2275 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
2276 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
2277 cc8a8ed7 Apollon Oikonomopoulos
          continue
2278 5d9bfd87 Apollon Oikonomopoulos
        try:
2279 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
2280 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
2281 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
2282 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
2283 5d9bfd87 Apollon Oikonomopoulos
          continue
2284 5d9bfd87 Apollon Oikonomopoulos
        try:
2285 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
2286 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
2287 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
2288 5d9bfd87 Apollon Oikonomopoulos
2289 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
2290 30e42c4e Guido Trotter
    else:
2291 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
2292 30e42c4e Guido Trotter
2293 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
2294 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
2295 30e42c4e Guido Trotter

2296 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
2297 30e42c4e Guido Trotter
    currently running.
2298 30e42c4e Guido Trotter

2299 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
2300 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
2301 30e42c4e Guido Trotter
    @type target: string
2302 30e42c4e Guido Trotter
    @param target: ip address of the target node
2303 30e42c4e Guido Trotter
    @type live: boolean
2304 30e42c4e Guido Trotter
    @param live: perform a live migration
2305 30e42c4e Guido Trotter

2306 30e42c4e Guido Trotter
    """
2307 58d38b02 Iustin Pop
    instance_name = instance.name
2308 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
2309 6a1434d7 Andrea Spadaccini
    _, _, alive = self._InstancePidAlive(instance_name)
2310 30e42c4e Guido Trotter
    if not alive:
2311 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
2312 30e42c4e Guido Trotter
2313 30e42c4e Guido Trotter
    if not live:
2314 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
2315 30e42c4e Guido Trotter
2316 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
2317 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
2318 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2319 e43d4f9f Apollon Oikonomopoulos
2320 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
2321 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
2322 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2323 e43d4f9f Apollon Oikonomopoulos
2324 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
2325 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
2326 30e42c4e Guido Trotter
2327 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
2328 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
2329 6a1434d7 Andrea Spadaccini

2330 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2331 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
2332 6a1434d7 Andrea Spadaccini
    @type success: bool
2333 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
2334 6a1434d7 Andrea Spadaccini
    @type live: bool
2335 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
2336 6a1434d7 Andrea Spadaccini

2337 6a1434d7 Andrea Spadaccini
    """
2338 6a1434d7 Andrea Spadaccini
    if success:
2339 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
2340 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
2341 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
2342 6a1434d7 Andrea Spadaccini
    elif live:
2343 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
2344 6a1434d7 Andrea Spadaccini
2345 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
2346 6a1434d7 Andrea Spadaccini
    """Get the migration status
2347 6a1434d7 Andrea Spadaccini

2348 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2349 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
2350 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
2351 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
2352 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
2353 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
2354 6a1434d7 Andrea Spadaccini

2355 6a1434d7 Andrea Spadaccini
    """
2356 d0c8c01d Iustin Pop
    info_command = "info migrate"
2357 6a1434d7 Andrea Spadaccini
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
2358 6a1434d7 Andrea Spadaccini
      result = self._CallMonitorCommand(instance.name, info_command)
2359 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
2360 30e42c4e Guido Trotter
      if not match:
2361 c4e388a5 Guido Trotter
        if not result.stdout:
2362 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
2363 c4e388a5 Guido Trotter
        else:
2364 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
2365 c4e388a5 Guido Trotter
                          result.stdout)
2366 30e42c4e Guido Trotter
      else:
2367 30e42c4e Guido Trotter
        status = match.group(1)
2368 6a1434d7 Andrea Spadaccini
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
2369 6a1434d7 Andrea Spadaccini
          migration_status = objects.MigrationStatus(status=status)
2370 61643226 Andrea Spadaccini
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
2371 61643226 Andrea Spadaccini
          if match:
2372 61643226 Andrea Spadaccini
            migration_status.transferred_ram = match.group("transferred")
2373 61643226 Andrea Spadaccini
            migration_status.total_ram = match.group("total")
2374 61643226 Andrea Spadaccini
2375 6a1434d7 Andrea Spadaccini
          return migration_status
2376 30e42c4e Guido Trotter
2377 6a1434d7 Andrea Spadaccini
        logging.warning("KVM: unknown migration status '%s'", status)
2378 6a1434d7 Andrea Spadaccini
2379 6a1434d7 Andrea Spadaccini
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
2380 6a1434d7 Andrea Spadaccini
2381 62457f51 Iustin Pop
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
2382 30e42c4e Guido Trotter
2383 3d836750 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
2384 3d836750 Guido Trotter
    """Balloon an instance memory to a certain value.
2385 3d836750 Guido Trotter

2386 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
2387 3d836750 Guido Trotter
    @param instance: instance to be accepted
2388 3d836750 Guido Trotter
    @type mem: int
2389 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
2390 3d836750 Guido Trotter

2391 3d836750 Guido Trotter
    """
2392 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2393 3d836750 Guido Trotter
2394 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
2395 eb58f9b1 Guido Trotter
    """Return information about the node.
2396 eb58f9b1 Guido Trotter

2397 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
2398 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
2399 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
2400 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
2401 34fbc862 Andrea Spadaccini
          - hv_version: the hypervisor version in the form (major, minor,
2402 34fbc862 Andrea Spadaccini
                        revision)
2403 eb58f9b1 Guido Trotter

2404 eb58f9b1 Guido Trotter
    """
2405 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
2406 4b9638dc Guido Trotter
    # FIXME: this is the global kvm version, but the actual version can be
2407 4b9638dc Guido Trotter
    # customized as an hv parameter. we should use the nodegroup's default kvm
2408 4b9638dc Guido Trotter
    # path parameter here.
2409 3b59ec02 Guido Trotter
    _, v_major, v_min, v_rev = self._GetKVMVersion(constants.KVM_PATH)
2410 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2411 34fbc862 Andrea Spadaccini
    return result
2412 eb58f9b1 Guido Trotter
2413 637ce7f9 Guido Trotter
  @classmethod
2414 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
2415 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
2416 eb58f9b1 Guido Trotter

2417 eb58f9b1 Guido Trotter
    """
2418 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2419 9d9bded1 Michael Hanselmann
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2420 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2421 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2422 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
2423 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2424 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2425 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
2426 55cc0a44 Michael Hanselmann
                                     host=instance.primary_node,
2427 052783ff Michael Hanselmann
                                     user=constants.SSH_CONSOLE_USER,
2428 55cc0a44 Michael Hanselmann
                                     command=cmd)
2429 3be34f57 Guido Trotter
2430 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2431 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2432 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
2433 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2434 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
2435 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
2436 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
2437 55cc0a44 Michael Hanselmann
                                     display=display)
2438 55cc0a44 Michael Hanselmann
2439 4d2cdb5a Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2440 4d2cdb5a Andrea Spadaccini
    if spice_bind:
2441 4d2cdb5a Andrea Spadaccini
      return objects.InstanceConsole(instance=instance.name,
2442 4d2cdb5a Andrea Spadaccini
                                     kind=constants.CONS_SPICE,
2443 4d2cdb5a Andrea Spadaccini
                                     host=spice_bind,
2444 4d2cdb5a Andrea Spadaccini
                                     port=instance.network_port)
2445 4d2cdb5a Andrea Spadaccini
2446 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
2447 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
2448 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
2449 55cc0a44 Michael Hanselmann
                                            instance.name))
2450 eb58f9b1 Guido Trotter
2451 eb58f9b1 Guido Trotter
  def Verify(self):
2452 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
2453 eb58f9b1 Guido Trotter

2454 cd04dfd2 Michael Hanselmann
    Check that the required binaries exist.
2455 cd04dfd2 Michael Hanselmann

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

2458 eb58f9b1 Guido Trotter
    """
2459 1f4b9d39 Iustin Pop
    msgs = []
2460 1f4b9d39 Iustin Pop
    # FIXME: this is the global kvm binary, but the actual path can be
2461 1f4b9d39 Iustin Pop
    # customized as an hv parameter; we should use the nodegroup's
2462 1f4b9d39 Iustin Pop
    # default kvm path parameter here.
2463 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
2464 1f4b9d39 Iustin Pop
      msgs.append("The KVM binary ('%s') does not exist" % constants.KVM_PATH)
2465 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2466 1f4b9d39 Iustin Pop
      msgs.append("The socat binary ('%s') does not exist" %
2467 1f4b9d39 Iustin Pop
                  constants.SOCAT_PATH)
2468 1f4b9d39 Iustin Pop
2469 1f4b9d39 Iustin Pop
    return self._FormatVerifyResults(msgs)
2470 14aa53cb Guido Trotter
2471 6b5605e8 Iustin Pop
  @classmethod
2472 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2473 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2474 6b5605e8 Iustin Pop

2475 6b5605e8 Iustin Pop
    @type hvparams:  dict
2476 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2477 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2478 6b5605e8 Iustin Pop

2479 6b5605e8 Iustin Pop
    """
2480 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2481 6b5605e8 Iustin Pop
2482 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
2483 df5ab9f0 Guido Trotter
    if kernel_path:
2484 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
2485 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
2486 205ab586 Iustin Pop
                                     " if a kernel is defined")
2487 6b5605e8 Iustin Pop
2488 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
2489 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
2490 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
2491 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
2492 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
2493 66d5dbef Guido Trotter
2494 14fd6c81 Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2495 14fd6c81 Guido Trotter
      serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2496 14fd6c81 Guido Trotter
      valid_speeds = constants.VALID_SERIAL_SPEEDS
2497 14fd6c81 Guido Trotter
      if not serial_speed or serial_speed not in valid_speeds:
2498 14fd6c81 Guido Trotter
        raise errors.HypervisorError("Invalid serial console speed, must be"
2499 14fd6c81 Guido Trotter
                                     " one of: %s" %
2500 14fd6c81 Guido Trotter
                                     utils.CommaJoin(valid_speeds))
2501 14fd6c81 Guido Trotter
2502 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2503 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
2504 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2505 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2506 835528af Iustin Pop
                                   " ISO path")
2507 f5118ade Iustin Pop
2508 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2509 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2510 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
2511 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
2512 d19d94db Guido Trotter
                                     " must be specified")
2513 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
2514 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
2515 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
2516 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
2517 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
2518 d19d94db Guido Trotter
2519 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2520 b451c4c7 Andrea Spadaccini
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2521 b1cb62bd Andrea Spadaccini
    if spice_bind:
2522 b1cb62bd Andrea Spadaccini
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2523 b1cb62bd Andrea Spadaccini
        # if an IP version is specified, the spice_bind parameter must be an
2524 b1cb62bd Andrea Spadaccini
        # IP of that family
2525 b1cb62bd Andrea Spadaccini
        if (netutils.IP4Address.IsValid(spice_bind) and
2526 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP4_VERSION):
2527 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv4 address (%s), but"
2528 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2529 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2530 b1cb62bd Andrea Spadaccini
2531 b1cb62bd Andrea Spadaccini
        if (netutils.IP6Address.IsValid(spice_bind) and
2532 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP6_VERSION):
2533 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv6 address (%s), but"
2534 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2535 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2536 b451c4c7 Andrea Spadaccini
    else:
2537 0e1b03b9 Andrea Spadaccini
      # All the other SPICE parameters depend on spice_bind being set. Raise an
2538 0e1b03b9 Andrea Spadaccini
      # error if any of them is set without it.
2539 07788a0b Michael Hanselmann
      for param in _SPICE_ADDITIONAL_PARAMS:
2540 0e1b03b9 Andrea Spadaccini
        if hvparams[param]:
2541 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: %s requires %s to be set" %
2542 0e1b03b9 Andrea Spadaccini
                                       (param, constants.HV_KVM_SPICE_BIND))
2543 b1cb62bd Andrea Spadaccini
2544 d19d94db Guido Trotter
  @classmethod
2545 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
2546 d19d94db Guido Trotter
    """Check the given parameters for validity.
2547 d19d94db Guido Trotter

2548 d19d94db Guido Trotter
    @type hvparams:  dict
2549 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2550 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2551 d19d94db Guido Trotter

2552 d19d94db Guido Trotter
    """
2553 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2554 d19d94db Guido Trotter
2555 82e3bf85 Dimitris Aragiorgis
    kvm_path = hvparams[constants.HV_KVM_PATH]
2556 82e3bf85 Dimitris Aragiorgis
2557 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2558 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2559 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2560 d19d94db Guido Trotter
      try:
2561 1feb39ec Guido Trotter
        pwd.getpwnam(username)
2562 d19d94db Guido Trotter
      except KeyError:
2563 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
2564 d19d94db Guido Trotter
                                     % username)
2565 d19d94db Guido Trotter
2566 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2567 b1cb62bd Andrea Spadaccini
    if spice_bind:
2568 b1cb62bd Andrea Spadaccini
      # only one of VNC and SPICE can be used currently.
2569 b1cb62bd Andrea Spadaccini
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2570 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("Both SPICE and VNC are configured, but"
2571 b1cb62bd Andrea Spadaccini
                                     " only one of them can be used at a"
2572 afa9bb2e Michael Hanselmann
                                     " given time")
2573 b1cb62bd Andrea Spadaccini
2574 3b59ec02 Guido Trotter
      # check that KVM supports SPICE
2575 6e043e60 Guido Trotter
      kvmhelp = cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP)
2576 0ad7f5d8 Guido Trotter
      if not cls._SPICE_RE.search(kvmhelp):
2577 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE is configured, but it is not"
2578 afa9bb2e Michael Hanselmann
                                     " supported according to 'kvm --help'")
2579 b1cb62bd Andrea Spadaccini
2580 b1cb62bd Andrea Spadaccini
      # if spice_bind is not an IP address, it must be a valid interface
2581 afa9bb2e Michael Hanselmann
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind) or
2582 afa9bb2e Michael Hanselmann
                       netutils.IP6Address.IsValid(spice_bind))
2583 b1cb62bd Andrea Spadaccini
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2584 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE: The %s parameter must be either"
2585 b1cb62bd Andrea Spadaccini
                                     " a valid IP address or interface name" %
2586 b1cb62bd Andrea Spadaccini
                                     constants.HV_KVM_SPICE_BIND)
2587 b1cb62bd Andrea Spadaccini
2588 82e3bf85 Dimitris Aragiorgis
    machine_version = hvparams[constants.HV_KVM_MACHINE_VERSION]
2589 82e3bf85 Dimitris Aragiorgis
    if machine_version:
2590 6e043e60 Guido Trotter
      output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2591 82e3bf85 Dimitris Aragiorgis
      if not cls._CHECK_MACHINE_VERSION_RE(machine_version).search(output):
2592 82e3bf85 Dimitris Aragiorgis
        raise errors.HypervisorError("Unsupported machine version: %s" %
2593 82e3bf85 Dimitris Aragiorgis
                                     machine_version)
2594 82e3bf85 Dimitris Aragiorgis
2595 f5118ade Iustin Pop
  @classmethod
2596 f5118ade Iustin Pop
  def PowercycleNode(cls):
2597 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
2598 f5118ade Iustin Pop

2599 f5118ade Iustin Pop
    """
2600 f5118ade Iustin Pop
    cls.LinuxPowercycle()