Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 3889f749

History | View | Annotate | Download (103 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 2615646c 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 97cd9092 Dimitris Aragiorgis
try:
46 97cd9092 Dimitris Aragiorgis
  import fdsend   # pylint: disable=F0401
47 97cd9092 Dimitris Aragiorgis
except ImportError:
48 97cd9092 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 18f16482 Dimitris Aragiorgis
_KVM_NETWORK_SCRIPT = pathutils.CONF_DIR + "/kvm-ifup-custom"
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 b8168679 Apollon Oikonomopoulos
IFF_ONE_QUEUE = 0x2000
75 199b2053 Apollon Oikonomopoulos
IFF_VNET_HDR = 0x4000
76 199b2053 Apollon Oikonomopoulos
77 07788a0b Michael Hanselmann
#: SPICE parameters which depend on L{constants.HV_KVM_SPICE_BIND}
78 07788a0b Michael Hanselmann
_SPICE_ADDITIONAL_PARAMS = frozenset([
79 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_IP_VERSION,
80 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_PASSWORD_FILE,
81 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR,
82 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_JPEG_IMG_COMPR,
83 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR,
84 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION,
85 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_USE_TLS,
86 07788a0b Michael Hanselmann
  ])
87 07788a0b Michael Hanselmann
88 2615646c Dimitris Aragiorgis
# Constant bitarray that reflects to a free pci slot
89 2615646c Dimitris Aragiorgis
# Use it with bitarray.search()
90 2615646c Dimitris Aragiorgis
_AVAILABLE_PCI_SLOT = bitarray("0")
91 2615646c Dimitris Aragiorgis
92 0fe22ad2 Dimitris Aragiorgis
# below constants show the format of runtime file
93 0fe22ad2 Dimitris Aragiorgis
# the nics are in second possition, while the disks in 4th (last)
94 41a878b5 Dimitris Aragiorgis
# moreover disk entries are stored as a list of in tuples
95 41a878b5 Dimitris Aragiorgis
# (L{objects.Disk}, link_name, uri)
96 0fe22ad2 Dimitris Aragiorgis
_KVM_NICS_RUNTIME_INDEX = 1
97 0fe22ad2 Dimitris Aragiorgis
_KVM_DISKS_RUNTIME_INDEX = 3
98 0fe22ad2 Dimitris Aragiorgis
_DEVICE_RUNTIME_INDEX = {
99 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK: _KVM_DISKS_RUNTIME_INDEX,
100 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC: _KVM_NICS_RUNTIME_INDEX
101 0fe22ad2 Dimitris Aragiorgis
  }
102 0fe22ad2 Dimitris Aragiorgis
_FIND_RUNTIME_ENTRY = {
103 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC:
104 0fe22ad2 Dimitris Aragiorgis
    lambda nic, kvm_nics: [n for n in kvm_nics if n.uuid == nic.uuid],
105 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK:
106 0fe22ad2 Dimitris Aragiorgis
    lambda disk, kvm_disks: [(d, l, u) for (d, l, u) in kvm_disks
107 0fe22ad2 Dimitris Aragiorgis
                             if d.uuid == disk.uuid]
108 0fe22ad2 Dimitris Aragiorgis
  }
109 0fe22ad2 Dimitris Aragiorgis
_RUNTIME_DEVICE = {
110 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC: lambda d: d,
111 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK: lambda (d, e, _): d
112 0fe22ad2 Dimitris Aragiorgis
  }
113 0fe22ad2 Dimitris Aragiorgis
_RUNTIME_ENTRY = {
114 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC: lambda d, e: d,
115 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK: lambda d, e: (d, e, None)
116 0fe22ad2 Dimitris Aragiorgis
  }
117 0fe22ad2 Dimitris Aragiorgis
118 d93e2477 Dimitris Aragiorgis
_MIGRATION_CAPS_DELIM = ":"
119 d93e2477 Dimitris Aragiorgis
120 0fe22ad2 Dimitris Aragiorgis
121 2615646c Dimitris Aragiorgis
def _GenerateDeviceKVMId(dev_type, dev):
122 2615646c Dimitris Aragiorgis
  """Helper function to generate a unique device name used by KVM
123 2615646c Dimitris Aragiorgis

124 2615646c Dimitris Aragiorgis
  QEMU monitor commands use names to identify devices. Here we use their pci
125 2615646c Dimitris Aragiorgis
  slot and a part of their UUID to name them. dev.pci might be None for old
126 2615646c Dimitris Aragiorgis
  devices in the cluster.
127 2615646c Dimitris Aragiorgis

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

134 2615646c Dimitris Aragiorgis
  """
135 2615646c Dimitris Aragiorgis
136 2615646c Dimitris Aragiorgis
  if not dev.pci:
137 2615646c Dimitris Aragiorgis
    raise errors.HotplugError("Hotplug is not supported for %s with UUID %s" %
138 2615646c Dimitris Aragiorgis
                              (dev_type, dev.uuid))
139 2615646c Dimitris Aragiorgis
140 2615646c Dimitris Aragiorgis
  return "%s-%s-pci-%d" % (dev_type.lower(), dev.uuid.split("-")[0], dev.pci)
141 2615646c Dimitris Aragiorgis
142 2615646c Dimitris Aragiorgis
143 d13fb3f1 Dimitris Aragiorgis
def _GetFreeSlot(slots, slot=None, reserve=False):
144 d13fb3f1 Dimitris Aragiorgis
  """Helper method to get first available slot in a bitarray
145 d13fb3f1 Dimitris Aragiorgis

146 d13fb3f1 Dimitris Aragiorgis
  @type slots: bitarray
147 d13fb3f1 Dimitris Aragiorgis
  @param slots: the bitarray to operate on
148 d13fb3f1 Dimitris Aragiorgis
  @type slot: integer
149 d13fb3f1 Dimitris Aragiorgis
  @param slot: if given we check whether the slot is free
150 d13fb3f1 Dimitris Aragiorgis
  @type reserve: boolean
151 d13fb3f1 Dimitris Aragiorgis
  @param reserve: whether to reserve the first available slot or not
152 d13fb3f1 Dimitris Aragiorgis
  @return: the idx of the (first) available slot
153 d13fb3f1 Dimitris Aragiorgis
  @raise errors.HotplugError: If all slots in a bitarray are occupied
154 d13fb3f1 Dimitris Aragiorgis
    or the given slot is not free.
155 2615646c Dimitris Aragiorgis

156 d13fb3f1 Dimitris Aragiorgis
  """
157 d13fb3f1 Dimitris Aragiorgis
  if slot is not None:
158 d13fb3f1 Dimitris Aragiorgis
    assert slot < len(slots)
159 d13fb3f1 Dimitris Aragiorgis
    if slots[slot]:
160 d13fb3f1 Dimitris Aragiorgis
      raise errors.HypervisorError("Slots %d occupied" % slot)
161 2615646c Dimitris Aragiorgis
162 d13fb3f1 Dimitris Aragiorgis
  else:
163 d13fb3f1 Dimitris Aragiorgis
    avail = slots.search(_AVAILABLE_PCI_SLOT, 1)
164 d13fb3f1 Dimitris Aragiorgis
    if not avail:
165 d13fb3f1 Dimitris Aragiorgis
      raise errors.HypervisorError("All slots occupied")
166 2615646c Dimitris Aragiorgis
167 d13fb3f1 Dimitris Aragiorgis
    slot = int(avail[0])
168 d13fb3f1 Dimitris Aragiorgis
169 d13fb3f1 Dimitris Aragiorgis
  if reserve:
170 d13fb3f1 Dimitris Aragiorgis
    slots[slot] = True
171 2615646c Dimitris Aragiorgis
172 d13fb3f1 Dimitris Aragiorgis
  return slot
173 2615646c Dimitris Aragiorgis
174 2615646c Dimitris Aragiorgis
175 0fe22ad2 Dimitris Aragiorgis
def _GetExistingDeviceInfo(dev_type, device, runtime):
176 0fe22ad2 Dimitris Aragiorgis
  """Helper function to get an existing device inside the runtime file
177 0fe22ad2 Dimitris Aragiorgis

178 0fe22ad2 Dimitris Aragiorgis
  Used when an instance is running. Load kvm runtime file and search
179 0fe22ad2 Dimitris Aragiorgis
  for a device based on its type and uuid.
180 0fe22ad2 Dimitris Aragiorgis

181 0fe22ad2 Dimitris Aragiorgis
  @type dev_type: sting
182 0fe22ad2 Dimitris Aragiorgis
  @param dev_type: device type of param dev
183 0fe22ad2 Dimitris Aragiorgis
  @type device: L{objects.Disk} or L{objects.NIC}
184 0fe22ad2 Dimitris Aragiorgis
  @param device: the device object for which we generate a kvm name
185 0fe22ad2 Dimitris Aragiorgis
  @type runtime: tuple (cmd, nics, hvparams, disks)
186 0fe22ad2 Dimitris Aragiorgis
  @param runtime: the runtime data to search for the device
187 0fe22ad2 Dimitris Aragiorgis
  @raise errors.HotplugError: in case the requested device does not
188 0fe22ad2 Dimitris Aragiorgis
    exist (e.g. device has been added without --hotplug option) or
189 0fe22ad2 Dimitris Aragiorgis
    device info has not pci slot (e.g. old devices in the cluster)
190 0fe22ad2 Dimitris Aragiorgis

191 0fe22ad2 Dimitris Aragiorgis
  """
192 0fe22ad2 Dimitris Aragiorgis
  index = _DEVICE_RUNTIME_INDEX[dev_type]
193 0fe22ad2 Dimitris Aragiorgis
  found = _FIND_RUNTIME_ENTRY[dev_type](device, runtime[index])
194 0fe22ad2 Dimitris Aragiorgis
  if not found:
195 0fe22ad2 Dimitris Aragiorgis
    raise errors.HotplugError("Cannot find runtime info for %s with UUID %s" %
196 0fe22ad2 Dimitris Aragiorgis
                              (dev_type, device.uuid))
197 0fe22ad2 Dimitris Aragiorgis
198 0fe22ad2 Dimitris Aragiorgis
  return found[0]
199 0fe22ad2 Dimitris Aragiorgis
200 0fe22ad2 Dimitris Aragiorgis
201 e8cbe174 Dimitris Aragiorgis
def _UpgradeSerializedRuntime(serialized_runtime):
202 e8cbe174 Dimitris Aragiorgis
  """Upgrade runtime data
203 e8cbe174 Dimitris Aragiorgis

204 e8cbe174 Dimitris Aragiorgis
  Remove any deprecated fields or change the format of the data.
205 e8cbe174 Dimitris Aragiorgis
  The runtime files are not upgraded when Ganeti is upgraded, so the required
206 e8cbe174 Dimitris Aragiorgis
  modification have to be performed here.
207 0fe22ad2 Dimitris Aragiorgis

208 0fe22ad2 Dimitris Aragiorgis
  @type serialized_runtime: string
209 0fe22ad2 Dimitris Aragiorgis
  @param serialized_runtime: raw text data read from actual runtime file
210 e8cbe174 Dimitris Aragiorgis
  @return: (cmd, nic dicts, hvparams, bdev dicts)
211 e8cbe174 Dimitris Aragiorgis
  @rtype: tuple
212 0fe22ad2 Dimitris Aragiorgis

213 0fe22ad2 Dimitris Aragiorgis
  """
214 0fe22ad2 Dimitris Aragiorgis
  loaded_runtime = serializer.Load(serialized_runtime)
215 e8cbe174 Dimitris Aragiorgis
  kvm_cmd, serialized_nics, hvparams = loaded_runtime[:3]
216 e8cbe174 Dimitris Aragiorgis
  if len(loaded_runtime) >= 4:
217 e8cbe174 Dimitris Aragiorgis
    serialized_disks = loaded_runtime[3]
218 0fe22ad2 Dimitris Aragiorgis
  else:
219 e8cbe174 Dimitris Aragiorgis
    serialized_disks = []
220 e8cbe174 Dimitris Aragiorgis
221 e8cbe174 Dimitris Aragiorgis
  for nic in serialized_nics:
222 e8cbe174 Dimitris Aragiorgis
    # Add a dummy uuid slot if an pre-2.8 NIC is found
223 e8cbe174 Dimitris Aragiorgis
    if "uuid" not in nic:
224 e8cbe174 Dimitris Aragiorgis
      nic["uuid"] = utils.NewUUID()
225 e8cbe174 Dimitris Aragiorgis
226 e8cbe174 Dimitris Aragiorgis
  return kvm_cmd, serialized_nics, hvparams, serialized_disks
227 e8cbe174 Dimitris Aragiorgis
228 0fe22ad2 Dimitris Aragiorgis
229 e8cbe174 Dimitris Aragiorgis
def _AnalyzeSerializedRuntime(serialized_runtime):
230 e8cbe174 Dimitris Aragiorgis
  """Return runtime entries for a serialized runtime file
231 e8cbe174 Dimitris Aragiorgis

232 e8cbe174 Dimitris Aragiorgis
  @type serialized_runtime: string
233 e8cbe174 Dimitris Aragiorgis
  @param serialized_runtime: raw text data read from actual runtime file
234 e8cbe174 Dimitris Aragiorgis
  @return: (cmd, nics, hvparams, bdevs)
235 e8cbe174 Dimitris Aragiorgis
  @rtype: tuple
236 e8cbe174 Dimitris Aragiorgis

237 e8cbe174 Dimitris Aragiorgis
  """
238 e8cbe174 Dimitris Aragiorgis
  kvm_cmd, serialized_nics, hvparams, serialized_disks = \
239 e8cbe174 Dimitris Aragiorgis
    _UpgradeSerializedRuntime(serialized_runtime)
240 0fe22ad2 Dimitris Aragiorgis
  kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
241 41a878b5 Dimitris Aragiorgis
  kvm_disks = [(objects.Disk.FromDict(sdisk), link, uri)
242 41a878b5 Dimitris Aragiorgis
               for sdisk, link, uri in serialized_disks]
243 0fe22ad2 Dimitris Aragiorgis
244 41a878b5 Dimitris Aragiorgis
  return (kvm_cmd, kvm_nics, hvparams, kvm_disks)
245 0fe22ad2 Dimitris Aragiorgis
246 199b2053 Apollon Oikonomopoulos
247 ea2bcb82 Michael Hanselmann
def _GetTunFeatures(fd, _ioctl=fcntl.ioctl):
248 ea2bcb82 Michael Hanselmann
  """Retrieves supported TUN features from file descriptor.
249 ea2bcb82 Michael Hanselmann

250 ea2bcb82 Michael Hanselmann
  @see: L{_ProbeTapVnetHdr}
251 ea2bcb82 Michael Hanselmann

252 ea2bcb82 Michael Hanselmann
  """
253 ea2bcb82 Michael Hanselmann
  req = struct.pack("I", 0)
254 ea2bcb82 Michael Hanselmann
  try:
255 ea2bcb82 Michael Hanselmann
    buf = _ioctl(fd, TUNGETFEATURES, req)
256 ea2bcb82 Michael Hanselmann
  except EnvironmentError, err:
257 cfc24646 Iustin Pop
    logging.warning("ioctl(TUNGETFEATURES) failed: %s", err)
258 ea2bcb82 Michael Hanselmann
    return None
259 ea2bcb82 Michael Hanselmann
  else:
260 ea2bcb82 Michael Hanselmann
    (flags, ) = struct.unpack("I", buf)
261 ea2bcb82 Michael Hanselmann
    return flags
262 ea2bcb82 Michael Hanselmann
263 ea2bcb82 Michael Hanselmann
264 ea2bcb82 Michael Hanselmann
def _ProbeTapVnetHdr(fd, _features_fn=_GetTunFeatures):
265 199b2053 Apollon Oikonomopoulos
  """Check whether to enable the IFF_VNET_HDR flag.
266 199b2053 Apollon Oikonomopoulos

267 199b2053 Apollon Oikonomopoulos
  To do this, _all_ of the following conditions must be met:
268 199b2053 Apollon Oikonomopoulos
   1. TUNGETFEATURES ioctl() *must* be implemented
269 199b2053 Apollon Oikonomopoulos
   2. TUNGETFEATURES ioctl() result *must* contain the IFF_VNET_HDR flag
270 199b2053 Apollon Oikonomopoulos
   3. TUNGETIFF ioctl() *must* be implemented; reading the kernel code in
271 199b2053 Apollon Oikonomopoulos
      drivers/net/tun.c there is no way to test this until after the tap device
272 199b2053 Apollon Oikonomopoulos
      has been created using TUNSETIFF, and there is no way to change the
273 199b2053 Apollon Oikonomopoulos
      IFF_VNET_HDR flag after creating the interface, catch-22! However both
274 199b2053 Apollon Oikonomopoulos
      TUNGETIFF and TUNGETFEATURES were introduced in kernel version 2.6.27,
275 199b2053 Apollon Oikonomopoulos
      thus we can expect TUNGETIFF to be present if TUNGETFEATURES is.
276 199b2053 Apollon Oikonomopoulos

277 199b2053 Apollon Oikonomopoulos
   @type fd: int
278 199b2053 Apollon Oikonomopoulos
   @param fd: the file descriptor of /dev/net/tun
279 199b2053 Apollon Oikonomopoulos

280 199b2053 Apollon Oikonomopoulos
  """
281 ea2bcb82 Michael Hanselmann
  flags = _features_fn(fd)
282 199b2053 Apollon Oikonomopoulos
283 ea2bcb82 Michael Hanselmann
  if flags is None:
284 ea2bcb82 Michael Hanselmann
    # Not supported
285 199b2053 Apollon Oikonomopoulos
    return False
286 199b2053 Apollon Oikonomopoulos
287 ea2bcb82 Michael Hanselmann
  result = bool(flags & IFF_VNET_HDR)
288 ea2bcb82 Michael Hanselmann
289 ea2bcb82 Michael Hanselmann
  if not result:
290 ea2bcb82 Michael Hanselmann
    logging.warning("Kernel does not support IFF_VNET_HDR, not enabling")
291 ea2bcb82 Michael Hanselmann
292 ea2bcb82 Michael Hanselmann
  return result
293 ea2bcb82 Michael Hanselmann
294 199b2053 Apollon Oikonomopoulos
295 199b2053 Apollon Oikonomopoulos
def _OpenTap(vnet_hdr=True):
296 199b2053 Apollon Oikonomopoulos
  """Open a new tap device and return its file descriptor.
297 199b2053 Apollon Oikonomopoulos

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

301 199b2053 Apollon Oikonomopoulos
  @type vnet_hdr: boolean
302 199b2053 Apollon Oikonomopoulos
  @param vnet_hdr: Enable the VNET Header
303 199b2053 Apollon Oikonomopoulos
  @return: (ifname, tapfd)
304 199b2053 Apollon Oikonomopoulos
  @rtype: tuple
305 199b2053 Apollon Oikonomopoulos

306 199b2053 Apollon Oikonomopoulos
  """
307 199b2053 Apollon Oikonomopoulos
  try:
308 199b2053 Apollon Oikonomopoulos
    tapfd = os.open("/dev/net/tun", os.O_RDWR)
309 199b2053 Apollon Oikonomopoulos
  except EnvironmentError:
310 199b2053 Apollon Oikonomopoulos
    raise errors.HypervisorError("Failed to open /dev/net/tun")
311 199b2053 Apollon Oikonomopoulos
312 b8168679 Apollon Oikonomopoulos
  flags = IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE
313 199b2053 Apollon Oikonomopoulos
314 199b2053 Apollon Oikonomopoulos
  if vnet_hdr and _ProbeTapVnetHdr(tapfd):
315 199b2053 Apollon Oikonomopoulos
    flags |= IFF_VNET_HDR
316 199b2053 Apollon Oikonomopoulos
317 199b2053 Apollon Oikonomopoulos
  # The struct ifreq ioctl request (see netdevice(7))
318 199b2053 Apollon Oikonomopoulos
  ifr = struct.pack("16sh", "", flags)
319 199b2053 Apollon Oikonomopoulos
320 199b2053 Apollon Oikonomopoulos
  try:
321 199b2053 Apollon Oikonomopoulos
    res = fcntl.ioctl(tapfd, TUNSETIFF, ifr)
322 6f1e1921 Michael Hanselmann
  except EnvironmentError, err:
323 6f1e1921 Michael Hanselmann
    raise errors.HypervisorError("Failed to allocate a new TAP device: %s" %
324 6f1e1921 Michael Hanselmann
                                 err)
325 199b2053 Apollon Oikonomopoulos
326 199b2053 Apollon Oikonomopoulos
  # Get the interface name from the ioctl
327 199b2053 Apollon Oikonomopoulos
  ifname = struct.unpack("16sh", res)[0].strip("\x00")
328 199b2053 Apollon Oikonomopoulos
  return (ifname, tapfd)
329 199b2053 Apollon Oikonomopoulos
330 748e4b5a Michael Hanselmann
331 91c10532 Andrea Spadaccini
class QmpMessage:
332 91c10532 Andrea Spadaccini
  """QEMU Messaging Protocol (QMP) message.
333 91c10532 Andrea Spadaccini

334 91c10532 Andrea Spadaccini
  """
335 91c10532 Andrea Spadaccini
  def __init__(self, data):
336 91c10532 Andrea Spadaccini
    """Creates a new QMP message based on the passed data.
337 91c10532 Andrea Spadaccini

338 91c10532 Andrea Spadaccini
    """
339 91c10532 Andrea Spadaccini
    if not isinstance(data, dict):
340 91c10532 Andrea Spadaccini
      raise TypeError("QmpMessage must be initialized with a dict")
341 91c10532 Andrea Spadaccini
342 91c10532 Andrea Spadaccini
    self.data = data
343 91c10532 Andrea Spadaccini
344 91c10532 Andrea Spadaccini
  def __getitem__(self, field_name):
345 91c10532 Andrea Spadaccini
    """Get the value of the required field if present, or None.
346 91c10532 Andrea Spadaccini

347 91c10532 Andrea Spadaccini
    Overrides the [] operator to provide access to the message data,
348 91c10532 Andrea Spadaccini
    returning None if the required item is not in the message
349 91c10532 Andrea Spadaccini
    @return: the value of the field_name field, or None if field_name
350 91c10532 Andrea Spadaccini
             is not contained in the message
351 91c10532 Andrea Spadaccini

352 91c10532 Andrea Spadaccini
    """
353 9b87c2cf Michael Hanselmann
    return self.data.get(field_name, None)
354 91c10532 Andrea Spadaccini
355 91c10532 Andrea Spadaccini
  def __setitem__(self, field_name, field_value):
356 91c10532 Andrea Spadaccini
    """Set the value of the required field_name to field_value.
357 91c10532 Andrea Spadaccini

358 91c10532 Andrea Spadaccini
    """
359 91c10532 Andrea Spadaccini
    self.data[field_name] = field_value
360 91c10532 Andrea Spadaccini
361 5e34123e Michele Tartara
  def __len__(self):
362 5e34123e Michele Tartara
    """Return the number of fields stored in this QmpMessage.
363 5e34123e Michele Tartara

364 5e34123e Michele Tartara
    """
365 5e34123e Michele Tartara
    return len(self.data)
366 5e34123e Michele Tartara
367 5e34123e Michele Tartara
  def __delitem__(self, key):
368 5e34123e Michele Tartara
    """Delete the specified element from the QmpMessage.
369 5e34123e Michele Tartara

370 5e34123e Michele Tartara
    """
371 5e34123e Michele Tartara
    del(self.data[key])
372 5e34123e Michele Tartara
373 91c10532 Andrea Spadaccini
  @staticmethod
374 91c10532 Andrea Spadaccini
  def BuildFromJsonString(json_string):
375 91c10532 Andrea Spadaccini
    """Build a QmpMessage from a JSON encoded string.
376 91c10532 Andrea Spadaccini

377 91c10532 Andrea Spadaccini
    @type json_string: str
378 91c10532 Andrea Spadaccini
    @param json_string: JSON string representing the message
379 91c10532 Andrea Spadaccini
    @rtype: L{QmpMessage}
380 91c10532 Andrea Spadaccini
    @return: a L{QmpMessage} built from json_string
381 91c10532 Andrea Spadaccini

382 91c10532 Andrea Spadaccini
    """
383 91c10532 Andrea Spadaccini
    # Parse the string
384 91c10532 Andrea Spadaccini
    data = serializer.LoadJson(json_string)
385 91c10532 Andrea Spadaccini
    return QmpMessage(data)
386 91c10532 Andrea Spadaccini
387 91c10532 Andrea Spadaccini
  def __str__(self):
388 a182a3ed Michael Hanselmann
    # The protocol expects the JSON object to be sent as a single line.
389 a182a3ed Michael Hanselmann
    return serializer.DumpJson(self.data)
390 91c10532 Andrea Spadaccini
391 91c10532 Andrea Spadaccini
  def __eq__(self, other):
392 91c10532 Andrea Spadaccini
    # When comparing two QmpMessages, we are interested in comparing
393 91c10532 Andrea Spadaccini
    # their internal representation of the message data
394 91c10532 Andrea Spadaccini
    return self.data == other.data
395 91c10532 Andrea Spadaccini
396 91c10532 Andrea Spadaccini
397 cad837b9 Dimitris Aragiorgis
class MonitorSocket(object):
398 91c10532 Andrea Spadaccini
  _SOCKET_TIMEOUT = 5
399 91c10532 Andrea Spadaccini
400 91c10532 Andrea Spadaccini
  def __init__(self, monitor_filename):
401 cad837b9 Dimitris Aragiorgis
    """Instantiates the MonitorSocket object.
402 91c10532 Andrea Spadaccini

403 91c10532 Andrea Spadaccini
    @type monitor_filename: string
404 91c10532 Andrea Spadaccini
    @param monitor_filename: the filename of the UNIX raw socket on which the
405 cad837b9 Dimitris Aragiorgis
                             monitor (QMP or simple one) is listening
406 91c10532 Andrea Spadaccini

407 91c10532 Andrea Spadaccini
    """
408 91c10532 Andrea Spadaccini
    self.monitor_filename = monitor_filename
409 91c10532 Andrea Spadaccini
    self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
410 91c10532 Andrea Spadaccini
    # We want to fail if the server doesn't send a complete message
411 91c10532 Andrea Spadaccini
    # in a reasonable amount of time
412 91c10532 Andrea Spadaccini
    self.sock.settimeout(self._SOCKET_TIMEOUT)
413 91c10532 Andrea Spadaccini
    self._connected = False
414 91c10532 Andrea Spadaccini
415 fc84cd5d Guido Trotter
  def _check_socket(self):
416 fc84cd5d Guido Trotter
    sock_stat = None
417 fc84cd5d Guido Trotter
    try:
418 fc84cd5d Guido Trotter
      sock_stat = os.stat(self.monitor_filename)
419 fc84cd5d Guido Trotter
    except EnvironmentError, err:
420 fc84cd5d Guido Trotter
      if err.errno == errno.ENOENT:
421 cad837b9 Dimitris Aragiorgis
        raise errors.HypervisorError("No monitor socket found")
422 fc84cd5d Guido Trotter
      else:
423 cad837b9 Dimitris Aragiorgis
        raise errors.HypervisorError("Error checking monitor socket: %s",
424 fc84cd5d Guido Trotter
                                     utils.ErrnoOrStr(err))
425 fc84cd5d Guido Trotter
    if not stat.S_ISSOCK(sock_stat.st_mode):
426 cad837b9 Dimitris Aragiorgis
      raise errors.HypervisorError("Monitor socket is not a socket")
427 fc84cd5d Guido Trotter
428 91c10532 Andrea Spadaccini
  def _check_connection(self):
429 91c10532 Andrea Spadaccini
    """Make sure that the connection is established.
430 91c10532 Andrea Spadaccini

431 91c10532 Andrea Spadaccini
    """
432 91c10532 Andrea Spadaccini
    if not self._connected:
433 cad837b9 Dimitris Aragiorgis
      raise errors.ProgrammerError("To use a MonitorSocket you need to first"
434 91c10532 Andrea Spadaccini
                                   " invoke connect() on it")
435 91c10532 Andrea Spadaccini
436 91c10532 Andrea Spadaccini
  def connect(self):
437 cad837b9 Dimitris Aragiorgis
    """Connects to the monitor.
438 91c10532 Andrea Spadaccini

439 cad837b9 Dimitris Aragiorgis
    Connects to the UNIX socket
440 91c10532 Andrea Spadaccini

441 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
442 91c10532 Andrea Spadaccini

443 91c10532 Andrea Spadaccini
    """
444 fc84cd5d Guido Trotter
    if self._connected:
445 fc84cd5d Guido Trotter
      raise errors.ProgrammerError("Cannot connect twice")
446 fc84cd5d Guido Trotter
447 fc84cd5d Guido Trotter
    self._check_socket()
448 fc84cd5d Guido Trotter
449 fc84cd5d Guido Trotter
    # Check file existance/stuff
450 fc84cd5d Guido Trotter
    try:
451 fc84cd5d Guido Trotter
      self.sock.connect(self.monitor_filename)
452 fc84cd5d Guido Trotter
    except EnvironmentError:
453 fc84cd5d Guido Trotter
      raise errors.HypervisorError("Can't connect to qmp socket")
454 91c10532 Andrea Spadaccini
    self._connected = True
455 91c10532 Andrea Spadaccini
456 cad837b9 Dimitris Aragiorgis
  def close(self):
457 cad837b9 Dimitris Aragiorgis
    """Closes the socket
458 cad837b9 Dimitris Aragiorgis

459 cad837b9 Dimitris Aragiorgis
    It cannot be used after this call.
460 cad837b9 Dimitris Aragiorgis

461 cad837b9 Dimitris Aragiorgis
    """
462 cad837b9 Dimitris Aragiorgis
    self.sock.close()
463 cad837b9 Dimitris Aragiorgis
464 cad837b9 Dimitris Aragiorgis
465 cad837b9 Dimitris Aragiorgis
class QmpConnection(MonitorSocket):
466 cad837b9 Dimitris Aragiorgis
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
467 cad837b9 Dimitris Aragiorgis

468 cad837b9 Dimitris Aragiorgis
  """
469 cad837b9 Dimitris Aragiorgis
  _FIRST_MESSAGE_KEY = "QMP"
470 cad837b9 Dimitris Aragiorgis
  _EVENT_KEY = "event"
471 cad837b9 Dimitris Aragiorgis
  _ERROR_KEY = "error"
472 cad837b9 Dimitris Aragiorgis
  _RETURN_KEY = RETURN_KEY = "return"
473 cad837b9 Dimitris Aragiorgis
  _ACTUAL_KEY = ACTUAL_KEY = "actual"
474 cad837b9 Dimitris Aragiorgis
  _ERROR_CLASS_KEY = "class"
475 cad837b9 Dimitris Aragiorgis
  _ERROR_DESC_KEY = "desc"
476 cad837b9 Dimitris Aragiorgis
  _EXECUTE_KEY = "execute"
477 cad837b9 Dimitris Aragiorgis
  _ARGUMENTS_KEY = "arguments"
478 cad837b9 Dimitris Aragiorgis
  _CAPABILITIES_COMMAND = "qmp_capabilities"
479 cad837b9 Dimitris Aragiorgis
  _MESSAGE_END_TOKEN = "\r\n"
480 cad837b9 Dimitris Aragiorgis
481 cad837b9 Dimitris Aragiorgis
  def __init__(self, monitor_filename):
482 cad837b9 Dimitris Aragiorgis
    super(QmpConnection, self).__init__(monitor_filename)
483 cad837b9 Dimitris Aragiorgis
    self._buf = ""
484 cad837b9 Dimitris Aragiorgis
485 cad837b9 Dimitris Aragiorgis
  def connect(self):
486 cad837b9 Dimitris Aragiorgis
    """Connects to the QMP monitor.
487 cad837b9 Dimitris Aragiorgis

488 cad837b9 Dimitris Aragiorgis
    Connects to the UNIX socket and makes sure that we can actually send and
489 cad837b9 Dimitris Aragiorgis
    receive data to the kvm instance via QMP.
490 cad837b9 Dimitris Aragiorgis

491 cad837b9 Dimitris Aragiorgis
    @raise errors.HypervisorError: when there are communication errors
492 cad837b9 Dimitris Aragiorgis
    @raise errors.ProgrammerError: when there are data serialization errors
493 cad837b9 Dimitris Aragiorgis

494 cad837b9 Dimitris Aragiorgis
    """
495 cad837b9 Dimitris Aragiorgis
    super(QmpConnection, self).connect()
496 91c10532 Andrea Spadaccini
    # Check if we receive a correct greeting message from the server
497 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 2.2)
498 91c10532 Andrea Spadaccini
    greeting = self._Recv()
499 91c10532 Andrea Spadaccini
    if not greeting[self._FIRST_MESSAGE_KEY]:
500 91c10532 Andrea Spadaccini
      self._connected = False
501 afa9bb2e Michael Hanselmann
      raise errors.HypervisorError("kvm: QMP communication error (wrong"
502 91c10532 Andrea Spadaccini
                                   " server greeting")
503 91c10532 Andrea Spadaccini
504 7231ca26 Dimitris Aragiorgis
    # This is needed because QMP can return more than one greetings
505 7231ca26 Dimitris Aragiorgis
    # see https://groups.google.com/d/msg/ganeti-devel/gZYcvHKDooU/SnukC8dgS5AJ
506 7231ca26 Dimitris Aragiorgis
    self._buf = ""
507 7231ca26 Dimitris Aragiorgis
508 91c10532 Andrea Spadaccini
    # Let's put the monitor in command mode using the qmp_capabilities
509 91c10532 Andrea Spadaccini
    # command, or else no command will be executable.
510 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 4)
511 91c10532 Andrea Spadaccini
    self.Execute(self._CAPABILITIES_COMMAND)
512 91c10532 Andrea Spadaccini
513 91c10532 Andrea Spadaccini
  def _ParseMessage(self, buf):
514 91c10532 Andrea Spadaccini
    """Extract and parse a QMP message from the given buffer.
515 91c10532 Andrea Spadaccini

516 91c10532 Andrea Spadaccini
    Seeks for a QMP message in the given buf. If found, it parses it and
517 91c10532 Andrea Spadaccini
    returns it together with the rest of the characters in the buf.
518 91c10532 Andrea Spadaccini
    If no message is found, returns None and the whole buffer.
519 91c10532 Andrea Spadaccini

520 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
521 91c10532 Andrea Spadaccini

522 91c10532 Andrea Spadaccini
    """
523 91c10532 Andrea Spadaccini
    message = None
524 91c10532 Andrea Spadaccini
    # Check if we got the message end token (CRLF, as per the QEMU Protocol
525 91c10532 Andrea Spadaccini
    # Specification 0.1 - Section 2.1.1)
526 91c10532 Andrea Spadaccini
    pos = buf.find(self._MESSAGE_END_TOKEN)
527 91c10532 Andrea Spadaccini
    if pos >= 0:
528 91c10532 Andrea Spadaccini
      try:
529 91c10532 Andrea Spadaccini
        message = QmpMessage.BuildFromJsonString(buf[:pos + 1])
530 91c10532 Andrea Spadaccini
      except Exception, err:
531 91c10532 Andrea Spadaccini
        raise errors.ProgrammerError("QMP data serialization error: %s" % err)
532 91c10532 Andrea Spadaccini
      buf = buf[pos + 1:]
533 91c10532 Andrea Spadaccini
534 91c10532 Andrea Spadaccini
    return (message, buf)
535 91c10532 Andrea Spadaccini
536 91c10532 Andrea Spadaccini
  def _Recv(self):
537 91c10532 Andrea Spadaccini
    """Receives a message from QMP and decodes the received JSON object.
538 91c10532 Andrea Spadaccini

539 91c10532 Andrea Spadaccini
    @rtype: QmpMessage
540 91c10532 Andrea Spadaccini
    @return: the received message
541 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
542 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
543 91c10532 Andrea Spadaccini

544 91c10532 Andrea Spadaccini
    """
545 91c10532 Andrea Spadaccini
    self._check_connection()
546 91c10532 Andrea Spadaccini
547 91c10532 Andrea Spadaccini
    # Check if there is already a message in the buffer
548 91c10532 Andrea Spadaccini
    (message, self._buf) = self._ParseMessage(self._buf)
549 91c10532 Andrea Spadaccini
    if message:
550 91c10532 Andrea Spadaccini
      return message
551 91c10532 Andrea Spadaccini
552 91c10532 Andrea Spadaccini
    recv_buffer = StringIO.StringIO(self._buf)
553 91c10532 Andrea Spadaccini
    recv_buffer.seek(len(self._buf))
554 91c10532 Andrea Spadaccini
    try:
555 91c10532 Andrea Spadaccini
      while True:
556 91c10532 Andrea Spadaccini
        data = self.sock.recv(4096)
557 91c10532 Andrea Spadaccini
        if not data:
558 91c10532 Andrea Spadaccini
          break
559 91c10532 Andrea Spadaccini
        recv_buffer.write(data)
560 91c10532 Andrea Spadaccini
561 91c10532 Andrea Spadaccini
        (message, self._buf) = self._ParseMessage(recv_buffer.getvalue())
562 91c10532 Andrea Spadaccini
        if message:
563 91c10532 Andrea Spadaccini
          return message
564 91c10532 Andrea Spadaccini
565 91c10532 Andrea Spadaccini
    except socket.timeout, err:
566 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while receiving a QMP message: "
567 91c10532 Andrea Spadaccini
                                   "%s" % (err))
568 91c10532 Andrea Spadaccini
    except socket.error, err:
569 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to receive data from KVM using the"
570 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
571 91c10532 Andrea Spadaccini
572 91c10532 Andrea Spadaccini
  def _Send(self, message):
573 91c10532 Andrea Spadaccini
    """Encodes and sends a message to KVM using QMP.
574 91c10532 Andrea Spadaccini

575 91c10532 Andrea Spadaccini
    @type message: QmpMessage
576 91c10532 Andrea Spadaccini
    @param message: message to send to KVM
577 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
578 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
579 91c10532 Andrea Spadaccini

580 91c10532 Andrea Spadaccini
    """
581 91c10532 Andrea Spadaccini
    self._check_connection()
582 91c10532 Andrea Spadaccini
    try:
583 91c10532 Andrea Spadaccini
      message_str = str(message)
584 91c10532 Andrea Spadaccini
    except Exception, err:
585 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("QMP data deserialization error: %s" % err)
586 91c10532 Andrea Spadaccini
587 91c10532 Andrea Spadaccini
    try:
588 91c10532 Andrea Spadaccini
      self.sock.sendall(message_str)
589 91c10532 Andrea Spadaccini
    except socket.timeout, err:
590 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while sending a QMP message: "
591 91c10532 Andrea Spadaccini
                                   "%s (%s)" % (err.string, err.errno))
592 91c10532 Andrea Spadaccini
    except socket.error, err:
593 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to send data from KVM using the"
594 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
595 91c10532 Andrea Spadaccini
596 91c10532 Andrea Spadaccini
  def Execute(self, command, arguments=None):
597 91c10532 Andrea Spadaccini
    """Executes a QMP command and returns the response of the server.
598 91c10532 Andrea Spadaccini

599 91c10532 Andrea Spadaccini
    @type command: str
600 91c10532 Andrea Spadaccini
    @param command: the command to execute
601 91c10532 Andrea Spadaccini
    @type arguments: dict
602 91c10532 Andrea Spadaccini
    @param arguments: dictionary of arguments to be passed to the command
603 91c10532 Andrea Spadaccini
    @rtype: dict
604 91c10532 Andrea Spadaccini
    @return: dictionary representing the received JSON object
605 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
606 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
607 91c10532 Andrea Spadaccini

608 91c10532 Andrea Spadaccini
    """
609 91c10532 Andrea Spadaccini
    self._check_connection()
610 91c10532 Andrea Spadaccini
    message = QmpMessage({self._EXECUTE_KEY: command})
611 91c10532 Andrea Spadaccini
    if arguments:
612 91c10532 Andrea Spadaccini
      message[self._ARGUMENTS_KEY] = arguments
613 91c10532 Andrea Spadaccini
    self._Send(message)
614 91c10532 Andrea Spadaccini
615 91c10532 Andrea Spadaccini
    # Events can occur between the sending of the command and the reception
616 91c10532 Andrea Spadaccini
    # of the response, so we need to filter out messages with the event key.
617 91c10532 Andrea Spadaccini
    while True:
618 91c10532 Andrea Spadaccini
      response = self._Recv()
619 91c10532 Andrea Spadaccini
      err = response[self._ERROR_KEY]
620 91c10532 Andrea Spadaccini
      if err:
621 91c10532 Andrea Spadaccini
        raise errors.HypervisorError("kvm: error executing the %s"
622 02d17fe3 Dimitris Aragiorgis
                                     " command: %s (%s):" %
623 91c10532 Andrea Spadaccini
                                     (command,
624 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DESC_KEY],
625 02d17fe3 Dimitris Aragiorgis
                                      err[self._ERROR_CLASS_KEY]))
626 91c10532 Andrea Spadaccini
627 91c10532 Andrea Spadaccini
      elif not response[self._EVENT_KEY]:
628 91c10532 Andrea Spadaccini
        return response
629 91c10532 Andrea Spadaccini
630 91c10532 Andrea Spadaccini
631 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
632 65107a2f Michael Hanselmann
  """KVM hypervisor interface
633 65107a2f Michael Hanselmann

634 65107a2f Michael Hanselmann
  """
635 d271c6fd Iustin Pop
  CAN_MIGRATE = True
636 eb58f9b1 Guido Trotter
637 9d9bded1 Michael Hanselmann
  _ROOT_DIR = pathutils.RUN_DIR + "/kvm-hypervisor"
638 a1d79fc6 Guido Trotter
  _PIDS_DIR = _ROOT_DIR + "/pid" # contains live instances pids
639 7548396c Guido Trotter
  _UIDS_DIR = _ROOT_DIR + "/uid" # contains instances reserved uids
640 a1d79fc6 Guido Trotter
  _CTRL_DIR = _ROOT_DIR + "/ctrl" # contains instances control sockets
641 a1d79fc6 Guido Trotter
  _CONF_DIR = _ROOT_DIR + "/conf" # contains instances startup data
642 5d9bfd87 Apollon Oikonomopoulos
  _NICS_DIR = _ROOT_DIR + "/nic" # contains instances nic <-> tap associations
643 4f580fef Sébastien Bocahu
  _KEYMAP_DIR = _ROOT_DIR + "/keymap" # contains instances keymaps
644 547a63b7 Balazs Lecz
  # KVM instances with chroot enabled are started in empty chroot directories.
645 547a63b7 Balazs Lecz
  _CHROOT_DIR = _ROOT_DIR + "/chroot" # for empty chroot directories
646 547a63b7 Balazs Lecz
  # After an instance is stopped, its chroot directory is removed.
647 547a63b7 Balazs Lecz
  # If the chroot directory is not empty, it can't be removed.
648 547a63b7 Balazs Lecz
  # A non-empty chroot directory indicates a possible security incident.
649 547a63b7 Balazs Lecz
  # To support forensics, the non-empty chroot directory is quarantined in
650 547a63b7 Balazs Lecz
  # a separate directory, called 'chroot-quarantine'.
651 547a63b7 Balazs Lecz
  _CHROOT_QUARANTINE_DIR = _ROOT_DIR + "/chroot-quarantine"
652 5d9bfd87 Apollon Oikonomopoulos
  _DIRS = [_ROOT_DIR, _PIDS_DIR, _UIDS_DIR, _CTRL_DIR, _CONF_DIR, _NICS_DIR,
653 2911f46c Iustin Pop
           _CHROOT_DIR, _CHROOT_QUARANTINE_DIR, _KEYMAP_DIR]
654 eb58f9b1 Guido Trotter
655 205ab586 Iustin Pop
  PARAMETERS = {
656 4b9638dc Guido Trotter
    constants.HV_KVM_PATH: hv_base.REQ_FILE_CHECK,
657 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK,
658 205ab586 Iustin Pop
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
659 205ab586 Iustin Pop
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
660 205ab586 Iustin Pop
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
661 205ab586 Iustin Pop
    constants.HV_ACPI: hv_base.NO_CHECK,
662 205ab586 Iustin Pop
    constants.HV_SERIAL_CONSOLE: hv_base.NO_CHECK,
663 14fd6c81 Guido Trotter
    constants.HV_SERIAL_SPEED: hv_base.NO_CHECK,
664 d6e5767e Klaus Aehlig
    constants.HV_VNC_BIND_ADDRESS: hv_base.NO_CHECK, # will be checked later
665 205ab586 Iustin Pop
    constants.HV_VNC_TLS: hv_base.NO_CHECK,
666 205ab586 Iustin Pop
    constants.HV_VNC_X509: hv_base.OPT_DIR_CHECK,
667 205ab586 Iustin Pop
    constants.HV_VNC_X509_VERIFY: hv_base.NO_CHECK,
668 6e6bb8d5 Guido Trotter
    constants.HV_VNC_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
669 b1cb62bd Andrea Spadaccini
    constants.HV_KVM_SPICE_BIND: hv_base.NO_CHECK, # will be checked later
670 b1cb62bd Andrea Spadaccini
    constants.HV_KVM_SPICE_IP_VERSION:
671 b1cb62bd Andrea Spadaccini
      (False, lambda x: (x == constants.IFACE_NO_IP_VERSION_SPECIFIED or
672 b1cb62bd Andrea Spadaccini
                         x in constants.VALID_IP_VERSIONS),
673 afa9bb2e Michael Hanselmann
       "The SPICE IP version should be 4 or 6",
674 b1cb62bd Andrea Spadaccini
       None, None),
675 b451c4c7 Andrea Spadaccini
    constants.HV_KVM_SPICE_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
676 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR:
677 5ae4945a Iustin Pop
      hv_base.ParamInSet(
678 5ae4945a Iustin Pop
        False, constants.HT_KVM_SPICE_VALID_LOSSLESS_IMG_COMPR_OPTIONS),
679 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_JPEG_IMG_COMPR:
680 5ae4945a Iustin Pop
      hv_base.ParamInSet(
681 5ae4945a Iustin Pop
        False, constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
682 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR:
683 5ae4945a Iustin Pop
      hv_base.ParamInSet(
684 5ae4945a Iustin Pop
        False, constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
685 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION:
686 5ae4945a Iustin Pop
      hv_base.ParamInSet(
687 5ae4945a Iustin Pop
        False, constants.HT_KVM_SPICE_VALID_VIDEO_STREAM_DETECTION_OPTIONS),
688 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_AUDIO_COMPR: hv_base.NO_CHECK,
689 bfe86c76 Andrea Spadaccini
    constants.HV_KVM_SPICE_USE_TLS: hv_base.NO_CHECK,
690 3e40b587 Andrea Spadaccini
    constants.HV_KVM_SPICE_TLS_CIPHERS: hv_base.NO_CHECK,
691 3e40b587 Andrea Spadaccini
    constants.HV_KVM_SPICE_USE_VDAGENT: hv_base.NO_CHECK,
692 cc130cc7 Marco Casavecchia
    constants.HV_KVM_FLOPPY_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
693 205ab586 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
694 cc130cc7 Marco Casavecchia
    constants.HV_KVM_CDROM2_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
695 d73ef63f Michael Hanselmann
    constants.HV_BOOT_ORDER:
696 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
697 d73ef63f Michael Hanselmann
    constants.HV_NIC_TYPE:
698 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
699 d73ef63f Michael Hanselmann
    constants.HV_DISK_TYPE:
700 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
701 cc130cc7 Marco Casavecchia
    constants.HV_KVM_CDROM_DISK_TYPE:
702 cc130cc7 Marco Casavecchia
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_DISK_TYPES),
703 d73ef63f Michael Hanselmann
    constants.HV_USB_MOUSE:
704 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
705 4f580fef Sébastien Bocahu
    constants.HV_KEYMAP: hv_base.NO_CHECK,
706 e2d14329 Andrea Spadaccini
    constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
707 2c368f28 Guido Trotter
    constants.HV_MIGRATION_BANDWIDTH: hv_base.REQ_NONNEGATIVE_INT_CHECK,
708 2c368f28 Guido Trotter
    constants.HV_MIGRATION_DOWNTIME: hv_base.REQ_NONNEGATIVE_INT_CHECK,
709 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
710 6b970cef Jun Futagawa
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
711 19572932 Iustin Pop
    constants.HV_DISK_CACHE:
712 19572932 Iustin Pop
      hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
713 d19d94db Guido Trotter
    constants.HV_SECURITY_MODEL:
714 d19d94db Guido Trotter
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_SM_TYPES),
715 d19d94db Guido Trotter
    constants.HV_SECURITY_DOMAIN: hv_base.NO_CHECK,
716 7ba594c0 Guido Trotter
    constants.HV_KVM_FLAG:
717 7ba594c0 Guido Trotter
      hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES),
718 fbe27e2b Guido Trotter
    constants.HV_VHOST_NET: hv_base.NO_CHECK,
719 547a63b7 Balazs Lecz
    constants.HV_KVM_USE_CHROOT: hv_base.NO_CHECK,
720 4f958b0b Miguel Di Ciurcio Filho
    constants.HV_MEM_PATH: hv_base.OPT_DIR_CHECK,
721 990ade2d Stephen Shirley
    constants.HV_REBOOT_BEHAVIOR:
722 a7f884d3 Tsachy Shacham
      hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
723 a7f884d3 Tsachy Shacham
    constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
724 3c286190 Dimitris Aragiorgis
    constants.HV_CPU_TYPE: hv_base.NO_CHECK,
725 2c368f28 Guido Trotter
    constants.HV_CPU_CORES: hv_base.OPT_NONNEGATIVE_INT_CHECK,
726 2c368f28 Guido Trotter
    constants.HV_CPU_THREADS: hv_base.OPT_NONNEGATIVE_INT_CHECK,
727 2c368f28 Guido Trotter
    constants.HV_CPU_SOCKETS: hv_base.OPT_NONNEGATIVE_INT_CHECK,
728 2fddb144 Guido Trotter
    constants.HV_SOUNDHW: hv_base.NO_CHECK,
729 156681c1 Guido Trotter
    constants.HV_USB_DEVICES: hv_base.NO_CHECK,
730 7589346f Guido Trotter
    constants.HV_VGA: hv_base.NO_CHECK,
731 e6f24d89 Guido Trotter
    constants.HV_KVM_EXTRA: hv_base.NO_CHECK,
732 4ab75599 Dimitris Aragiorgis
    constants.HV_KVM_MACHINE_VERSION: hv_base.NO_CHECK,
733 d93e2477 Dimitris Aragiorgis
    constants.HV_KVM_MIGRATION_CAPS: hv_base.NO_CHECK,
734 8a534fbe Stratos Psomdakis
    constants.HV_VNET_HDR: hv_base.NO_CHECK,
735 205ab586 Iustin Pop
    }
736 6b5605e8 Iustin Pop
737 f0db563d Guido Trotter
  _VIRTIO = "virtio"
738 f0db563d Guido Trotter
  _VIRTIO_NET_PCI = "virtio-net-pci"
739 a16f0d77 Dimitris Aragiorgis
  _VIRTIO_BLK_PCI = "virtio-blk-pci"
740 f0db563d Guido Trotter
741 78f99abb Michele Tartara
  _MIGRATION_STATUS_RE = re.compile(r"Migration\s+status:\s+(\w+)",
742 30e42c4e Guido Trotter
                                    re.M | re.I)
743 65107a2f Michael Hanselmann
  _MIGRATION_PROGRESS_RE = \
744 527c0cf7 Michael Hanselmann
    re.compile(r"\s*transferred\s+ram:\s+(?P<transferred>\d+)\s+kbytes\s*\n"
745 527c0cf7 Michael Hanselmann
               r"\s*remaining\s+ram:\s+(?P<remaining>\d+)\s+kbytes\s*\n"
746 527c0cf7 Michael Hanselmann
               r"\s*total\s+ram:\s+(?P<total>\d+)\s+kbytes\s*\n", re.I)
747 61643226 Andrea Spadaccini
748 c4e388a5 Guido Trotter
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
749 c4e388a5 Guido Trotter
  _MIGRATION_INFO_RETRY_DELAY = 2
750 30e42c4e Guido Trotter
751 585c8187 Guido Trotter
  _VERSION_RE = re.compile(r"\b(\d+)\.(\d+)(\.(\d+))?\b")
752 b52d85c1 Guido Trotter
753 b693125f Tsachy Shacham
  _CPU_INFO_RE = re.compile(r"cpu\s+\#(\d+).*thread_id\s*=\s*(\d+)", re.I)
754 b693125f Tsachy Shacham
  _CPU_INFO_CMD = "info cpus"
755 b693125f Tsachy Shacham
  _CONT_CMD = "cont"
756 b693125f Tsachy Shacham
757 7f83345f Guido Trotter
  _DEFAULT_MACHINE_VERSION_RE = re.compile(r"^(\S+).*\(default\)", re.M)
758 82e3bf85 Dimitris Aragiorgis
  _CHECK_MACHINE_VERSION_RE = \
759 82e3bf85 Dimitris Aragiorgis
    staticmethod(lambda x: re.compile(r"^(%s)[ ]+.*PC" % x, re.M))
760 e6ba3320 Dimitris Aragiorgis
761 0ad7f5d8 Guido Trotter
  _QMP_RE = re.compile(r"^-qmp\s", re.M)
762 0ad7f5d8 Guido Trotter
  _SPICE_RE = re.compile(r"^-spice\s", re.M)
763 0ad7f5d8 Guido Trotter
  _VHOST_RE = re.compile(r"^-net\s.*,vhost=on|off", re.M)
764 0ad7f5d8 Guido Trotter
  _ENABLE_KVM_RE = re.compile(r"^-enable-kvm\s", re.M)
765 0ad7f5d8 Guido Trotter
  _DISABLE_KVM_RE = re.compile(r"^-disable-kvm\s", re.M)
766 0ad7f5d8 Guido Trotter
  _NETDEV_RE = re.compile(r"^-netdev\s", re.M)
767 99c7cd5b Guido Trotter
  _DISPLAY_RE = re.compile(r"^-display\s", re.M)
768 8cb5634a Guido Trotter
  _MACHINE_RE = re.compile(r"^-machine\s", re.M)
769 a16f0d77 Dimitris Aragiorgis
  _VIRTIO_NET_RE = re.compile(r"^name \"%s\"" % _VIRTIO_NET_PCI, re.M)
770 a16f0d77 Dimitris Aragiorgis
  _VIRTIO_BLK_RE = re.compile(r"^name \"%s\"" % _VIRTIO_BLK_PCI, re.M)
771 0ad7f5d8 Guido Trotter
  # match  -drive.*boot=on|off on different lines, but in between accept only
772 0ad7f5d8 Guido Trotter
  # dashes not preceeded by a new line (which would mean another option
773 0ad7f5d8 Guido Trotter
  # different than -drive is starting)
774 0ad7f5d8 Guido Trotter
  _BOOT_RE = re.compile(r"^-drive\s([^-]|(?<!^)-)*,boot=on\|off", re.M | re.S)
775 8feeb253 Christos Stavrakakis
  _UUID_RE = re.compile(r"^-uuid\s", re.M)
776 0ad7f5d8 Guido Trotter
777 2615646c Dimitris Aragiorgis
  _INFO_PCI_RE = re.compile(r'Bus.*device[ ]*(\d+).*')
778 2615646c Dimitris Aragiorgis
  _INFO_PCI_CMD = "info pci"
779 066f16b0 Dimitris Aragiorgis
  _FIND_PCI_DEVICE_RE = \
780 066f16b0 Dimitris Aragiorgis
    staticmethod(
781 066f16b0 Dimitris Aragiorgis
      lambda pci, devid: re.compile(r'Bus.*device[ ]*%d,(.*\n){5,6}.*id "%s"' %
782 066f16b0 Dimitris Aragiorgis
                                    (pci, devid), re.M))
783 066f16b0 Dimitris Aragiorgis
784 2615646c Dimitris Aragiorgis
  _INFO_VERSION_RE = \
785 2615646c Dimitris Aragiorgis
    re.compile(r'^QEMU (\d+)\.(\d+)(\.(\d+))?.*monitor.*', re.M)
786 2615646c Dimitris Aragiorgis
  _INFO_VERSION_CMD = "info version"
787 2615646c Dimitris Aragiorgis
788 3a72e34a Dimitris Aragiorgis
  # Slot 0 for Host bridge, Slot 1 for ISA bridge, Slot 2 for VGA controller
789 3a72e34a Dimitris Aragiorgis
  _DEFAULT_PCI_RESERVATIONS = "11100000000000000000000000000000"
790 3a72e34a Dimitris Aragiorgis
  _SOUNDHW_WITH_PCI_SLOT = ["ac97", "es1370", "hda"]
791 2615646c Dimitris Aragiorgis
792 64bfbc08 Guido Trotter
  ANCILLARY_FILES = [
793 64bfbc08 Guido Trotter
    _KVM_NETWORK_SCRIPT,
794 64bfbc08 Guido Trotter
    ]
795 69ab2e12 Guido Trotter
  ANCILLARY_FILES_OPT = [
796 69ab2e12 Guido Trotter
    _KVM_NETWORK_SCRIPT,
797 69ab2e12 Guido Trotter
    ]
798 64bfbc08 Guido Trotter
799 6e043e60 Guido Trotter
  # Supported kvm options to get output from
800 6e043e60 Guido Trotter
  _KVMOPT_HELP = "help"
801 6e043e60 Guido Trotter
  _KVMOPT_MLIST = "mlist"
802 f0db563d Guido Trotter
  _KVMOPT_DEVICELIST = "devicelist"
803 bc0fed4b Guido Trotter
804 bc0fed4b Guido Trotter
  # Command to execute to get the output from kvm, and whether to
805 bc0fed4b Guido Trotter
  # accept the output even on failure.
806 6e043e60 Guido Trotter
  _KVMOPTS_CMDS = {
807 bc0fed4b Guido Trotter
    _KVMOPT_HELP: (["--help"], False),
808 bc0fed4b Guido Trotter
    _KVMOPT_MLIST: (["-M", "?"], False),
809 bc0fed4b Guido Trotter
    _KVMOPT_DEVICELIST: (["-device", "?"], True),
810 6e043e60 Guido Trotter
  }
811 6e043e60 Guido Trotter
812 eb58f9b1 Guido Trotter
  def __init__(self):
813 eb58f9b1 Guido Trotter
    hv_base.BaseHypervisor.__init__(self)
814 eb58f9b1 Guido Trotter
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
815 eb58f9b1 Guido Trotter
    # in a tmpfs filesystem or has been otherwise wiped out.
816 29921401 Iustin Pop
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
817 9afb67fe Guido Trotter
    utils.EnsureDirs(dirs)
818 eb58f9b1 Guido Trotter
819 30786fc9 Iustin Pop
  @classmethod
820 30786fc9 Iustin Pop
  def _InstancePidFile(cls, instance_name):
821 98ec75d6 Iustin Pop
    """Returns the instance pidfile.
822 98ec75d6 Iustin Pop

823 98ec75d6 Iustin Pop
    """
824 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
825 98ec75d6 Iustin Pop
826 263b8de6 Guido Trotter
  @classmethod
827 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
828 7548396c Guido Trotter
    """Returns the instance uidfile.
829 7548396c Guido Trotter

830 7548396c Guido Trotter
    """
831 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
832 7548396c Guido Trotter
833 7548396c Guido Trotter
  @classmethod
834 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
835 263b8de6 Guido Trotter
    """Check pid file for instance information.
836 263b8de6 Guido Trotter

837 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
838 263b8de6 Guido Trotter
    information from its command line.
839 263b8de6 Guido Trotter

840 263b8de6 Guido Trotter
    @type pid: string or int
841 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
842 263b8de6 Guido Trotter
    @rtype: tuple
843 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
844 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
845 263b8de6 Guido Trotter

846 263b8de6 Guido Trotter
    """
847 263b8de6 Guido Trotter
    alive = utils.IsProcessAlive(pid)
848 263b8de6 Guido Trotter
    if not alive:
849 263b8de6 Guido Trotter
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
850 263b8de6 Guido Trotter
851 263b8de6 Guido Trotter
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
852 263b8de6 Guido Trotter
    try:
853 263b8de6 Guido Trotter
      cmdline = utils.ReadFile(cmdline_file)
854 263b8de6 Guido Trotter
    except EnvironmentError, err:
855 263b8de6 Guido Trotter
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
856 263b8de6 Guido Trotter
                                   (pid, err))
857 263b8de6 Guido Trotter
858 263b8de6 Guido Trotter
    instance = None
859 263b8de6 Guido Trotter
    memory = 0
860 263b8de6 Guido Trotter
    vcpus = 0
861 263b8de6 Guido Trotter
862 d0c8c01d Iustin Pop
    arg_list = cmdline.split("\x00")
863 263b8de6 Guido Trotter
    while arg_list:
864 e687ec01 Michael Hanselmann
      arg = arg_list.pop(0)
865 263b8de6 Guido Trotter
      if arg == "-name":
866 263b8de6 Guido Trotter
        instance = arg_list.pop(0)
867 263b8de6 Guido Trotter
      elif arg == "-m":
868 263b8de6 Guido Trotter
        memory = int(arg_list.pop(0))
869 263b8de6 Guido Trotter
      elif arg == "-smp":
870 4888a609 Guido Trotter
        vcpus = int(arg_list.pop(0).split(",")[0])
871 263b8de6 Guido Trotter
872 263b8de6 Guido Trotter
    if instance is None:
873 263b8de6 Guido Trotter
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
874 263b8de6 Guido Trotter
                                   " instance" % pid)
875 263b8de6 Guido Trotter
876 263b8de6 Guido Trotter
    return (instance, memory, vcpus)
877 263b8de6 Guido Trotter
878 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
879 263b8de6 Guido Trotter
    """Returns the instance pidfile, pid, and liveness.
880 263b8de6 Guido Trotter

881 263b8de6 Guido Trotter
    @type instance_name: string
882 263b8de6 Guido Trotter
    @param instance_name: instance name
883 263b8de6 Guido Trotter
    @rtype: tuple
884 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
885 1f8b3a27 Guido Trotter

886 1f8b3a27 Guido Trotter
    """
887 98ec75d6 Iustin Pop
    pidfile = self._InstancePidFile(instance_name)
888 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
889 263b8de6 Guido Trotter
890 263b8de6 Guido Trotter
    alive = False
891 263b8de6 Guido Trotter
    try:
892 263b8de6 Guido Trotter
      cmd_instance = self._InstancePidInfo(pid)[0]
893 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
894 263b8de6 Guido Trotter
    except errors.HypervisorError:
895 263b8de6 Guido Trotter
      pass
896 1f8b3a27 Guido Trotter
897 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
898 1f8b3a27 Guido Trotter
899 5905901c Iustin Pop
  def _CheckDown(self, instance_name):
900 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
901 5905901c Iustin Pop

902 5905901c Iustin Pop
    """
903 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
904 5905901c Iustin Pop
    if alive:
905 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
906 5905901c Iustin Pop
                                   (instance_name, "already running"))
907 5905901c Iustin Pop
908 0df4d98a Guido Trotter
  @classmethod
909 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
910 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
911 c4fbefc8 Guido Trotter

912 c4fbefc8 Guido Trotter
    """
913 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
914 c4fbefc8 Guido Trotter
915 0df4d98a Guido Trotter
  @classmethod
916 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
917 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
918 c4fbefc8 Guido Trotter

919 c4fbefc8 Guido Trotter
    """
920 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
921 c4fbefc8 Guido Trotter
922 91c10532 Andrea Spadaccini
  @classmethod
923 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
924 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
925 91c10532 Andrea Spadaccini

926 91c10532 Andrea Spadaccini
    """
927 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
928 91c10532 Andrea Spadaccini
929 86d6bc2a Guido Trotter
  @staticmethod
930 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
931 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
932 86d6bc2a Guido Trotter

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

935 86d6bc2a Guido Trotter
    """
936 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
937 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
938 86d6bc2a Guido Trotter
    else:
939 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
940 86d6bc2a Guido Trotter
941 0df4d98a Guido Trotter
  @classmethod
942 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
943 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
944 38e250ba Guido Trotter

945 38e250ba Guido Trotter
    """
946 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
947 38e250ba Guido Trotter
948 7e66c35b Guido Trotter
  @classmethod
949 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
950 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
951 547a63b7 Balazs Lecz

952 547a63b7 Balazs Lecz
    """
953 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
954 547a63b7 Balazs Lecz
955 547a63b7 Balazs Lecz
  @classmethod
956 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
957 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
958 5d9bfd87 Apollon Oikonomopoulos
    given instance.
959 5d9bfd87 Apollon Oikonomopoulos

960 5d9bfd87 Apollon Oikonomopoulos
    """
961 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
962 5d9bfd87 Apollon Oikonomopoulos
963 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
964 aec254f5 Dimitris Aragiorgis
  def _InstanceNICFile(cls, instance_name, seq_or_uuid):
965 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
966 5d9bfd87 Apollon Oikonomopoulos

967 5d9bfd87 Apollon Oikonomopoulos
    """
968 aec254f5 Dimitris Aragiorgis
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq_or_uuid))
969 aec254f5 Dimitris Aragiorgis
970 aec254f5 Dimitris Aragiorgis
  @classmethod
971 aec254f5 Dimitris Aragiorgis
  def _GetInstanceNICTap(cls, instance_name, nic):
972 aec254f5 Dimitris Aragiorgis
    """Returns the tap for the corresponding nic
973 aec254f5 Dimitris Aragiorgis

974 aec254f5 Dimitris Aragiorgis
    Search for tap file named after NIC's uuid.
975 aec254f5 Dimitris Aragiorgis
    For old instances without uuid indexed tap files returns nothing.
976 aec254f5 Dimitris Aragiorgis

977 aec254f5 Dimitris Aragiorgis
    """
978 aec254f5 Dimitris Aragiorgis
    try:
979 aec254f5 Dimitris Aragiorgis
      return utils.ReadFile(cls._InstanceNICFile(instance_name, nic.uuid))
980 aec254f5 Dimitris Aragiorgis
    except EnvironmentError:
981 aec254f5 Dimitris Aragiorgis
      pass
982 aec254f5 Dimitris Aragiorgis
983 aec254f5 Dimitris Aragiorgis
  @classmethod
984 aec254f5 Dimitris Aragiorgis
  def _WriteInstanceNICFiles(cls, instance_name, seq, nic, tap):
985 aec254f5 Dimitris Aragiorgis
    """Write tap name to both instance NIC files
986 aec254f5 Dimitris Aragiorgis

987 aec254f5 Dimitris Aragiorgis
    """
988 aec254f5 Dimitris Aragiorgis
    for ident in [seq, nic.uuid]:
989 aec254f5 Dimitris Aragiorgis
      utils.WriteFile(cls._InstanceNICFile(instance_name, ident), data=tap)
990 aec254f5 Dimitris Aragiorgis
991 aec254f5 Dimitris Aragiorgis
  @classmethod
992 aec254f5 Dimitris Aragiorgis
  def _RemoveInstanceNICFiles(cls, instance_name, seq, nic):
993 aec254f5 Dimitris Aragiorgis
    """Write tap name to both instance NIC files
994 aec254f5 Dimitris Aragiorgis

995 aec254f5 Dimitris Aragiorgis
    """
996 aec254f5 Dimitris Aragiorgis
    for ident in [seq, nic.uuid]:
997 aec254f5 Dimitris Aragiorgis
      utils.RemoveFile(cls._InstanceNICFile(instance_name, ident))
998 5d9bfd87 Apollon Oikonomopoulos
999 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
1000 4f580fef Sébastien Bocahu
  def _InstanceKeymapFile(cls, instance_name):
1001 4f580fef Sébastien Bocahu
    """Returns the name of the file containing the keymap for a given instance
1002 4f580fef Sébastien Bocahu

1003 4f580fef Sébastien Bocahu
    """
1004 4f580fef Sébastien Bocahu
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
1005 4f580fef Sébastien Bocahu
1006 4f580fef Sébastien Bocahu
  @classmethod
1007 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
1008 7548396c Guido Trotter
    """Try to read a uid file
1009 7548396c Guido Trotter

1010 7548396c Guido Trotter
    """
1011 7548396c Guido Trotter
    if os.path.exists(uid_file):
1012 7548396c Guido Trotter
      try:
1013 682f7601 Guido Trotter
        uid = int(utils.ReadOneLineFile(uid_file))
1014 aa0b600b Guido Trotter
        return uid
1015 7548396c Guido Trotter
      except EnvironmentError:
1016 7548396c Guido Trotter
        logging.warning("Can't read uid file", exc_info=True)
1017 7548396c Guido Trotter
      except (TypeError, ValueError):
1018 7548396c Guido Trotter
        logging.warning("Can't parse uid file contents", exc_info=True)
1019 aa0b600b Guido Trotter
    return None
1020 7548396c Guido Trotter
1021 7548396c Guido Trotter
  @classmethod
1022 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
1023 547a63b7 Balazs Lecz
    """Removes an instance's rutime sockets/files/dirs.
1024 7e66c35b Guido Trotter

1025 7e66c35b Guido Trotter
    """
1026 7e66c35b Guido Trotter
    utils.RemoveFile(pidfile)
1027 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
1028 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceSerial(instance_name))
1029 91c10532 Andrea Spadaccini
    utils.RemoveFile(cls._InstanceQmpMonitor(instance_name))
1030 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
1031 4f580fef Sébastien Bocahu
    utils.RemoveFile(cls._InstanceKeymapFile(instance_name))
1032 7548396c Guido Trotter
    uid_file = cls._InstanceUidFile(instance_name)
1033 7548396c Guido Trotter
    uid = cls._TryReadUidFile(uid_file)
1034 7548396c Guido Trotter
    utils.RemoveFile(uid_file)
1035 7548396c Guido Trotter
    if uid is not None:
1036 7548396c Guido Trotter
      uidpool.ReleaseUid(uid)
1037 7be85163 Guido Trotter
    try:
1038 7be85163 Guido Trotter
      shutil.rmtree(cls._InstanceNICDir(instance_name))
1039 7be85163 Guido Trotter
    except OSError, err:
1040 7be85163 Guido Trotter
      if err.errno != errno.ENOENT:
1041 7be85163 Guido Trotter
        raise
1042 547a63b7 Balazs Lecz
    try:
1043 547a63b7 Balazs Lecz
      chroot_dir = cls._InstanceChrootDir(instance_name)
1044 547a63b7 Balazs Lecz
      utils.RemoveDir(chroot_dir)
1045 547a63b7 Balazs Lecz
    except OSError, err:
1046 547a63b7 Balazs Lecz
      if err.errno == errno.ENOTEMPTY:
1047 547a63b7 Balazs Lecz
        # The chroot directory is expected to be empty, but it isn't.
1048 547a63b7 Balazs Lecz
        new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
1049 547a63b7 Balazs Lecz
                                          prefix="%s-%s-" %
1050 547a63b7 Balazs Lecz
                                          (instance_name,
1051 547a63b7 Balazs Lecz
                                           utils.TimestampForFilename()))
1052 547a63b7 Balazs Lecz
        logging.warning("The chroot directory of instance %s can not be"
1053 547a63b7 Balazs Lecz
                        " removed as it is not empty. Moving it to the"
1054 547a63b7 Balazs Lecz
                        " quarantine instead. Please investigate the"
1055 547a63b7 Balazs Lecz
                        " contents (%s) and clean up manually",
1056 547a63b7 Balazs Lecz
                        instance_name, new_chroot_dir)
1057 547a63b7 Balazs Lecz
        utils.RenameFile(chroot_dir, new_chroot_dir)
1058 547a63b7 Balazs Lecz
      else:
1059 547a63b7 Balazs Lecz
        raise
1060 7e66c35b Guido Trotter
1061 748e4b5a Michael Hanselmann
  @staticmethod
1062 0d2863a2 Dimitris Aragiorgis
  def _CreateNICEnv(instance_name, nic, tap, seq=None, instance_tags=None):
1063 0d2863a2 Dimitris Aragiorgis
    """Create environment variables for a specific NIC
1064 eb58f9b1 Guido Trotter

1065 0d2863a2 Dimitris Aragiorgis
    This is needed during NIC ifup/ifdown scripts.
1066 0d2863a2 Dimitris Aragiorgis
    Since instance tags may change during NIC creation and removal
1067 0d2863a2 Dimitris Aragiorgis
    and because during cleanup instance object is not available we
1068 0d2863a2 Dimitris Aragiorgis
    pass them only upon NIC creation (instance startup/NIC hot-plugging).
1069 eb58f9b1 Guido Trotter

1070 eb58f9b1 Guido Trotter
    """
1071 5d9bfd87 Apollon Oikonomopoulos
    env = {
1072 5d9bfd87 Apollon Oikonomopoulos
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
1073 0d2863a2 Dimitris Aragiorgis
      "INSTANCE": instance_name,
1074 5d9bfd87 Apollon Oikonomopoulos
      "MAC": nic.mac,
1075 5d9bfd87 Apollon Oikonomopoulos
      "MODE": nic.nicparams[constants.NIC_MODE],
1076 cc6fd3da Dimitris Aragiorgis
      "INTERFACE_UUID": nic.uuid,
1077 5d9bfd87 Apollon Oikonomopoulos
    }
1078 5d9bfd87 Apollon Oikonomopoulos
1079 0d2863a2 Dimitris Aragiorgis
    if instance_tags:
1080 0d2863a2 Dimitris Aragiorgis
      env["TAGS"] = " ".join(instance_tags)
1081 0d2863a2 Dimitris Aragiorgis
1082 0d2863a2 Dimitris Aragiorgis
    # This should always be available except for old instances in the
1083 0d2863a2 Dimitris Aragiorgis
    # cluster without uuid indexed tap files.
1084 0d2863a2 Dimitris Aragiorgis
    if tap:
1085 0d2863a2 Dimitris Aragiorgis
      env["INTERFACE"] = tap
1086 0d2863a2 Dimitris Aragiorgis
1087 0d2863a2 Dimitris Aragiorgis
    if seq:
1088 0d2863a2 Dimitris Aragiorgis
      env["INTERFACE_INDEX"] = str(seq)
1089 0d2863a2 Dimitris Aragiorgis
1090 5d9bfd87 Apollon Oikonomopoulos
    if nic.ip:
1091 5d9bfd87 Apollon Oikonomopoulos
      env["IP"] = nic.ip
1092 5d9bfd87 Apollon Oikonomopoulos
1093 cc6fd3da Dimitris Aragiorgis
    if nic.name:
1094 cc6fd3da Dimitris Aragiorgis
      env["INTERFACE_NAME"] = nic.name
1095 cc6fd3da Dimitris Aragiorgis
1096 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_LINK]:
1097 5d9bfd87 Apollon Oikonomopoulos
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
1098 5d9bfd87 Apollon Oikonomopoulos
1099 a5ad5e58 Apollon Oikonomopoulos
    if nic.network:
1100 cbe4a0a5 Dimitris Aragiorgis
      n = objects.Network.FromDict(nic.netinfo)
1101 7e8f03e3 Dimitris Aragiorgis
      env.update(n.HooksDict())
1102 a5ad5e58 Apollon Oikonomopoulos
1103 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1104 5d9bfd87 Apollon Oikonomopoulos
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
1105 5d9bfd87 Apollon Oikonomopoulos
1106 0d2863a2 Dimitris Aragiorgis
    return env
1107 0d2863a2 Dimitris Aragiorgis
1108 0d2863a2 Dimitris Aragiorgis
  @classmethod
1109 0d2863a2 Dimitris Aragiorgis
  def _ConfigureNIC(cls, instance, seq, nic, tap):
1110 0d2863a2 Dimitris Aragiorgis
    """Run the network configuration script for a specified NIC
1111 0d2863a2 Dimitris Aragiorgis

1112 0d2863a2 Dimitris Aragiorgis
    @param instance: instance we're acting on
1113 0d2863a2 Dimitris Aragiorgis
    @type instance: instance object
1114 0d2863a2 Dimitris Aragiorgis
    @param seq: nic sequence number
1115 0d2863a2 Dimitris Aragiorgis
    @type seq: int
1116 0d2863a2 Dimitris Aragiorgis
    @param nic: nic we're acting on
1117 0d2863a2 Dimitris Aragiorgis
    @type nic: nic object
1118 0d2863a2 Dimitris Aragiorgis
    @param tap: the host's tap interface this NIC corresponds to
1119 0d2863a2 Dimitris Aragiorgis
    @type tap: str
1120 0d2863a2 Dimitris Aragiorgis

1121 0d2863a2 Dimitris Aragiorgis
    """
1122 0d2863a2 Dimitris Aragiorgis
    env = cls._CreateNICEnv(instance.name, nic, tap, seq, instance.GetTags())
1123 9d9bded1 Michael Hanselmann
    result = utils.RunCmd([pathutils.KVM_IFUP, tap], env=env)
1124 5d9bfd87 Apollon Oikonomopoulos
    if result.failed:
1125 afa9bb2e Michael Hanselmann
      raise errors.HypervisorError("Failed to configure interface %s: %s;"
1126 afa9bb2e Michael Hanselmann
                                   " network configuration script output: %s" %
1127 5d9bfd87 Apollon Oikonomopoulos
                                   (tap, result.fail_reason, result.output))
1128 eb58f9b1 Guido Trotter
1129 3889f749 Dimitris Aragiorgis
  @classmethod
1130 3889f749 Dimitris Aragiorgis
  def _UnconfigureNic(cls, instance_name, nic, only_local=True):
1131 3889f749 Dimitris Aragiorgis
    """Run ifdown script for a specific NIC
1132 3889f749 Dimitris Aragiorgis

1133 3889f749 Dimitris Aragiorgis
    This is executed during instance cleanup and NIC hot-unplug
1134 3889f749 Dimitris Aragiorgis

1135 3889f749 Dimitris Aragiorgis
    @param instance_name: instance we're acting on
1136 3889f749 Dimitris Aragiorgis
    @type instance_name: string
1137 3889f749 Dimitris Aragiorgis
    @param nic: nic we're acting on
1138 3889f749 Dimitris Aragiorgis
    @type nic: nic object
1139 3889f749 Dimitris Aragiorgis
    @param only_local: whether ifdown script should reset global conf (dns)
1140 3889f749 Dimitris Aragiorgis
    @type only_local: boolean
1141 3889f749 Dimitris Aragiorgis

1142 3889f749 Dimitris Aragiorgis
    """
1143 3889f749 Dimitris Aragiorgis
    tap = cls._GetInstanceNICTap(instance_name, nic)
1144 3889f749 Dimitris Aragiorgis
    env = cls._CreateNICEnv(instance_name, nic, tap)
1145 3889f749 Dimitris Aragiorgis
    arg2 = str(only_local).lower()
1146 3889f749 Dimitris Aragiorgis
    result = utils.RunCmd([pathutils.KVM_IFDOWN, tap, arg2], env=env)
1147 3889f749 Dimitris Aragiorgis
    if result.failed:
1148 3889f749 Dimitris Aragiorgis
      raise errors.HypervisorError("Failed to unconfigure interface %s: %s;"
1149 3889f749 Dimitris Aragiorgis
                                   " network configuration script output: %s" %
1150 3889f749 Dimitris Aragiorgis
                                   (tap, result.fail_reason, result.output))
1151 3889f749 Dimitris Aragiorgis
1152 b693125f Tsachy Shacham
  @staticmethod
1153 b693125f Tsachy Shacham
  def _VerifyAffinityPackage():
1154 b693125f Tsachy Shacham
    if affinity is None:
1155 b693125f Tsachy Shacham
      raise errors.HypervisorError("affinity Python package not"
1156 5ae4945a Iustin Pop
                                   " found; cannot use CPU pinning under KVM")
1157 b693125f Tsachy Shacham
1158 b693125f Tsachy Shacham
  @staticmethod
1159 b693125f Tsachy Shacham
  def _BuildAffinityCpuMask(cpu_list):
1160 b693125f Tsachy Shacham
    """Create a CPU mask suitable for sched_setaffinity from a list of
1161 b693125f Tsachy Shacham
    CPUs.
1162 b693125f Tsachy Shacham

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

1166 b693125f Tsachy Shacham
    @type cpu_list: list of int
1167 b693125f Tsachy Shacham
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
1168 b693125f Tsachy Shacham
    @rtype: int
1169 b693125f Tsachy Shacham
    @return: a bit mask of CPU affinities
1170 b693125f Tsachy Shacham

1171 b693125f Tsachy Shacham
    """
1172 b693125f Tsachy Shacham
    if cpu_list == constants.CPU_PINNING_OFF:
1173 b693125f Tsachy Shacham
      return constants.CPU_PINNING_ALL_KVM
1174 b693125f Tsachy Shacham
    else:
1175 b693125f Tsachy Shacham
      return sum(2 ** cpu for cpu in cpu_list)
1176 b693125f Tsachy Shacham
1177 b693125f Tsachy Shacham
  @classmethod
1178 b693125f Tsachy Shacham
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
1179 b693125f Tsachy Shacham
    """Change CPU affinity for running VM according to given CPU mask.
1180 b693125f Tsachy Shacham

1181 b693125f Tsachy Shacham
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
1182 b693125f Tsachy Shacham
    @type cpu_mask: string
1183 b693125f Tsachy Shacham
    @param process_id: process ID of KVM process. Used to pin entire VM
1184 b693125f Tsachy Shacham
                       to physical CPUs.
1185 b693125f Tsachy Shacham
    @type process_id: int
1186 b693125f Tsachy Shacham
    @param thread_dict: map of virtual CPUs to KVM thread IDs
1187 b693125f Tsachy Shacham
    @type thread_dict: dict int:int
1188 b693125f Tsachy Shacham

1189 b693125f Tsachy Shacham
    """
1190 b693125f Tsachy Shacham
    # Convert the string CPU mask to a list of list of int's
1191 b693125f Tsachy Shacham
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
1192 b693125f Tsachy Shacham
1193 b693125f Tsachy Shacham
    if len(cpu_list) == 1:
1194 b693125f Tsachy Shacham
      all_cpu_mapping = cpu_list[0]
1195 b693125f Tsachy Shacham
      if all_cpu_mapping == constants.CPU_PINNING_OFF:
1196 b693125f Tsachy Shacham
        # If CPU pinning has 1 entry that's "all", then do nothing
1197 b693125f Tsachy Shacham
        pass
1198 b693125f Tsachy Shacham
      else:
1199 b693125f Tsachy Shacham
        # If CPU pinning has one non-all entry, map the entire VM to
1200 b693125f Tsachy Shacham
        # one set of physical CPUs
1201 b693125f Tsachy Shacham
        cls._VerifyAffinityPackage()
1202 5ae4945a Iustin Pop
        affinity.set_process_affinity_mask(
1203 5ae4945a Iustin Pop
          process_id, cls._BuildAffinityCpuMask(all_cpu_mapping))
1204 b693125f Tsachy Shacham
    else:
1205 b693125f Tsachy Shacham
      # The number of vCPUs mapped should match the number of vCPUs
1206 b693125f Tsachy Shacham
      # reported by KVM. This was already verified earlier, so
1207 b693125f Tsachy Shacham
      # here only as a sanity check.
1208 b693125f Tsachy Shacham
      assert len(thread_dict) == len(cpu_list)
1209 b693125f Tsachy Shacham
      cls._VerifyAffinityPackage()
1210 b693125f Tsachy Shacham
1211 b693125f Tsachy Shacham
      # For each vCPU, map it to the proper list of physical CPUs
1212 b693125f Tsachy Shacham
      for vcpu, i in zip(cpu_list, range(len(cpu_list))):
1213 b693125f Tsachy Shacham
        affinity.set_process_affinity_mask(thread_dict[i],
1214 5ae4945a Iustin Pop
                                           cls._BuildAffinityCpuMask(vcpu))
1215 b693125f Tsachy Shacham
1216 b693125f Tsachy Shacham
  def _GetVcpuThreadIds(self, instance_name):
1217 b693125f Tsachy Shacham
    """Get a mapping of vCPU no. to thread IDs for the instance
1218 b693125f Tsachy Shacham

1219 b693125f Tsachy Shacham
    @type instance_name: string
1220 b693125f Tsachy Shacham
    @param instance_name: instance in question
1221 b693125f Tsachy Shacham
    @rtype: dictionary of int:int
1222 b693125f Tsachy Shacham
    @return: a dictionary mapping vCPU numbers to thread IDs
1223 b693125f Tsachy Shacham

1224 b693125f Tsachy Shacham
    """
1225 b693125f Tsachy Shacham
    result = {}
1226 b693125f Tsachy Shacham
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
1227 b693125f Tsachy Shacham
    for line in output.stdout.splitlines():
1228 b693125f Tsachy Shacham
      match = self._CPU_INFO_RE.search(line)
1229 b693125f Tsachy Shacham
      if not match:
1230 b693125f Tsachy Shacham
        continue
1231 b693125f Tsachy Shacham
      grp = map(int, match.groups())
1232 b693125f Tsachy Shacham
      result[grp[0]] = grp[1]
1233 b693125f Tsachy Shacham
1234 b693125f Tsachy Shacham
    return result
1235 b693125f Tsachy Shacham
1236 1d8a7812 Andrea Spadaccini
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
1237 1d8a7812 Andrea Spadaccini
    """Complete CPU pinning.
1238 b693125f Tsachy Shacham

1239 b693125f Tsachy Shacham
    @type instance_name: string
1240 b693125f Tsachy Shacham
    @param instance_name: name of instance
1241 b693125f Tsachy Shacham
    @type cpu_mask: string
1242 b693125f Tsachy Shacham
    @param cpu_mask: CPU pinning mask as entered by user
1243 b693125f Tsachy Shacham

1244 b693125f Tsachy Shacham
    """
1245 1d8a7812 Andrea Spadaccini
    # Get KVM process ID, to be used if need to pin entire VM
1246 1d8a7812 Andrea Spadaccini
    _, pid, _ = self._InstancePidAlive(instance_name)
1247 1d8a7812 Andrea Spadaccini
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
1248 1d8a7812 Andrea Spadaccini
    thread_dict = self._GetVcpuThreadIds(instance_name)
1249 1d8a7812 Andrea Spadaccini
    # Run CPU pinning, based on configured mask
1250 1d8a7812 Andrea Spadaccini
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
1251 b693125f Tsachy Shacham
1252 58e356a9 Helga Velroyen
  def ListInstances(self, hvparams=None):
1253 eb58f9b1 Guido Trotter
    """Get the list of running instances.
1254 eb58f9b1 Guido Trotter

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

1258 eb58f9b1 Guido Trotter
    """
1259 eb58f9b1 Guido Trotter
    result = []
1260 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1261 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
1262 eb58f9b1 Guido Trotter
        result.append(name)
1263 eb58f9b1 Guido Trotter
    return result
1264 eb58f9b1 Guido Trotter
1265 0bbec3af Helga Velroyen
  def GetInstanceInfo(self, instance_name, hvparams=None):
1266 eb58f9b1 Guido Trotter
    """Get instance properties.
1267 eb58f9b1 Guido Trotter

1268 4fbb3c60 Guido Trotter
    @type instance_name: string
1269 c41eea6e Iustin Pop
    @param instance_name: the instance name
1270 0bbec3af Helga Velroyen
    @type hvparams: dict of strings
1271 0bbec3af Helga Velroyen
    @param hvparams: hvparams to be used with this instance
1272 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
1273 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
1274 eb58f9b1 Guido Trotter

1275 eb58f9b1 Guido Trotter
    """
1276 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
1277 1f8b3a27 Guido Trotter
    if not alive:
1278 eb58f9b1 Guido Trotter
      return None
1279 eb58f9b1 Guido Trotter
1280 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
1281 fc84cd5d Guido Trotter
    istat = "---b-"
1282 eb58f9b1 Guido Trotter
    times = "0"
1283 eb58f9b1 Guido Trotter
1284 89da2ff3 Guido Trotter
    try:
1285 89da2ff3 Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
1286 89da2ff3 Guido Trotter
      qmp.connect()
1287 89da2ff3 Guido Trotter
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
1288 89da2ff3 Guido Trotter
      # Will fail if ballooning is not enabled, but we can then just resort to
1289 89da2ff3 Guido Trotter
      # the value above.
1290 89da2ff3 Guido Trotter
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
1291 89da2ff3 Guido Trotter
      memory = mem_bytes / 1048576
1292 89da2ff3 Guido Trotter
    except errors.HypervisorError:
1293 89da2ff3 Guido Trotter
      pass
1294 89da2ff3 Guido Trotter
1295 fc84cd5d Guido Trotter
    return (instance_name, pid, memory, vcpus, istat, times)
1296 eb58f9b1 Guido Trotter
1297 0200a1af Helga Velroyen
  def GetAllInstancesInfo(self, hvparams=None):
1298 eb58f9b1 Guido Trotter
    """Get properties of all instances.
1299 eb58f9b1 Guido Trotter

1300 0200a1af Helga Velroyen
    @type hvparams: dict of strings
1301 0200a1af Helga Velroyen
    @param hvparams: hypervisor parameter
1302 c41eea6e Iustin Pop
    @return: list of tuples (name, id, memory, vcpus, stat, times)
1303 c41eea6e Iustin Pop

1304 eb58f9b1 Guido Trotter
    """
1305 eb58f9b1 Guido Trotter
    data = []
1306 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1307 263b8de6 Guido Trotter
      try:
1308 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
1309 263b8de6 Guido Trotter
      except errors.HypervisorError:
1310 3bc145d8 Bernardo Dal Seno
        # Ignore exceptions due to instances being shut down
1311 263b8de6 Guido Trotter
        continue
1312 263b8de6 Guido Trotter
      if info:
1313 263b8de6 Guido Trotter
        data.append(info)
1314 eb58f9b1 Guido Trotter
    return data
1315 eb58f9b1 Guido Trotter
1316 918baead Apollon Oikonomopoulos
  def _GenerateKVMBlockDevicesOptions(self, instance, up_hvp, kvm_disks,
1317 43c6e76f Dimitris Aragiorgis
                                      kvmhelp, devlist):
1318 43c6e76f Dimitris Aragiorgis
    """Generate KVM options regarding instance's block devices.
1319 43c6e76f Dimitris Aragiorgis

1320 43c6e76f Dimitris Aragiorgis
    @type instance: L{objects.Instance}
1321 43c6e76f Dimitris Aragiorgis
    @param instance: the instance object
1322 918baead Apollon Oikonomopoulos
    @type up_hvp: dict
1323 918baead Apollon Oikonomopoulos
    @param up_hvp: the instance's runtime hypervisor parameters
1324 41a878b5 Dimitris Aragiorgis
    @type kvm_disks: list of tuples
1325 41a878b5 Dimitris Aragiorgis
    @param kvm_disks: list of tuples [(disk, link_name, uri)..]
1326 43c6e76f Dimitris Aragiorgis
    @type kvmhelp: string
1327 43c6e76f Dimitris Aragiorgis
    @param kvmhelp: output of kvm --help
1328 43c6e76f Dimitris Aragiorgis
    @type devlist: string
1329 43c6e76f Dimitris Aragiorgis
    @param devlist: output of kvm -device ?
1330 43c6e76f Dimitris Aragiorgis
    @rtype: list
1331 43c6e76f Dimitris Aragiorgis
    @return: list of command line options eventually used by kvm executable
1332 af5db30c Dimitris Aragiorgis

1333 43c6e76f Dimitris Aragiorgis
    """
1334 918baead Apollon Oikonomopoulos
    kernel_path = up_hvp[constants.HV_KERNEL_PATH]
1335 43c6e76f Dimitris Aragiorgis
    if kernel_path:
1336 43c6e76f Dimitris Aragiorgis
      boot_disk = False
1337 43c6e76f Dimitris Aragiorgis
    else:
1338 918baead Apollon Oikonomopoulos
      boot_disk = up_hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
1339 af5db30c Dimitris Aragiorgis
1340 af5db30c Dimitris Aragiorgis
    # whether this is an older KVM version that uses the boot=on flag
1341 af5db30c Dimitris Aragiorgis
    # on devices
1342 af5db30c Dimitris Aragiorgis
    needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1343 af5db30c Dimitris Aragiorgis
1344 af5db30c Dimitris Aragiorgis
    dev_opts = []
1345 a16f0d77 Dimitris Aragiorgis
    device_driver = None
1346 918baead Apollon Oikonomopoulos
    disk_type = up_hvp[constants.HV_DISK_TYPE]
1347 af5db30c Dimitris Aragiorgis
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
1348 af5db30c Dimitris Aragiorgis
      if_val = ",if=%s" % self._VIRTIO
1349 a16f0d77 Dimitris Aragiorgis
      try:
1350 a16f0d77 Dimitris Aragiorgis
        if self._VIRTIO_BLK_RE.search(devlist):
1351 a7ccf635 Dimitris Aragiorgis
          if_val = ",if=none"
1352 a16f0d77 Dimitris Aragiorgis
          # will be passed in -device option as driver
1353 a16f0d77 Dimitris Aragiorgis
          device_driver = self._VIRTIO_BLK_PCI
1354 a16f0d77 Dimitris Aragiorgis
      except errors.HypervisorError, _:
1355 a16f0d77 Dimitris Aragiorgis
        pass
1356 af5db30c Dimitris Aragiorgis
    else:
1357 af5db30c Dimitris Aragiorgis
      if_val = ",if=%s" % disk_type
1358 af5db30c Dimitris Aragiorgis
    # Cache mode
1359 918baead Apollon Oikonomopoulos
    disk_cache = up_hvp[constants.HV_DISK_CACHE]
1360 af5db30c Dimitris Aragiorgis
    if instance.disk_template in constants.DTS_EXT_MIRROR:
1361 af5db30c Dimitris Aragiorgis
      if disk_cache != "none":
1362 af5db30c Dimitris Aragiorgis
        # TODO: make this a hard error, instead of a silent overwrite
1363 af5db30c Dimitris Aragiorgis
        logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
1364 af5db30c Dimitris Aragiorgis
                        " to prevent shared storage corruption on migration",
1365 af5db30c Dimitris Aragiorgis
                        disk_cache)
1366 af5db30c Dimitris Aragiorgis
      cache_val = ",cache=none"
1367 af5db30c Dimitris Aragiorgis
    elif disk_cache != constants.HT_CACHE_DEFAULT:
1368 af5db30c Dimitris Aragiorgis
      cache_val = ",cache=%s" % disk_cache
1369 af5db30c Dimitris Aragiorgis
    else:
1370 af5db30c Dimitris Aragiorgis
      cache_val = ""
1371 41a878b5 Dimitris Aragiorgis
    for cfdev, link_name, uri in kvm_disks:
1372 af5db30c Dimitris Aragiorgis
      if cfdev.mode != constants.DISK_RDWR:
1373 af5db30c Dimitris Aragiorgis
        raise errors.HypervisorError("Instance has read-only disks which"
1374 af5db30c Dimitris Aragiorgis
                                     " are not supported by KVM")
1375 af5db30c Dimitris Aragiorgis
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
1376 af5db30c Dimitris Aragiorgis
      boot_val = ""
1377 af5db30c Dimitris Aragiorgis
      if boot_disk:
1378 af5db30c Dimitris Aragiorgis
        dev_opts.extend(["-boot", "c"])
1379 af5db30c Dimitris Aragiorgis
        boot_disk = False
1380 af5db30c Dimitris Aragiorgis
        if needs_boot_flag and disk_type != constants.HT_DISK_IDE:
1381 af5db30c Dimitris Aragiorgis
          boot_val = ",boot=on"
1382 af5db30c Dimitris Aragiorgis
1383 af5db30c Dimitris Aragiorgis
      access_mode = cfdev.params.get(constants.LDP_ACCESS,
1384 af5db30c Dimitris Aragiorgis
                                     constants.DISK_KERNELSPACE)
1385 66d3d195 Dimitris Aragiorgis
      if (uri and access_mode == constants.DISK_USERSPACE):
1386 66d3d195 Dimitris Aragiorgis
        drive_uri = uri
1387 af5db30c Dimitris Aragiorgis
      else:
1388 66d3d195 Dimitris Aragiorgis
        drive_uri = link_name
1389 af5db30c Dimitris Aragiorgis
1390 1a1af037 Dimitris Aragiorgis
      # For ext we allow overriding disk_cache hypervisor params per disk
1391 1a1af037 Dimitris Aragiorgis
      disk_cache = cfdev.params.get("cache", None)
1392 1a1af037 Dimitris Aragiorgis
      if disk_cache:
1393 1a1af037 Dimitris Aragiorgis
        cache_val = ",cache=%s" % disk_cache
1394 1a1af037 Dimitris Aragiorgis
1395 af5db30c Dimitris Aragiorgis
      drive_val = "file=%s,format=raw%s%s%s" % \
1396 af5db30c Dimitris Aragiorgis
                  (drive_uri, if_val, boot_val, cache_val)
1397 af5db30c Dimitris Aragiorgis
1398 a16f0d77 Dimitris Aragiorgis
      if device_driver:
1399 41a878b5 Dimitris Aragiorgis
        # kvm_disks are the 4th entry of runtime file that did not exist in
1400 a7ccf635 Dimitris Aragiorgis
        # the past. That means that cfdev should always have pci slot and
1401 a7ccf635 Dimitris Aragiorgis
        # _GenerateDeviceKVMId() will not raise a exception.
1402 a7ccf635 Dimitris Aragiorgis
        kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_DISK, cfdev)
1403 a7ccf635 Dimitris Aragiorgis
        drive_val += (",id=%s" % kvm_devid)
1404 a7ccf635 Dimitris Aragiorgis
        drive_val += (",bus=0,unit=%d" % cfdev.pci)
1405 a7ccf635 Dimitris Aragiorgis
        dev_val = ("%s,drive=%s,id=%s" %
1406 a7ccf635 Dimitris Aragiorgis
                   (device_driver, kvm_devid, kvm_devid))
1407 a7ccf635 Dimitris Aragiorgis
        dev_val += ",bus=pci.0,addr=%s" % hex(cfdev.pci)
1408 a7ccf635 Dimitris Aragiorgis
        dev_opts.extend(["-device", dev_val])
1409 a7ccf635 Dimitris Aragiorgis
1410 764fce21 Dimitris Aragiorgis
      # TODO: export disk geometry in IDISK_PARAMS
1411 764fce21 Dimitris Aragiorgis
      heads = cfdev.params.get('heads', None)
1412 764fce21 Dimitris Aragiorgis
      secs = cfdev.params.get('secs', None)
1413 764fce21 Dimitris Aragiorgis
      if heads and secs:
1414 764fce21 Dimitris Aragiorgis
        nr_sectors = cfdev.size * 1024 * 1024 / 512
1415 764fce21 Dimitris Aragiorgis
        cyls = nr_sectors / (int(heads) * int(secs))
1416 764fce21 Dimitris Aragiorgis
        if cyls > 16383:
1417 764fce21 Dimitris Aragiorgis
          cyls = 16383
1418 764fce21 Dimitris Aragiorgis
        elif cyls < 2:
1419 764fce21 Dimitris Aragiorgis
          cyls = 2
1420 764fce21 Dimitris Aragiorgis
        if cyls and heads and secs:
1421 764fce21 Dimitris Aragiorgis
          drive_val += (",cyls=%d,heads=%d,secs=%d" %
1422 764fce21 Dimitris Aragiorgis
                        (cyls, int(heads), int(secs)))
1423 764fce21 Dimitris Aragiorgis
1424 af5db30c Dimitris Aragiorgis
      dev_opts.extend(["-drive", drive_val])
1425 af5db30c Dimitris Aragiorgis
1426 af5db30c Dimitris Aragiorgis
    return dev_opts
1427 af5db30c Dimitris Aragiorgis
1428 b73f1c59 Guido Trotter
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused,
1429 b73f1c59 Guido Trotter
                          kvmhelp):
1430 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
1431 eb58f9b1 Guido Trotter

1432 b73f1c59 Guido Trotter
    @type kvmhelp: string
1433 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1434 839642c2 Iustin Pop
    @attention: this function must not have any side-effects; for
1435 839642c2 Iustin Pop
        example, it must not write to the filesystem, or read values
1436 839642c2 Iustin Pop
        from the current system the are expected to differ between
1437 839642c2 Iustin Pop
        nodes, since it is only run once at instance startup;
1438 839642c2 Iustin Pop
        actions/kvm arguments that can vary between systems should be
1439 839642c2 Iustin Pop
        done in L{_ExecuteKVMRuntime}
1440 839642c2 Iustin Pop

1441 eb58f9b1 Guido Trotter
    """
1442 4888a609 Guido Trotter
    # pylint: disable=R0912,R0914,R0915
1443 4888a609 Guido Trotter
    hvp = instance.hvparams
1444 81e265f5 Guido Trotter
    self.ValidateParameters(hvp)
1445 4304964a Guido Trotter
1446 e687ec01 Michael Hanselmann
    pidfile = self._InstancePidFile(instance.name)
1447 4b9638dc Guido Trotter
    kvm = hvp[constants.HV_KVM_PATH]
1448 eb58f9b1 Guido Trotter
    kvm_cmd = [kvm]
1449 c6a39fc2 Guido Trotter
    # used just by the vnc server, if enabled
1450 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-name", instance.name])
1451 f5a4b9ce Guido Trotter
    kvm_cmd.extend(["-m", instance.beparams[constants.BE_MAXMEM]])
1452 4888a609 Guido Trotter
1453 4888a609 Guido Trotter
    smp_list = ["%s" % instance.beparams[constants.BE_VCPUS]]
1454 4888a609 Guido Trotter
    if hvp[constants.HV_CPU_CORES]:
1455 4888a609 Guido Trotter
      smp_list.append("cores=%s" % hvp[constants.HV_CPU_CORES])
1456 4888a609 Guido Trotter
    if hvp[constants.HV_CPU_THREADS]:
1457 4888a609 Guido Trotter
      smp_list.append("threads=%s" % hvp[constants.HV_CPU_THREADS])
1458 4888a609 Guido Trotter
    if hvp[constants.HV_CPU_SOCKETS]:
1459 4888a609 Guido Trotter
      smp_list.append("sockets=%s" % hvp[constants.HV_CPU_SOCKETS])
1460 4888a609 Guido Trotter
1461 4888a609 Guido Trotter
    kvm_cmd.extend(["-smp", ",".join(smp_list)])
1462 4888a609 Guido Trotter
1463 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-pidfile", pidfile])
1464 3a72e34a Dimitris Aragiorgis
1465 3a72e34a Dimitris Aragiorgis
    pci_reservations = bitarray(self._DEFAULT_PCI_RESERVATIONS)
1466 3a72e34a Dimitris Aragiorgis
1467 3a72e34a Dimitris Aragiorgis
    # As requested by music lovers
1468 3a72e34a Dimitris Aragiorgis
    if hvp[constants.HV_SOUNDHW]:
1469 3a72e34a Dimitris Aragiorgis
      soundhw = hvp[constants.HV_SOUNDHW]
1470 3a72e34a Dimitris Aragiorgis
      # For some reason only few sound devices require a PCI slot
1471 3a72e34a Dimitris Aragiorgis
      # while the Audio controller *must* be in slot 3.
1472 3a72e34a Dimitris Aragiorgis
      # That's why we bridge this option early in command line
1473 3a72e34a Dimitris Aragiorgis
      if soundhw in self._SOUNDHW_WITH_PCI_SLOT:
1474 3a72e34a Dimitris Aragiorgis
        _ = _GetFreeSlot(pci_reservations, reserve=True)
1475 3a72e34a Dimitris Aragiorgis
      kvm_cmd.extend(["-soundhw", soundhw])
1476 3a72e34a Dimitris Aragiorgis
1477 5e6d16ab Apollon Oikonomopoulos
    if hvp[constants.HV_DISK_TYPE] == constants.HT_DISK_SCSI:
1478 5e6d16ab Apollon Oikonomopoulos
      # The SCSI controller requires another PCI slot.
1479 5e6d16ab Apollon Oikonomopoulos
      _ = _GetFreeSlot(pci_reservations, reserve=True)
1480 5e6d16ab Apollon Oikonomopoulos
1481 3a72e34a Dimitris Aragiorgis
    # Add id to ballon and place to the first available slot (3 or 4)
1482 3a72e34a Dimitris Aragiorgis
    addr = _GetFreeSlot(pci_reservations, reserve=True)
1483 3a72e34a Dimitris Aragiorgis
    pci_info = ",bus=pci.0,addr=%s" % hex(addr)
1484 3a72e34a Dimitris Aragiorgis
    kvm_cmd.extend(["-balloon", "virtio,id=balloon%s" % pci_info])
1485 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-daemonize"])
1486 6b5605e8 Iustin Pop
    if not instance.hvparams[constants.HV_ACPI]:
1487 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-no-acpi"])
1488 990ade2d Stephen Shirley
    if instance.hvparams[constants.HV_REBOOT_BEHAVIOR] == \
1489 990ade2d Stephen Shirley
        constants.INSTANCE_REBOOT_EXIT:
1490 990ade2d Stephen Shirley
      kvm_cmd.extend(["-no-reboot"])
1491 eb58f9b1 Guido Trotter
1492 4ab75599 Dimitris Aragiorgis
    mversion = hvp[constants.HV_KVM_MACHINE_VERSION]
1493 4ab75599 Dimitris Aragiorgis
    if not mversion:
1494 4b9638dc Guido Trotter
      mversion = self._GetDefaultMachineVersion(kvm)
1495 8cb5634a Guido Trotter
    if self._MACHINE_RE.search(kvmhelp):
1496 8cb5634a Guido Trotter
      # TODO (2.8): kernel_irqchip and kvm_shadow_mem machine properties, as
1497 8cb5634a Guido Trotter
      # extra hypervisor parameters. We should also investigate whether and how
1498 8cb5634a Guido Trotter
      # shadow_mem should be considered for the resource model.
1499 8cb5634a Guido Trotter
      if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED):
1500 8cb5634a Guido Trotter
        specprop = ",accel=kvm"
1501 8cb5634a Guido Trotter
      else:
1502 8cb5634a Guido Trotter
        specprop = ""
1503 8cb5634a Guido Trotter
      machinespec = "%s%s" % (mversion, specprop)
1504 8cb5634a Guido Trotter
      kvm_cmd.extend(["-machine", machinespec])
1505 8cb5634a Guido Trotter
    else:
1506 8cb5634a Guido Trotter
      kvm_cmd.extend(["-M", mversion])
1507 8cb5634a Guido Trotter
      if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED and
1508 8cb5634a Guido Trotter
          self._ENABLE_KVM_RE.search(kvmhelp)):
1509 8cb5634a Guido Trotter
        kvm_cmd.extend(["-enable-kvm"])
1510 8cb5634a Guido Trotter
      elif (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED and
1511 8cb5634a Guido Trotter
            self._DISABLE_KVM_RE.search(kvmhelp)):
1512 8cb5634a Guido Trotter
        kvm_cmd.extend(["-disable-kvm"])
1513 4ab75599 Dimitris Aragiorgis
1514 2b846304 Iustin Pop
    kernel_path = hvp[constants.HV_KERNEL_PATH]
1515 2b846304 Iustin Pop
    if kernel_path:
1516 af5db30c Dimitris Aragiorgis
      boot_cdrom = boot_floppy = boot_network = False
1517 2b846304 Iustin Pop
    else:
1518 2b846304 Iustin Pop
      boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
1519 2b846304 Iustin Pop
      boot_floppy = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_FLOPPY
1520 2b846304 Iustin Pop
      boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
1521 8745c3d7 Guido Trotter
1522 b693125f Tsachy Shacham
    if startup_paused:
1523 b693125f Tsachy Shacham
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1524 b693125f Tsachy Shacham
1525 8745c3d7 Guido Trotter
    if boot_network:
1526 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-boot", "n"])
1527 1213604d Guido Trotter
1528 24be50e0 Iustin Pop
    # whether this is an older KVM version that uses the boot=on flag
1529 24be50e0 Iustin Pop
    # on devices
1530 0ad7f5d8 Guido Trotter
    needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1531 24be50e0 Iustin Pop
1532 a985b417 Iustin Pop
    disk_type = hvp[constants.HV_DISK_TYPE]
1533 eb58f9b1 Guido Trotter
1534 cc130cc7 Marco Casavecchia
    #Now we can specify a different device type for CDROM devices.
1535 cc130cc7 Marco Casavecchia
    cdrom_disk_type = hvp[constants.HV_KVM_CDROM_DISK_TYPE]
1536 cc130cc7 Marco Casavecchia
    if not cdrom_disk_type:
1537 cc130cc7 Marco Casavecchia
      cdrom_disk_type = disk_type
1538 cc130cc7 Marco Casavecchia
1539 a985b417 Iustin Pop
    iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
1540 66d5dbef Guido Trotter
    if iso_image:
1541 d0c8c01d Iustin Pop
      options = ",format=raw,media=cdrom"
1542 24be50e0 Iustin Pop
      # set cdrom 'if' type
1543 66d5dbef Guido Trotter
      if boot_cdrom:
1544 24be50e0 Iustin Pop
        actual_cdrom_type = constants.HT_DISK_IDE
1545 24be50e0 Iustin Pop
      elif cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1546 24be50e0 Iustin Pop
        actual_cdrom_type = "virtio"
1547 9dd363eb Guido Trotter
      else:
1548 24be50e0 Iustin Pop
        actual_cdrom_type = cdrom_disk_type
1549 24be50e0 Iustin Pop
      if_val = ",if=%s" % actual_cdrom_type
1550 24be50e0 Iustin Pop
      # set boot flag, if needed
1551 24be50e0 Iustin Pop
      boot_val = ""
1552 24be50e0 Iustin Pop
      if boot_cdrom:
1553 24be50e0 Iustin Pop
        kvm_cmd.extend(["-boot", "d"])
1554 24be50e0 Iustin Pop
        if needs_boot_flag:
1555 24be50e0 Iustin Pop
          boot_val = ",boot=on"
1556 24be50e0 Iustin Pop
      # and finally build the entire '-drive' value
1557 24be50e0 Iustin Pop
      drive_val = "file=%s%s%s%s" % (iso_image, options, if_val, boot_val)
1558 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1559 66d5dbef Guido Trotter
1560 cc130cc7 Marco Casavecchia
    iso_image2 = hvp[constants.HV_KVM_CDROM2_IMAGE_PATH]
1561 cc130cc7 Marco Casavecchia
    if iso_image2:
1562 d0c8c01d Iustin Pop
      options = ",format=raw,media=cdrom"
1563 cc130cc7 Marco Casavecchia
      if cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1564 d0c8c01d Iustin Pop
        if_val = ",if=virtio"
1565 cc130cc7 Marco Casavecchia
      else:
1566 d0c8c01d Iustin Pop
        if_val = ",if=%s" % cdrom_disk_type
1567 24be50e0 Iustin Pop
      drive_val = "file=%s%s%s" % (iso_image2, options, if_val)
1568 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1569 cc130cc7 Marco Casavecchia
1570 cc130cc7 Marco Casavecchia
    floppy_image = hvp[constants.HV_KVM_FLOPPY_IMAGE_PATH]
1571 cc130cc7 Marco Casavecchia
    if floppy_image:
1572 d0c8c01d Iustin Pop
      options = ",format=raw,media=disk"
1573 cc130cc7 Marco Casavecchia
      if boot_floppy:
1574 d0c8c01d Iustin Pop
        kvm_cmd.extend(["-boot", "a"])
1575 d0c8c01d Iustin Pop
        options = "%s,boot=on" % options
1576 d0c8c01d Iustin Pop
      if_val = ",if=floppy"
1577 d0c8c01d Iustin Pop
      options = "%s%s" % (options, if_val)
1578 d0c8c01d Iustin Pop
      drive_val = "file=%s%s" % (floppy_image, options)
1579 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1580 cc130cc7 Marco Casavecchia
1581 df5ab9f0 Guido Trotter
    if kernel_path:
1582 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-kernel", kernel_path])
1583 a985b417 Iustin Pop
      initrd_path = hvp[constants.HV_INITRD_PATH]
1584 df5ab9f0 Guido Trotter
      if initrd_path:
1585 d0c8c01d Iustin Pop
        kvm_cmd.extend(["-initrd", initrd_path])
1586 d0c8c01d Iustin Pop
      root_append = ["root=%s" % hvp[constants.HV_ROOT_PATH],
1587 07813a9e Iustin Pop
                     hvp[constants.HV_KERNEL_ARGS]]
1588 07813a9e Iustin Pop
      if hvp[constants.HV_SERIAL_CONSOLE]:
1589 14fd6c81 Guido Trotter
        serial_speed = hvp[constants.HV_SERIAL_SPEED]
1590 14fd6c81 Guido Trotter
        root_append.append("console=ttyS0,%s" % serial_speed)
1591 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-append", " ".join(root_append)])
1592 eb58f9b1 Guido Trotter
1593 4f958b0b Miguel Di Ciurcio Filho
    mem_path = hvp[constants.HV_MEM_PATH]
1594 4f958b0b Miguel Di Ciurcio Filho
    if mem_path:
1595 9d3015f9 Guido Trotter
      kvm_cmd.extend(["-mem-path", mem_path, "-mem-prealloc"])
1596 4f958b0b Miguel Di Ciurcio Filho
1597 596b2459 Guido Trotter
    monitor_dev = ("unix:%s,server,nowait" %
1598 596b2459 Guido Trotter
                   self._InstanceMonitor(instance.name))
1599 596b2459 Guido Trotter
    kvm_cmd.extend(["-monitor", monitor_dev])
1600 596b2459 Guido Trotter
    if hvp[constants.HV_SERIAL_CONSOLE]:
1601 596b2459 Guido Trotter
      serial_dev = ("unix:%s,server,nowait" %
1602 596b2459 Guido Trotter
                    self._InstanceSerial(instance.name))
1603 596b2459 Guido Trotter
      kvm_cmd.extend(["-serial", serial_dev])
1604 596b2459 Guido Trotter
    else:
1605 596b2459 Guido Trotter
      kvm_cmd.extend(["-serial", "none"])
1606 596b2459 Guido Trotter
1607 a985b417 Iustin Pop
    mouse_type = hvp[constants.HV_USB_MOUSE]
1608 31f6f67a Guido Trotter
    vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
1609 596b2459 Guido Trotter
    spice_bind = hvp[constants.HV_KVM_SPICE_BIND]
1610 596b2459 Guido Trotter
    spice_ip_version = None
1611 31f6f67a Guido Trotter
1612 a900a30c Guido Trotter
    kvm_cmd.extend(["-usb"])
1613 a900a30c Guido Trotter
1614 11344a50 Guido Trotter
    if mouse_type:
1615 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-usbdevice", mouse_type])
1616 31f6f67a Guido Trotter
    elif vnc_bind_address:
1617 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-usbdevice", constants.HT_MOUSE_TABLET])
1618 11344a50 Guido Trotter
1619 8470c8db Guido Trotter
    if vnc_bind_address:
1620 d6e5767e Klaus Aehlig
      if netutils.IsValidInterface(vnc_bind_address):
1621 d6e5767e Klaus Aehlig
        if_addresses = netutils.GetInterfaceIpAddresses(vnc_bind_address)
1622 d6e5767e Klaus Aehlig
        if_ip4_addresses = if_addresses[constants.IP4_VERSION]
1623 d6e5767e Klaus Aehlig
        if len(if_ip4_addresses) < 1:
1624 d6e5767e Klaus Aehlig
          logging.error("Could not determine IPv4 address of interface %s",
1625 d6e5767e Klaus Aehlig
                        vnc_bind_address)
1626 d6e5767e Klaus Aehlig
        else:
1627 d6e5767e Klaus Aehlig
          vnc_bind_address = if_ip4_addresses[0]
1628 8b312c1d Manuel Franceschini
      if netutils.IP4Address.IsValid(vnc_bind_address):
1629 377d74c9 Guido Trotter
        if instance.network_port > constants.VNC_BASE_PORT:
1630 377d74c9 Guido Trotter
          display = instance.network_port - constants.VNC_BASE_PORT
1631 14f5f1b6 Manuel Franceschini
          if vnc_bind_address == constants.IP4_ADDRESS_ANY:
1632 d0c8c01d Iustin Pop
            vnc_arg = ":%d" % (display)
1633 8447f52b Guido Trotter
          else:
1634 d0c8c01d Iustin Pop
            vnc_arg = "%s:%d" % (vnc_bind_address, display)
1635 8470c8db Guido Trotter
        else:
1636 afa9bb2e Michael Hanselmann
          logging.error("Network port is not a valid VNC display (%d < %d),"
1637 afa9bb2e Michael Hanselmann
                        " not starting VNC",
1638 afa9bb2e Michael Hanselmann
                        instance.network_port, constants.VNC_BASE_PORT)
1639 d0c8c01d Iustin Pop
          vnc_arg = "none"
1640 8b2d1013 Guido Trotter
1641 8b2d1013 Guido Trotter
        # Only allow tls and other option when not binding to a file, for now.
1642 8b2d1013 Guido Trotter
        # kvm/qemu gets confused otherwise about the filename to use.
1643 d0c8c01d Iustin Pop
        vnc_append = ""
1644 a985b417 Iustin Pop
        if hvp[constants.HV_VNC_TLS]:
1645 d0c8c01d Iustin Pop
          vnc_append = "%s,tls" % vnc_append
1646 a985b417 Iustin Pop
          if hvp[constants.HV_VNC_X509_VERIFY]:
1647 d0c8c01d Iustin Pop
            vnc_append = "%s,x509verify=%s" % (vnc_append,
1648 a985b417 Iustin Pop
                                               hvp[constants.HV_VNC_X509])
1649 a985b417 Iustin Pop
          elif hvp[constants.HV_VNC_X509]:
1650 d0c8c01d Iustin Pop
            vnc_append = "%s,x509=%s" % (vnc_append,
1651 a985b417 Iustin Pop
                                         hvp[constants.HV_VNC_X509])
1652 6e6bb8d5 Guido Trotter
        if hvp[constants.HV_VNC_PASSWORD_FILE]:
1653 d0c8c01d Iustin Pop
          vnc_append = "%s,password" % vnc_append
1654 6e6bb8d5 Guido Trotter
1655 d0c8c01d Iustin Pop
        vnc_arg = "%s%s" % (vnc_arg, vnc_append)
1656 8b2d1013 Guido Trotter
1657 8470c8db Guido Trotter
      else:
1658 d0c8c01d Iustin Pop
        vnc_arg = "unix:%s/%s.vnc" % (vnc_bind_address, instance.name)
1659 8b2d1013 Guido Trotter
1660 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-vnc", vnc_arg])
1661 596b2459 Guido Trotter
    elif spice_bind:
1662 839642c2 Iustin Pop
      # FIXME: this is wrong here; the iface ip address differs
1663 839642c2 Iustin Pop
      # between systems, so it should be done in _ExecuteKVMRuntime
1664 b1cb62bd Andrea Spadaccini
      if netutils.IsValidInterface(spice_bind):
1665 b1cb62bd Andrea Spadaccini
        # The user specified a network interface, we have to figure out the IP
1666 b1cb62bd Andrea Spadaccini
        # address.
1667 b1cb62bd Andrea Spadaccini
        addresses = netutils.GetInterfaceIpAddresses(spice_bind)
1668 b1cb62bd Andrea Spadaccini
        spice_ip_version = hvp[constants.HV_KVM_SPICE_IP_VERSION]
1669 b1cb62bd Andrea Spadaccini
1670 b1cb62bd Andrea Spadaccini
        # if the user specified an IP version and the interface does not
1671 b1cb62bd Andrea Spadaccini
        # have that kind of IP addresses, throw an exception
1672 b1cb62bd Andrea Spadaccini
        if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1673 b1cb62bd Andrea Spadaccini
          if not addresses[spice_ip_version]:
1674 afa9bb2e Michael Hanselmann
            raise errors.HypervisorError("SPICE: Unable to get an IPv%s address"
1675 b1cb62bd Andrea Spadaccini
                                         " for %s" % (spice_ip_version,
1676 b1cb62bd Andrea Spadaccini
                                                      spice_bind))
1677 b1cb62bd Andrea Spadaccini
1678 b1cb62bd Andrea Spadaccini
        # the user did not specify an IP version, we have to figure it out
1679 b1cb62bd Andrea Spadaccini
        elif (addresses[constants.IP4_VERSION] and
1680 b1cb62bd Andrea Spadaccini
              addresses[constants.IP6_VERSION]):
1681 b1cb62bd Andrea Spadaccini
          # we have both ipv4 and ipv6, let's use the cluster default IP
1682 b1cb62bd Andrea Spadaccini
          # version
1683 b1cb62bd Andrea Spadaccini
          cluster_family = ssconf.SimpleStore().GetPrimaryIPFamily()
1684 65107a2f Michael Hanselmann
          spice_ip_version = \
1685 65107a2f Michael Hanselmann
            netutils.IPAddress.GetVersionFromAddressFamily(cluster_family)
1686 b1cb62bd Andrea Spadaccini
        elif addresses[constants.IP4_VERSION]:
1687 b1cb62bd Andrea Spadaccini
          spice_ip_version = constants.IP4_VERSION
1688 b845c8a1 Andrea Spadaccini
        elif addresses[constants.IP6_VERSION]:
1689 b1cb62bd Andrea Spadaccini
          spice_ip_version = constants.IP6_VERSION
1690 b845c8a1 Andrea Spadaccini
        else:
1691 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Unable to get an IP address"
1692 b845c8a1 Andrea Spadaccini
                                       " for %s" % (spice_bind))
1693 b1cb62bd Andrea Spadaccini
1694 b1cb62bd Andrea Spadaccini
        spice_address = addresses[spice_ip_version][0]
1695 b1cb62bd Andrea Spadaccini
1696 b1cb62bd Andrea Spadaccini
      else:
1697 b1cb62bd Andrea Spadaccini
        # spice_bind is known to be a valid IP address, because
1698 b1cb62bd Andrea Spadaccini
        # ValidateParameters checked it.
1699 b1cb62bd Andrea Spadaccini
        spice_address = spice_bind
1700 b1cb62bd Andrea Spadaccini
1701 bfe86c76 Andrea Spadaccini
      spice_arg = "addr=%s" % spice_address
1702 bfe86c76 Andrea Spadaccini
      if hvp[constants.HV_KVM_SPICE_USE_TLS]:
1703 5ae4945a Iustin Pop
        spice_arg = ("%s,tls-port=%s,x509-cacert-file=%s" %
1704 5ae4945a Iustin Pop
                     (spice_arg, instance.network_port,
1705 9d9bded1 Michael Hanselmann
                      pathutils.SPICE_CACERT_FILE))
1706 5ae4945a Iustin Pop
        spice_arg = ("%s,x509-key-file=%s,x509-cert-file=%s" %
1707 9d9bded1 Michael Hanselmann
                     (spice_arg, pathutils.SPICE_CERT_FILE,
1708 9d9bded1 Michael Hanselmann
                      pathutils.SPICE_CERT_FILE))
1709 3e40b587 Andrea Spadaccini
        tls_ciphers = hvp[constants.HV_KVM_SPICE_TLS_CIPHERS]
1710 3e40b587 Andrea Spadaccini
        if tls_ciphers:
1711 3e40b587 Andrea Spadaccini
          spice_arg = "%s,tls-ciphers=%s" % (spice_arg, tls_ciphers)
1712 bfe86c76 Andrea Spadaccini
      else:
1713 bfe86c76 Andrea Spadaccini
        spice_arg = "%s,port=%s" % (spice_arg, instance.network_port)
1714 bfe86c76 Andrea Spadaccini
1715 b451c4c7 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]:
1716 b451c4c7 Andrea Spadaccini
        spice_arg = "%s,disable-ticketing" % spice_arg
1717 b451c4c7 Andrea Spadaccini
1718 11ae7a0a Andrea Spadaccini
      if spice_ip_version:
1719 11ae7a0a Andrea Spadaccini
        spice_arg = "%s,ipv%s" % (spice_arg, spice_ip_version)
1720 b1cb62bd Andrea Spadaccini
1721 ea064d24 Andrea Spadaccini
      # Image compression options
1722 ea064d24 Andrea Spadaccini
      img_lossless = hvp[constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR]
1723 ea064d24 Andrea Spadaccini
      img_jpeg = hvp[constants.HV_KVM_SPICE_JPEG_IMG_COMPR]
1724 ea064d24 Andrea Spadaccini
      img_zlib_glz = hvp[constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR]
1725 ea064d24 Andrea Spadaccini
      if img_lossless:
1726 ea064d24 Andrea Spadaccini
        spice_arg = "%s,image-compression=%s" % (spice_arg, img_lossless)
1727 ea064d24 Andrea Spadaccini
      if img_jpeg:
1728 ea064d24 Andrea Spadaccini
        spice_arg = "%s,jpeg-wan-compression=%s" % (spice_arg, img_jpeg)
1729 ea064d24 Andrea Spadaccini
      if img_zlib_glz:
1730 ea064d24 Andrea Spadaccini
        spice_arg = "%s,zlib-glz-wan-compression=%s" % (spice_arg, img_zlib_glz)
1731 ea064d24 Andrea Spadaccini
1732 ea064d24 Andrea Spadaccini
      # Video stream detection
1733 ea064d24 Andrea Spadaccini
      video_streaming = hvp[constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION]
1734 ea064d24 Andrea Spadaccini
      if video_streaming:
1735 ea064d24 Andrea Spadaccini
        spice_arg = "%s,streaming-video=%s" % (spice_arg, video_streaming)
1736 ea064d24 Andrea Spadaccini
1737 ea064d24 Andrea Spadaccini
      # Audio compression, by default in qemu-kvm it is on
1738 ea064d24 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_AUDIO_COMPR]:
1739 ea064d24 Andrea Spadaccini
        spice_arg = "%s,playback-compression=off" % spice_arg
1740 3e40b587 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_USE_VDAGENT]:
1741 3e40b587 Andrea Spadaccini
        spice_arg = "%s,agent-mouse=off" % spice_arg
1742 447af814 Nikos Skalkotos
      else:
1743 447af814 Nikos Skalkotos
        # Enable the spice agent communication channel between the host and the
1744 447af814 Nikos Skalkotos
        # agent.
1745 3a72e34a Dimitris Aragiorgis
        addr = _GetFreeSlot(pci_reservations, reserve=True)
1746 3a72e34a Dimitris Aragiorgis
        pci_info = ",bus=pci.0,addr=%s" % hex(addr)
1747 3a72e34a Dimitris Aragiorgis
        kvm_cmd.extend(["-device", "virtio-serial-pci,id=spice%s" % pci_info])
1748 afa9bb2e Michael Hanselmann
        kvm_cmd.extend([
1749 afa9bb2e Michael Hanselmann
          "-device",
1750 afa9bb2e Michael Hanselmann
          "virtserialport,chardev=spicechannel0,name=com.redhat.spice.0",
1751 afa9bb2e Michael Hanselmann
          ])
1752 447af814 Nikos Skalkotos
        kvm_cmd.extend(["-chardev", "spicevmc,id=spicechannel0,name=vdagent"])
1753 ea064d24 Andrea Spadaccini
1754 b1cb62bd Andrea Spadaccini
      logging.info("KVM: SPICE will listen on port %s", instance.network_port)
1755 b1cb62bd Andrea Spadaccini
      kvm_cmd.extend(["-spice", spice_arg])
1756 b1cb62bd Andrea Spadaccini
1757 596b2459 Guido Trotter
    else:
1758 99c7cd5b Guido Trotter
      # From qemu 1.4 -nographic is incompatible with -daemonize. The new way
1759 99c7cd5b Guido Trotter
      # also works in earlier versions though (tested with 1.1 and 1.3)
1760 99c7cd5b Guido Trotter
      if self._DISPLAY_RE.search(kvmhelp):
1761 99c7cd5b Guido Trotter
        kvm_cmd.extend(["-display", "none"])
1762 99c7cd5b Guido Trotter
      else:
1763 99c7cd5b Guido Trotter
        kvm_cmd.extend(["-nographic"])
1764 596b2459 Guido Trotter
1765 6b970cef Jun Futagawa
    if hvp[constants.HV_USE_LOCALTIME]:
1766 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-localtime"])
1767 6b970cef Jun Futagawa
1768 547a63b7 Balazs Lecz
    if hvp[constants.HV_KVM_USE_CHROOT]:
1769 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-chroot", self._InstanceChrootDir(instance.name)])
1770 547a63b7 Balazs Lecz
1771 7cb42171 Nikita Staroverov
    # Add qemu-KVM -cpu param
1772 7cb42171 Nikita Staroverov
    if hvp[constants.HV_CPU_TYPE]:
1773 7cb42171 Nikita Staroverov
      kvm_cmd.extend(["-cpu", hvp[constants.HV_CPU_TYPE]])
1774 7cb42171 Nikita Staroverov
1775 7589346f Guido Trotter
    # Pass a -vga option if requested, or if spice is used, for backwards
1776 7589346f Guido Trotter
    # compatibility.
1777 7589346f Guido Trotter
    if hvp[constants.HV_VGA]:
1778 7589346f Guido Trotter
      kvm_cmd.extend(["-vga", hvp[constants.HV_VGA]])
1779 7589346f Guido Trotter
    elif spice_bind:
1780 7589346f Guido Trotter
      kvm_cmd.extend(["-vga", "qxl"])
1781 7589346f Guido Trotter
1782 156681c1 Guido Trotter
    # Various types of usb devices, comma separated
1783 156681c1 Guido Trotter
    if hvp[constants.HV_USB_DEVICES]:
1784 156681c1 Guido Trotter
      for dev in hvp[constants.HV_USB_DEVICES].split(","):
1785 156681c1 Guido Trotter
        kvm_cmd.extend(["-usbdevice", dev])
1786 156681c1 Guido Trotter
1787 8feeb253 Christos Stavrakakis
    # Set system UUID to instance UUID
1788 8feeb253 Christos Stavrakakis
    if self._UUID_RE.search(kvmhelp):
1789 8feeb253 Christos Stavrakakis
      kvm_cmd.extend(["-uuid", instance.uuid])
1790 8feeb253 Christos Stavrakakis
1791 e6f24d89 Guido Trotter
    if hvp[constants.HV_KVM_EXTRA]:
1792 a967416c Guido Trotter
      kvm_cmd.extend(hvp[constants.HV_KVM_EXTRA].split(" "))
1793 e6f24d89 Guido Trotter
1794 0fe22ad2 Dimitris Aragiorgis
    kvm_disks = []
1795 a7ccf635 Dimitris Aragiorgis
    for disk, link_name, uri in block_devices:
1796 d13fb3f1 Dimitris Aragiorgis
      disk.pci = _GetFreeSlot(pci_reservations, disk.pci, True)
1797 a7ccf635 Dimitris Aragiorgis
      kvm_disks.append((disk, link_name, uri))
1798 0fe22ad2 Dimitris Aragiorgis
1799 0fe22ad2 Dimitris Aragiorgis
    kvm_nics = []
1800 0fe22ad2 Dimitris Aragiorgis
    for nic in instance.nics:
1801 d13fb3f1 Dimitris Aragiorgis
      nic.pci = _GetFreeSlot(pci_reservations, nic.pci, True)
1802 0fe22ad2 Dimitris Aragiorgis
      kvm_nics.append(nic)
1803 0fe22ad2 Dimitris Aragiorgis
1804 a985b417 Iustin Pop
    hvparams = hvp
1805 ee5f20b0 Guido Trotter
1806 0fe22ad2 Dimitris Aragiorgis
    return (kvm_cmd, kvm_nics, hvparams, kvm_disks)
1807 ee5f20b0 Guido Trotter
1808 38e250ba Guido Trotter
  def _WriteKVMRuntime(self, instance_name, data):
1809 38e250ba Guido Trotter
    """Write an instance's KVM runtime
1810 38e250ba Guido Trotter

1811 38e250ba Guido Trotter
    """
1812 38e250ba Guido Trotter
    try:
1813 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1814 38e250ba Guido Trotter
                      data=data)
1815 90c024f6 Guido Trotter
    except EnvironmentError, err:
1816 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1817 38e250ba Guido Trotter
1818 79f3e9e9 Dimitris Aragiorgis
  @classmethod
1819 79f3e9e9 Dimitris Aragiorgis
  def _ReadKVMRuntime(cls, instance_name):
1820 38e250ba Guido Trotter
    """Read an instance's KVM runtime
1821 38e250ba Guido Trotter

1822 38e250ba Guido Trotter
    """
1823 38e250ba Guido Trotter
    try:
1824 79f3e9e9 Dimitris Aragiorgis
      file_content = utils.ReadFile(cls._InstanceKVMRuntime(instance_name))
1825 90c024f6 Guido Trotter
    except EnvironmentError, err:
1826 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1827 38e250ba Guido Trotter
    return file_content
1828 38e250ba Guido Trotter
1829 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1830 38e250ba Guido Trotter
    """Save an instance's KVM runtime
1831 38e250ba Guido Trotter

1832 38e250ba Guido Trotter
    """
1833 41a878b5 Dimitris Aragiorgis
    kvm_cmd, kvm_nics, hvparams, kvm_disks = kvm_runtime
1834 0fe22ad2 Dimitris Aragiorgis
1835 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1836 41a878b5 Dimitris Aragiorgis
    serialized_disks = [(blk.ToDict(), link, uri)
1837 41a878b5 Dimitris Aragiorgis
                        for blk, link, uri in kvm_disks]
1838 0fe22ad2 Dimitris Aragiorgis
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams,
1839 41a878b5 Dimitris Aragiorgis
                                      serialized_disks))
1840 0fe22ad2 Dimitris Aragiorgis
1841 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
1842 38e250ba Guido Trotter
1843 79f3e9e9 Dimitris Aragiorgis
  @classmethod
1844 79f3e9e9 Dimitris Aragiorgis
  def _LoadKVMRuntime(cls, instance_name, serialized_runtime=None):
1845 38e250ba Guido Trotter
    """Load an instance's KVM runtime
1846 38e250ba Guido Trotter

1847 38e250ba Guido Trotter
    """
1848 30e42c4e Guido Trotter
    if not serialized_runtime:
1849 79f3e9e9 Dimitris Aragiorgis
      serialized_runtime = cls._ReadKVMRuntime(instance_name)
1850 0fe22ad2 Dimitris Aragiorgis
1851 0fe22ad2 Dimitris Aragiorgis
    return _AnalyzeSerializedRuntime(serialized_runtime)
1852 38e250ba Guido Trotter
1853 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1854 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
1855 76431533 Guido Trotter

1856 76431533 Guido Trotter
    @type name: string
1857 76431533 Guido Trotter
    @param name: instance name
1858 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1859 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1860 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1861 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1862 76431533 Guido Trotter

1863 76431533 Guido Trotter
    """
1864 5d9bfd87 Apollon Oikonomopoulos
    try:
1865 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1866 5d9bfd87 Apollon Oikonomopoulos
    finally:
1867 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
1868 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
1869 5d9bfd87 Apollon Oikonomopoulos
1870 76431533 Guido Trotter
    if result.failed:
1871 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1872 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
1873 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
1874 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
1875 76431533 Guido Trotter
1876 41a878b5 Dimitris Aragiorgis
  # too many local variables
1877 0fe22ad2 Dimitris Aragiorgis
  # pylint: disable=R0914
1878 b73f1c59 Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1879 839642c2 Iustin Pop
    """Execute a KVM cmd, after completing it with some last minute data.
1880 ee5f20b0 Guido Trotter

1881 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1882 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1883 b73f1c59 Guido Trotter
    @type kvmhelp: string
1884 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1885 30e42c4e Guido Trotter

1886 ee5f20b0 Guido Trotter
    """
1887 297e6e53 Guido Trotter
    # Small _ExecuteKVMRuntime hv parameters programming howto:
1888 297e6e53 Guido Trotter
    #  - conf_hvp contains the parameters as configured on ganeti. they might
1889 297e6e53 Guido Trotter
    #    have changed since the instance started; only use them if the change
1890 297e6e53 Guido Trotter
    #    won't affect the inside of the instance (which hasn't been rebooted).
1891 297e6e53 Guido Trotter
    #  - up_hvp contains the parameters as they were when the instance was
1892 297e6e53 Guido Trotter
    #    started, plus any new parameter which has been added between ganeti
1893 297e6e53 Guido Trotter
    #    versions: it is paramount that those default to a value which won't
1894 297e6e53 Guido Trotter
    #    affect the inside of the instance as well.
1895 297e6e53 Guido Trotter
    conf_hvp = instance.hvparams
1896 5905901c Iustin Pop
    name = instance.name
1897 5905901c Iustin Pop
    self._CheckDown(name)
1898 ee5f20b0 Guido Trotter
1899 ee5f20b0 Guido Trotter
    temp_files = []
1900 ee5f20b0 Guido Trotter
1901 41a878b5 Dimitris Aragiorgis
    kvm_cmd, kvm_nics, up_hvp, kvm_disks = kvm_runtime
1902 f0db563d Guido Trotter
    # the first element of kvm_cmd is always the path to the kvm binary
1903 f0db563d Guido Trotter
    kvm_path = kvm_cmd[0]
1904 297e6e53 Guido Trotter
    up_hvp = objects.FillDict(conf_hvp, up_hvp)
1905 ee5f20b0 Guido Trotter
1906 297e6e53 Guido Trotter
    # We know it's safe to run as a different user upon migration, so we'll use
1907 297e6e53 Guido Trotter
    # the latest conf, from conf_hvp.
1908 297e6e53 Guido Trotter
    security_model = conf_hvp[constants.HV_SECURITY_MODEL]
1909 cef34868 Guido Trotter
    if security_model == constants.HT_SM_USER:
1910 297e6e53 Guido Trotter
      kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
1911 cef34868 Guido Trotter
1912 839642c2 Iustin Pop
    keymap = conf_hvp[constants.HV_KEYMAP]
1913 839642c2 Iustin Pop
    if keymap:
1914 839642c2 Iustin Pop
      keymap_path = self._InstanceKeymapFile(name)
1915 839642c2 Iustin Pop
      # If a keymap file is specified, KVM won't use its internal defaults. By
1916 839642c2 Iustin Pop
      # first including the "en-us" layout, an error on loading the actual
1917 839642c2 Iustin Pop
      # layout (e.g. because it can't be found) won't lead to a non-functional
1918 839642c2 Iustin Pop
      # keyboard. A keyboard with incorrect keys is still better than none.
1919 839642c2 Iustin Pop
      utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
1920 839642c2 Iustin Pop
      kvm_cmd.extend(["-k", keymap_path])
1921 839642c2 Iustin Pop
1922 297e6e53 Guido Trotter
    # We have reasons to believe changing something like the nic driver/type
1923 297e6e53 Guido Trotter
    # upon migration won't exactly fly with the instance kernel, so for nic
1924 297e6e53 Guido Trotter
    # related parameters we'll use up_hvp
1925 5d9bfd87 Apollon Oikonomopoulos
    tapfds = []
1926 5d9bfd87 Apollon Oikonomopoulos
    taps = []
1927 43c6e76f Dimitris Aragiorgis
    devlist = self._GetKVMOutput(kvm_path, self._KVMOPT_DEVICELIST)
1928 ab0c6a39 Dimitris Aragiorgis
1929 ab0c6a39 Dimitris Aragiorgis
    bdev_opts = self._GenerateKVMBlockDevicesOptions(instance,
1930 ab0c6a39 Dimitris Aragiorgis
                                                     up_hvp,
1931 ab0c6a39 Dimitris Aragiorgis
                                                     kvm_disks,
1932 ab0c6a39 Dimitris Aragiorgis
                                                     kvmhelp,
1933 ab0c6a39 Dimitris Aragiorgis
                                                     devlist)
1934 ab0c6a39 Dimitris Aragiorgis
    kvm_cmd.extend(bdev_opts)
1935 ab0c6a39 Dimitris Aragiorgis
1936 ee5f20b0 Guido Trotter
    if not kvm_nics:
1937 fbe27e2b Guido Trotter
      kvm_cmd.extend(["-net", "none"])
1938 ee5f20b0 Guido Trotter
    else:
1939 5d9bfd87 Apollon Oikonomopoulos
      vnet_hdr = False
1940 fbe27e2b Guido Trotter
      tap_extra = ""
1941 297e6e53 Guido Trotter
      nic_type = up_hvp[constants.HV_NIC_TYPE]
1942 37f88dc6 Guido Trotter
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
1943 f0db563d Guido Trotter
        nic_model = self._VIRTIO
1944 f0db563d Guido Trotter
        try:
1945 a16f0d77 Dimitris Aragiorgis
          if self._VIRTIO_NET_RE.search(devlist):
1946 f0db563d Guido Trotter
            nic_model = self._VIRTIO_NET_PCI
1947 8a534fbe Stratos Psomdakis
            vnet_hdr = up_hvp[constants.HV_VNET_HDR]
1948 f0db563d Guido Trotter
        except errors.HypervisorError, _:
1949 f0db563d Guido Trotter
          # Older versions of kvm don't support DEVICE_LIST, but they don't
1950 f0db563d Guido Trotter
          # have new virtio syntax either.
1951 f0db563d Guido Trotter
          pass
1952 4b784cf8 Miguel Di Ciurcio Filho
1953 297e6e53 Guido Trotter
        if up_hvp[constants.HV_VHOST_NET]:
1954 3b59ec02 Guido Trotter
          # check for vhost_net support
1955 0ad7f5d8 Guido Trotter
          if self._VHOST_RE.search(kvmhelp):
1956 4b784cf8 Miguel Di Ciurcio Filho
            tap_extra = ",vhost=on"
1957 4b784cf8 Miguel Di Ciurcio Filho
          else:
1958 4b784cf8 Miguel Di Ciurcio Filho
            raise errors.HypervisorError("vhost_net is configured"
1959 5ae4945a Iustin Pop
                                         " but it is not available")
1960 37f88dc6 Guido Trotter
      else:
1961 4b784cf8 Miguel Di Ciurcio Filho
        nic_model = nic_type
1962 37f88dc6 Guido Trotter
1963 6f4070cd Guido Trotter
      kvm_supports_netdev = self._NETDEV_RE.search(kvmhelp)
1964 6f4070cd Guido Trotter
1965 ee5f20b0 Guido Trotter
      for nic_seq, nic in enumerate(kvm_nics):
1966 6f1e1921 Michael Hanselmann
        tapname, tapfd = _OpenTap(vnet_hdr=vnet_hdr)
1967 5d9bfd87 Apollon Oikonomopoulos
        tapfds.append(tapfd)
1968 5d9bfd87 Apollon Oikonomopoulos
        taps.append(tapname)
1969 6f4070cd Guido Trotter
        if kvm_supports_netdev:
1970 a7ccf635 Dimitris Aragiorgis
          nic_val = "%s,mac=%s" % (nic_model, nic.mac)
1971 a7ccf635 Dimitris Aragiorgis
          try:
1972 a7ccf635 Dimitris Aragiorgis
            # kvm_nics already exist in old runtime files and thus there might
1973 a7ccf635 Dimitris Aragiorgis
            # be some entries without pci slot (therefore try: except:)
1974 a7ccf635 Dimitris Aragiorgis
            kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_NIC, nic)
1975 a7ccf635 Dimitris Aragiorgis
            netdev = kvm_devid
1976 a7ccf635 Dimitris Aragiorgis
            nic_val += (",id=%s,bus=pci.0,addr=%s" % (kvm_devid, hex(nic.pci)))
1977 a7ccf635 Dimitris Aragiorgis
          except errors.HotplugError:
1978 a7ccf635 Dimitris Aragiorgis
            netdev = "netdev%d" % nic_seq
1979 a7ccf635 Dimitris Aragiorgis
          nic_val += (",netdev=%s" % netdev)
1980 a7ccf635 Dimitris Aragiorgis
          tap_val = ("type=tap,id=%s,fd=%d%s" %
1981 a7ccf635 Dimitris Aragiorgis
                     (netdev, tapfd, tap_extra))
1982 4b784cf8 Miguel Di Ciurcio Filho
          kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
1983 4b784cf8 Miguel Di Ciurcio Filho
        else:
1984 049383d9 Adeodato Simo
          nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq,
1985 049383d9 Adeodato Simo
                                                         nic.mac, nic_model)
1986 5d9bfd87 Apollon Oikonomopoulos
          tap_val = "tap,vlan=%s,fd=%d" % (nic_seq, tapfd)
1987 4b784cf8 Miguel Di Ciurcio Filho
          kvm_cmd.extend(["-net", tap_val, "-net", nic_val])
1988 ee5f20b0 Guido Trotter
1989 30e42c4e Guido Trotter
    if incoming:
1990 30e42c4e Guido Trotter
      target, port = incoming
1991 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])
1992 30e42c4e Guido Trotter
1993 297e6e53 Guido Trotter
    # Changing the vnc password doesn't bother the guest that much. At most it
1994 297e6e53 Guido Trotter
    # will surprise people who connect to it. Whether positively or negatively
1995 297e6e53 Guido Trotter
    # it's debatable.
1996 297e6e53 Guido Trotter
    vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
1997 6e6bb8d5 Guido Trotter
    vnc_pwd = None
1998 6e6bb8d5 Guido Trotter
    if vnc_pwd_file:
1999 6e6bb8d5 Guido Trotter
      try:
2000 682f7601 Guido Trotter
        vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
2001 6e6bb8d5 Guido Trotter
      except EnvironmentError, err:
2002 6e6bb8d5 Guido Trotter
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
2003 6e6bb8d5 Guido Trotter
                                     % (vnc_pwd_file, err))
2004 6e6bb8d5 Guido Trotter
2005 297e6e53 Guido Trotter
    if conf_hvp[constants.HV_KVM_USE_CHROOT]:
2006 547a63b7 Balazs Lecz
      utils.EnsureDirs([(self._InstanceChrootDir(name),
2007 547a63b7 Balazs Lecz
                         constants.SECURE_DIR_MODE)])
2008 547a63b7 Balazs Lecz
2009 91c10532 Andrea Spadaccini
    # Automatically enable QMP if version is >= 0.14
2010 0ad7f5d8 Guido Trotter
    if self._QMP_RE.search(kvmhelp):
2011 91c10532 Andrea Spadaccini
      logging.debug("Enabling QMP")
2012 91c10532 Andrea Spadaccini
      kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
2013 5ae4945a Iustin Pop
                      self._InstanceQmpMonitor(instance.name)])
2014 91c10532 Andrea Spadaccini
2015 cc8a8ed7 Apollon Oikonomopoulos
    # Configure the network now for starting instances and bridged interfaces,
2016 cc8a8ed7 Apollon Oikonomopoulos
    # during FinalizeMigration for incoming instances' routed interfaces
2017 cc8a8ed7 Apollon Oikonomopoulos
    for nic_seq, nic in enumerate(kvm_nics):
2018 cc8a8ed7 Apollon Oikonomopoulos
      if (incoming and
2019 cc8a8ed7 Apollon Oikonomopoulos
          nic.nicparams[constants.NIC_MODE] != constants.NIC_MODE_BRIDGED):
2020 cc8a8ed7 Apollon Oikonomopoulos
        continue
2021 cc8a8ed7 Apollon Oikonomopoulos
      self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
2022 5d9bfd87 Apollon Oikonomopoulos
2023 1d8a7812 Andrea Spadaccini
    # CPU affinity requires kvm to start paused, so we set this flag if the
2024 1d8a7812 Andrea Spadaccini
    # instance is not already paused and if we are not going to accept a
2025 1d8a7812 Andrea Spadaccini
    # migrating instance. In the latter case, pausing is not needed.
2026 1d8a7812 Andrea Spadaccini
    start_kvm_paused = not (_KVM_START_PAUSED_FLAG in kvm_cmd) and not incoming
2027 945a7e67 Guido Trotter
    if start_kvm_paused:
2028 945a7e67 Guido Trotter
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
2029 b693125f Tsachy Shacham
2030 b693125f Tsachy Shacham
    # Note: CPU pinning is using up_hvp since changes take effect
2031 b693125f Tsachy Shacham
    # during instance startup anyway, and to avoid problems when soft
2032 b693125f Tsachy Shacham
    # rebooting the instance.
2033 c607b1f7 Tsachy Shacham
    cpu_pinning = False
2034 b693125f Tsachy Shacham
    if up_hvp.get(constants.HV_CPU_MASK, None):
2035 b693125f Tsachy Shacham
      cpu_pinning = True
2036 b693125f Tsachy Shacham
2037 76431533 Guido Trotter
    if security_model == constants.HT_SM_POOL:
2038 76431533 Guido Trotter
      ss = ssconf.SimpleStore()
2039 76431533 Guido Trotter
      uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
2040 76431533 Guido Trotter
      all_uids = set(uidpool.ExpandUidPool(uid_pool))
2041 76431533 Guido Trotter
      uid = uidpool.RequestUnusedUid(all_uids)
2042 76431533 Guido Trotter
      try:
2043 76431533 Guido Trotter
        username = pwd.getpwuid(uid.GetUid()).pw_name
2044 76431533 Guido Trotter
        kvm_cmd.extend(["-runas", username])
2045 5d9bfd87 Apollon Oikonomopoulos
        self._RunKVMCmd(name, kvm_cmd, tapfds)
2046 76431533 Guido Trotter
      except:
2047 76431533 Guido Trotter
        uidpool.ReleaseUid(uid)
2048 76431533 Guido Trotter
        raise
2049 76431533 Guido Trotter
      else:
2050 76431533 Guido Trotter
        uid.Unlock()
2051 3af16328 Apollon Oikonomopoulos
        utils.WriteFile(self._InstanceUidFile(name), data=uid.AsStr())
2052 76431533 Guido Trotter
    else:
2053 5d9bfd87 Apollon Oikonomopoulos
      self._RunKVMCmd(name, kvm_cmd, tapfds)
2054 5d9bfd87 Apollon Oikonomopoulos
2055 5d9bfd87 Apollon Oikonomopoulos
    utils.EnsureDirs([(self._InstanceNICDir(instance.name),
2056 5d9bfd87 Apollon Oikonomopoulos
                     constants.RUN_DIRS_MODE)])
2057 5d9bfd87 Apollon Oikonomopoulos
    for nic_seq, tap in enumerate(taps):
2058 5d9bfd87 Apollon Oikonomopoulos
      utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
2059 5d9bfd87 Apollon Oikonomopoulos
                      data=tap)
2060 eb58f9b1 Guido Trotter
2061 6e6bb8d5 Guido Trotter
    if vnc_pwd:
2062 d0c8c01d Iustin Pop
      change_cmd = "change vnc password %s" % vnc_pwd
2063 6e6bb8d5 Guido Trotter
      self._CallMonitorCommand(instance.name, change_cmd)
2064 6e6bb8d5 Guido Trotter
2065 b451c4c7 Andrea Spadaccini
    # Setting SPICE password. We are not vulnerable to malicious passwordless
2066 b451c4c7 Andrea Spadaccini
    # connection attempts because SPICE by default does not allow connections
2067 b451c4c7 Andrea Spadaccini
    # if neither a password nor the "disable_ticketing" options are specified.
2068 b451c4c7 Andrea Spadaccini
    # As soon as we send the password via QMP, that password is a valid ticket
2069 b451c4c7 Andrea Spadaccini
    # for connection.
2070 b451c4c7 Andrea Spadaccini
    spice_password_file = conf_hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]
2071 b451c4c7 Andrea Spadaccini
    if spice_password_file:
2072 fc84cd5d Guido Trotter
      spice_pwd = ""
2073 b451c4c7 Andrea Spadaccini
      try:
2074 b451c4c7 Andrea Spadaccini
        spice_pwd = utils.ReadOneLineFile(spice_password_file, strict=True)
2075 b451c4c7 Andrea Spadaccini
      except EnvironmentError, err:
2076 b451c4c7 Andrea Spadaccini
        raise errors.HypervisorError("Failed to open SPICE password file %s: %s"
2077 b451c4c7 Andrea Spadaccini
                                     % (spice_password_file, err))
2078 b451c4c7 Andrea Spadaccini
2079 fc84cd5d Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
2080 fc84cd5d Guido Trotter
      qmp.connect()
2081 fc84cd5d Guido Trotter
      arguments = {
2082 fc84cd5d Guido Trotter
          "protocol": "spice",
2083 fc84cd5d Guido Trotter
          "password": spice_pwd,
2084 fc84cd5d Guido Trotter
      }
2085 fc84cd5d Guido Trotter
      qmp.Execute("set_password", arguments)
2086 fc84cd5d Guido Trotter
2087 08137f9e Iustin Pop
    for filename in temp_files:
2088 08137f9e Iustin Pop
      utils.RemoveFile(filename)
2089 eb58f9b1 Guido Trotter
2090 b693125f Tsachy Shacham
    # If requested, set CPU affinity and resume instance execution
2091 b693125f Tsachy Shacham
    if cpu_pinning:
2092 945a7e67 Guido Trotter
      self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK])
2093 945a7e67 Guido Trotter
2094 61eb1a46 Guido Trotter
    start_memory = self._InstanceStartupMemory(instance)
2095 61eb1a46 Guido Trotter
    if start_memory < instance.beparams[constants.BE_MAXMEM]:
2096 61eb1a46 Guido Trotter
      self.BalloonInstanceMemory(instance, start_memory)
2097 61eb1a46 Guido Trotter
2098 945a7e67 Guido Trotter
    if start_kvm_paused:
2099 2ed0e208 Iustin Pop
      # To control CPU pinning, ballooning, and vnc/spice passwords
2100 2ed0e208 Iustin Pop
      # the VM was started in a frozen state. If freezing was not
2101 2ed0e208 Iustin Pop
      # explicitly requested resume the vm status.
2102 945a7e67 Guido Trotter
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
2103 b693125f Tsachy Shacham
2104 323f9095 Stephen Shirley
  def StartInstance(self, instance, block_devices, startup_paused):
2105 ee5f20b0 Guido Trotter
    """Start an instance.
2106 ee5f20b0 Guido Trotter

2107 ee5f20b0 Guido Trotter
    """
2108 5905901c Iustin Pop
    self._CheckDown(instance.name)
2109 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2110 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2111 7238edb5 Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
2112 b73f1c59 Guido Trotter
                                           startup_paused, kvmhelp)
2113 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
2114 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
2115 ee5f20b0 Guido Trotter
2116 2a2d087a Michele Tartara
  def _CallMonitorCommand(self, instance_name, command, timeout=None):
2117 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
2118 6567aff3 Guido Trotter

2119 6567aff3 Guido Trotter
    """
2120 2a2d087a Michele Tartara
    if timeout is not None:
2121 2a2d087a Michele Tartara
      timeout_cmd = "timeout %s" % (timeout, )
2122 2a2d087a Michele Tartara
    else:
2123 2a2d087a Michele Tartara
      timeout_cmd = ""
2124 2a2d087a Michele Tartara
2125 eace6157 Michael Hanselmann
    # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
2126 eace6157 Michael Hanselmann
    # version. The monitor protocol is designed for human consumption, whereas
2127 eace6157 Michael Hanselmann
    # QMP is made for programmatic usage. In the worst case QMP can also
2128 eace6157 Michael Hanselmann
    # execute monitor commands. As it is, all calls to socat take at least
2129 eace6157 Michael Hanselmann
    # 500ms and likely more: socat can't detect the end of the reply and waits
2130 eace6157 Michael Hanselmann
    # for 500ms of no data received before exiting (500 ms is the default for
2131 eace6157 Michael Hanselmann
    # the "-t" parameter).
2132 874f6148 Michele Tartara
    socat = ("echo %s | %s %s STDIO UNIX-CONNECT:%s" %
2133 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
2134 874f6148 Michele Tartara
              timeout_cmd,
2135 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
2136 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
2137 874f6148 Michele Tartara
2138 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
2139 6567aff3 Guido Trotter
    if result.failed:
2140 afa9bb2e Michael Hanselmann
      msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
2141 afa9bb2e Michael Hanselmann
             " output: %s" %
2142 afa9bb2e Michael Hanselmann
             (command, instance_name, result.fail_reason, result.output))
2143 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
2144 6567aff3 Guido Trotter
2145 6567aff3 Guido Trotter
    return result
2146 6567aff3 Guido Trotter
2147 2615646c Dimitris Aragiorgis
  def _GetFreePCISlot(self, instance, dev):
2148 2615646c Dimitris Aragiorgis
    """Get the first available pci slot of a runnung instance.
2149 2615646c Dimitris Aragiorgis

2150 2615646c Dimitris Aragiorgis
    """
2151 2615646c Dimitris Aragiorgis
    slots = bitarray(32)
2152 2615646c Dimitris Aragiorgis
    slots.setall(False) # pylint: disable=E1101
2153 2615646c Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance.name, self._INFO_PCI_CMD)
2154 2615646c Dimitris Aragiorgis
    for line in output.stdout.splitlines():
2155 2615646c Dimitris Aragiorgis
      match = self._INFO_PCI_RE.search(line)
2156 2615646c Dimitris Aragiorgis
      if match:
2157 2615646c Dimitris Aragiorgis
        slot = int(match.group(1))
2158 2615646c Dimitris Aragiorgis
        slots[slot] = True
2159 2615646c Dimitris Aragiorgis
2160 d13fb3f1 Dimitris Aragiorgis
    dev.pci = _GetFreeSlot(slots)
2161 2615646c Dimitris Aragiorgis
2162 50e0f1d9 Dimitris Aragiorgis
  def VerifyHotplugSupport(self, instance, action, dev_type):
2163 50e0f1d9 Dimitris Aragiorgis
    """Verifies that hotplug is supported.
2164 97cd9092 Dimitris Aragiorgis

2165 97cd9092 Dimitris Aragiorgis
    Hotplug is *not* supported in case of:
2166 97cd9092 Dimitris Aragiorgis
     - security models and chroot (disk hotplug)
2167 97cd9092 Dimitris Aragiorgis
     - fdsend module is missing (nic hot-add)
2168 97cd9092 Dimitris Aragiorgis

2169 50e0f1d9 Dimitris Aragiorgis
    @raise errors.HypervisorError: in one of the previous cases
2170 97cd9092 Dimitris Aragiorgis

2171 97cd9092 Dimitris Aragiorgis
    """
2172 97cd9092 Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2173 97cd9092 Dimitris Aragiorgis
      hvp = instance.hvparams
2174 97cd9092 Dimitris Aragiorgis
      security_model = hvp[constants.HV_SECURITY_MODEL]
2175 97cd9092 Dimitris Aragiorgis
      use_chroot = hvp[constants.HV_KVM_USE_CHROOT]
2176 97cd9092 Dimitris Aragiorgis
      if use_chroot:
2177 97cd9092 Dimitris Aragiorgis
        raise errors.HotplugError("Disk hotplug is not supported"
2178 97cd9092 Dimitris Aragiorgis
                                  " in case of chroot.")
2179 97cd9092 Dimitris Aragiorgis
      if security_model != constants.HT_SM_NONE:
2180 97cd9092 Dimitris Aragiorgis
        raise errors.HotplugError("Disk Hotplug is not supported in case"
2181 97cd9092 Dimitris Aragiorgis
                                  " security models are used.")
2182 97cd9092 Dimitris Aragiorgis
2183 97cd9092 Dimitris Aragiorgis
    if (dev_type == constants.HOTPLUG_TARGET_NIC and
2184 97cd9092 Dimitris Aragiorgis
        action == constants.HOTPLUG_ACTION_ADD and not fdsend):
2185 97cd9092 Dimitris Aragiorgis
      raise errors.HotplugError("Cannot hot-add NIC."
2186 97cd9092 Dimitris Aragiorgis
                                " fdsend python module is missing.")
2187 97cd9092 Dimitris Aragiorgis
2188 24711492 Dimitris Aragiorgis
  def HotplugSupported(self, instance):
2189 24711492 Dimitris Aragiorgis
    """Checks if hotplug is generally supported.
2190 24711492 Dimitris Aragiorgis

2191 24711492 Dimitris Aragiorgis
    Hotplug is *not* supported in case of:
2192 24711492 Dimitris Aragiorgis
     - qemu versions < 1.0
2193 24711492 Dimitris Aragiorgis
     - for stopped instances
2194 24711492 Dimitris Aragiorgis

2195 24711492 Dimitris Aragiorgis
    @raise errors.HypervisorError: in one of the previous cases
2196 24711492 Dimitris Aragiorgis

2197 24711492 Dimitris Aragiorgis
    """
2198 96ed3a3e Dimitris Aragiorgis
    try:
2199 96ed3a3e Dimitris Aragiorgis
      output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD)
2200 96ed3a3e Dimitris Aragiorgis
    except errors.HypervisorError:
2201 96ed3a3e Dimitris Aragiorgis
      raise errors.HotplugError("Instance is probably down")
2202 96ed3a3e Dimitris Aragiorgis
2203 24711492 Dimitris Aragiorgis
    # TODO: search for netdev_add, drive_add, device_add.....
2204 24711492 Dimitris Aragiorgis
    match = self._INFO_VERSION_RE.search(output.stdout)
2205 24711492 Dimitris Aragiorgis
    if not match:
2206 96ed3a3e Dimitris Aragiorgis
      raise errors.HotplugError("Cannot parse qemu version via monitor")
2207 96ed3a3e Dimitris Aragiorgis
2208 24711492 Dimitris Aragiorgis
    v_major, v_min, _, _ = match.groups()
2209 24711492 Dimitris Aragiorgis
    if (int(v_major), int(v_min)) < (1, 0):
2210 24711492 Dimitris Aragiorgis
      raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0")
2211 24711492 Dimitris Aragiorgis
2212 89c10241 Dimitris Aragiorgis
  def _CallHotplugCommands(self, name, cmds):
2213 89c10241 Dimitris Aragiorgis
    for c in cmds:
2214 066f16b0 Dimitris Aragiorgis
      self._CallMonitorCommand(name, c)
2215 89c10241 Dimitris Aragiorgis
      time.sleep(1)
2216 97cd9092 Dimitris Aragiorgis
2217 066f16b0 Dimitris Aragiorgis
  def _VerifyHotplugCommand(self, instance_name, device, dev_type,
2218 066f16b0 Dimitris Aragiorgis
                            should_exist):
2219 066f16b0 Dimitris Aragiorgis
    """Checks if a previous hotplug command has succeeded.
2220 066f16b0 Dimitris Aragiorgis

2221 066f16b0 Dimitris Aragiorgis
    It issues info pci monitor command and checks depending on should_exist
2222 066f16b0 Dimitris Aragiorgis
    value if an entry with PCI slot and device ID is found or not.
2223 066f16b0 Dimitris Aragiorgis

2224 066f16b0 Dimitris Aragiorgis
    @raise errors.HypervisorError: if result is not the expected one
2225 066f16b0 Dimitris Aragiorgis

2226 066f16b0 Dimitris Aragiorgis
    """
2227 066f16b0 Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance_name, self._INFO_PCI_CMD)
2228 066f16b0 Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, device)
2229 066f16b0 Dimitris Aragiorgis
    match = \
2230 066f16b0 Dimitris Aragiorgis
      self._FIND_PCI_DEVICE_RE(device.pci, kvm_devid).search(output.stdout)
2231 066f16b0 Dimitris Aragiorgis
    if match and not should_exist:
2232 066f16b0 Dimitris Aragiorgis
      msg = "Device %s should have been removed but is still there" % kvm_devid
2233 066f16b0 Dimitris Aragiorgis
      raise errors.HypervisorError(msg)
2234 066f16b0 Dimitris Aragiorgis
2235 066f16b0 Dimitris Aragiorgis
    if not match and should_exist:
2236 066f16b0 Dimitris Aragiorgis
      msg = "Device %s should have been added but is missing" % kvm_devid
2237 066f16b0 Dimitris Aragiorgis
      raise errors.HypervisorError(msg)
2238 066f16b0 Dimitris Aragiorgis
2239 066f16b0 Dimitris Aragiorgis
    logging.info("Device %s has been correctly hot-plugged", kvm_devid)
2240 066f16b0 Dimitris Aragiorgis
2241 4b82125b Dimitris Aragiorgis
  def HotAddDevice(self, instance, dev_type, device, extra, seq):
2242 4b82125b Dimitris Aragiorgis
    """ Helper method to hot-add a new device
2243 4b82125b Dimitris Aragiorgis

2244 4b82125b Dimitris Aragiorgis
    It gets free pci slot generates the device name and invokes the
2245 4b82125b Dimitris Aragiorgis
    device specific method.
2246 4b82125b Dimitris Aragiorgis

2247 4b82125b Dimitris Aragiorgis
    """
2248 4b82125b Dimitris Aragiorgis
    # in case of hot-mod this is given
2249 4b82125b Dimitris Aragiorgis
    if device.pci is None:
2250 4b82125b Dimitris Aragiorgis
      self._GetFreePCISlot(instance, device)
2251 4b82125b Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, device)
2252 79f3e9e9 Dimitris Aragiorgis
    runtime = self._LoadKVMRuntime(instance.name)
2253 4b82125b Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2254 89c10241 Dimitris Aragiorgis
      cmds = ["drive_add dummy file=%s,if=none,id=%s,format=raw" %
2255 89c10241 Dimitris Aragiorgis
                (extra, kvm_devid)]
2256 89c10241 Dimitris Aragiorgis
      cmds += ["device_add virtio-blk-pci,bus=pci.0,addr=%s,drive=%s,id=%s" %
2257 89c10241 Dimitris Aragiorgis
                (hex(device.pci), kvm_devid, kvm_devid)]
2258 4b82125b Dimitris Aragiorgis
    elif dev_type == constants.HOTPLUG_TARGET_NIC:
2259 4b82125b Dimitris Aragiorgis
      (tap, fd) = _OpenTap()
2260 4b82125b Dimitris Aragiorgis
      self._ConfigureNIC(instance, seq, device, tap)
2261 4b82125b Dimitris Aragiorgis
      self._PassTapFd(instance, fd, device)
2262 89c10241 Dimitris Aragiorgis
      cmds = ["netdev_add tap,id=%s,fd=%s" % (kvm_devid, kvm_devid)]
2263 4b82125b Dimitris Aragiorgis
      args = "virtio-net-pci,bus=pci.0,addr=%s,mac=%s,netdev=%s,id=%s" % \
2264 4b82125b Dimitris Aragiorgis
               (hex(device.pci), device.mac, kvm_devid, kvm_devid)
2265 89c10241 Dimitris Aragiorgis
      cmds += ["device_add %s" % args]
2266 4b82125b Dimitris Aragiorgis
      utils.WriteFile(self._InstanceNICFile(instance.name, seq), data=tap)
2267 4b82125b Dimitris Aragiorgis
2268 89c10241 Dimitris Aragiorgis
    self._CallHotplugCommands(instance.name, cmds)
2269 066f16b0 Dimitris Aragiorgis
    self._VerifyHotplugCommand(instance.name, device, dev_type, True)
2270 4b82125b Dimitris Aragiorgis
    # update relevant entries in runtime file
2271 4b82125b Dimitris Aragiorgis
    index = _DEVICE_RUNTIME_INDEX[dev_type]
2272 4b82125b Dimitris Aragiorgis
    entry = _RUNTIME_ENTRY[dev_type](device, extra)
2273 4b82125b Dimitris Aragiorgis
    runtime[index].append(entry)
2274 4b82125b Dimitris Aragiorgis
    self._SaveKVMRuntime(instance, runtime)
2275 4b82125b Dimitris Aragiorgis
2276 4b82125b Dimitris Aragiorgis
  def HotDelDevice(self, instance, dev_type, device, _, seq):
2277 4b82125b Dimitris Aragiorgis
    """ Helper method for hot-del device
2278 4b82125b Dimitris Aragiorgis

2279 4b82125b Dimitris Aragiorgis
    It gets device info from runtime file, generates the device name and
2280 4b82125b Dimitris Aragiorgis
    invokes the device specific method.
2281 4b82125b Dimitris Aragiorgis

2282 4b82125b Dimitris Aragiorgis
    """
2283 79f3e9e9 Dimitris Aragiorgis
    runtime = self._LoadKVMRuntime(instance.name)
2284 4b82125b Dimitris Aragiorgis
    entry = _GetExistingDeviceInfo(dev_type, device, runtime)
2285 4b82125b Dimitris Aragiorgis
    kvm_device = _RUNTIME_DEVICE[dev_type](entry)
2286 4b82125b Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, kvm_device)
2287 4b82125b Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2288 89c10241 Dimitris Aragiorgis
      cmds = ["device_del %s" % kvm_devid]
2289 89c10241 Dimitris Aragiorgis
      cmds += ["drive_del %s" % kvm_devid]
2290 4b82125b Dimitris Aragiorgis
    elif dev_type == constants.HOTPLUG_TARGET_NIC:
2291 89c10241 Dimitris Aragiorgis
      cmds = ["device_del %s" % kvm_devid]
2292 89c10241 Dimitris Aragiorgis
      cmds += ["netdev_del %s" % kvm_devid]
2293 4b82125b Dimitris Aragiorgis
      utils.RemoveFile(self._InstanceNICFile(instance.name, seq))
2294 89c10241 Dimitris Aragiorgis
    self._CallHotplugCommands(instance.name, cmds)
2295 066f16b0 Dimitris Aragiorgis
    self._VerifyHotplugCommand(instance.name, kvm_device, dev_type, False)
2296 4b82125b Dimitris Aragiorgis
    index = _DEVICE_RUNTIME_INDEX[dev_type]
2297 4b82125b Dimitris Aragiorgis
    runtime[index].remove(entry)
2298 4b82125b Dimitris Aragiorgis
    self._SaveKVMRuntime(instance, runtime)
2299 4b82125b Dimitris Aragiorgis
2300 4b82125b Dimitris Aragiorgis
    return kvm_device.pci
2301 4b82125b Dimitris Aragiorgis
2302 4b82125b Dimitris Aragiorgis
  def HotModDevice(self, instance, dev_type, device, _, seq):
2303 4b82125b Dimitris Aragiorgis
    """ Helper method for hot-mod device
2304 4b82125b Dimitris Aragiorgis

2305 4b82125b Dimitris Aragiorgis
    It gets device info from runtime file, generates the device name and
2306 4b82125b Dimitris Aragiorgis
    invokes the device specific method. Currently only NICs support hot-mod
2307 4b82125b Dimitris Aragiorgis

2308 4b82125b Dimitris Aragiorgis
    """
2309 4b82125b Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_NIC:
2310 4b82125b Dimitris Aragiorgis
      # putting it back in the same pci slot
2311 4b82125b Dimitris Aragiorgis
      device.pci = self.HotDelDevice(instance, dev_type, device, _, seq)
2312 4b82125b Dimitris Aragiorgis
      self.HotAddDevice(instance, dev_type, device, _, seq)
2313 4b82125b Dimitris Aragiorgis
2314 4b82125b Dimitris Aragiorgis
  def _PassTapFd(self, instance, fd, nic):
2315 4b82125b Dimitris Aragiorgis
    """Pass file descriptor to kvm process via monitor socket using SCM_RIGHTS
2316 4b82125b Dimitris Aragiorgis

2317 4b82125b Dimitris Aragiorgis
    """
2318 4b82125b Dimitris Aragiorgis
    # TODO: factor out code related to unix sockets.
2319 4b82125b Dimitris Aragiorgis
    #       squash common parts between monitor and qmp
2320 4b82125b Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_NIC, nic)
2321 4b82125b Dimitris Aragiorgis
    command = "getfd %s\n" % kvm_devid
2322 4b82125b Dimitris Aragiorgis
    fds = [fd]
2323 4b82125b Dimitris Aragiorgis
    logging.info("%s", fds)
2324 4b82125b Dimitris Aragiorgis
    try:
2325 4b82125b Dimitris Aragiorgis
      monsock = MonitorSocket(self._InstanceMonitor(instance.name))
2326 4b82125b Dimitris Aragiorgis
      monsock.connect()
2327 4b82125b Dimitris Aragiorgis
      fdsend.sendfds(monsock.sock, command, fds=fds)
2328 4b82125b Dimitris Aragiorgis
    finally:
2329 4b82125b Dimitris Aragiorgis
      monsock.close()
2330 4b82125b Dimitris Aragiorgis
2331 b52d85c1 Guido Trotter
  @classmethod
2332 585c8187 Guido Trotter
  def _ParseKVMVersion(cls, text):
2333 585c8187 Guido Trotter
    """Parse the KVM version from the --help output.
2334 585c8187 Guido Trotter

2335 585c8187 Guido Trotter
    @type text: string
2336 585c8187 Guido Trotter
    @param text: output of kvm --help
2337 585c8187 Guido Trotter
    @return: (version, v_maj, v_min, v_rev)
2338 5c3d5dfd Iustin Pop
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
2339 585c8187 Guido Trotter

2340 585c8187 Guido Trotter
    """
2341 585c8187 Guido Trotter
    match = cls._VERSION_RE.search(text.splitlines()[0])
2342 585c8187 Guido Trotter
    if not match:
2343 585c8187 Guido Trotter
      raise errors.HypervisorError("Unable to get KVM version")
2344 585c8187 Guido Trotter
2345 585c8187 Guido Trotter
    v_all = match.group(0)
2346 585c8187 Guido Trotter
    v_maj = int(match.group(1))
2347 585c8187 Guido Trotter
    v_min = int(match.group(2))
2348 585c8187 Guido Trotter
    if match.group(4):
2349 585c8187 Guido Trotter
      v_rev = int(match.group(4))
2350 585c8187 Guido Trotter
    else:
2351 585c8187 Guido Trotter
      v_rev = 0
2352 585c8187 Guido Trotter
    return (v_all, v_maj, v_min, v_rev)
2353 585c8187 Guido Trotter
2354 585c8187 Guido Trotter
  @classmethod
2355 6e043e60 Guido Trotter
  def _GetKVMOutput(cls, kvm_path, option):
2356 6e043e60 Guido Trotter
    """Return the output of a kvm invocation
2357 e3b89628 Guido Trotter

2358 bc0fed4b Guido Trotter
    @type kvm_path: string
2359 bc0fed4b Guido Trotter
    @param kvm_path: path to the kvm executable
2360 bc0fed4b Guido Trotter
    @type option: a key of _KVMOPTS_CMDS
2361 bc0fed4b Guido Trotter
    @param option: kvm option to fetch the output from
2362 6e043e60 Guido Trotter
    @return: output a supported kvm invocation
2363 e3b89628 Guido Trotter
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
2364 e3b89628 Guido Trotter

2365 e3b89628 Guido Trotter
    """
2366 6e043e60 Guido Trotter
    assert option in cls._KVMOPTS_CMDS, "Invalid output option"
2367 6e043e60 Guido Trotter
2368 bc0fed4b Guido Trotter
    optlist, can_fail = cls._KVMOPTS_CMDS[option]
2369 bc0fed4b Guido Trotter
2370 bc0fed4b Guido Trotter
    result = utils.RunCmd([kvm_path] + optlist)
2371 bc0fed4b Guido Trotter
    if result.failed and not can_fail:
2372 af89fa76 Helga Velroyen
      raise errors.HypervisorError("Unable to get KVM %s output" %
2373 3ddc7650 Jose A. Lopes
                                    " ".join(optlist))
2374 e3b89628 Guido Trotter
    return result.output
2375 e3b89628 Guido Trotter
2376 e3b89628 Guido Trotter
  @classmethod
2377 3b59ec02 Guido Trotter
  def _GetKVMVersion(cls, kvm_path):
2378 d7e4a2b1 Andrea Spadaccini
    """Return the installed KVM version.
2379 b52d85c1 Guido Trotter

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

2383 b52d85c1 Guido Trotter
    """
2384 6e043e60 Guido Trotter
    return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
2385 82e3bf85 Dimitris Aragiorgis
2386 82e3bf85 Dimitris Aragiorgis
  @classmethod
2387 82e3bf85 Dimitris Aragiorgis
  def _GetDefaultMachineVersion(cls, kvm_path):
2388 82e3bf85 Dimitris Aragiorgis
    """Return the default hardware revision (e.g. pc-1.1)
2389 82e3bf85 Dimitris Aragiorgis

2390 82e3bf85 Dimitris Aragiorgis
    """
2391 6e043e60 Guido Trotter
    output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2392 82e3bf85 Dimitris Aragiorgis
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
2393 82e3bf85 Dimitris Aragiorgis
    if match:
2394 82e3bf85 Dimitris Aragiorgis
      return match.group(1)
2395 82e3bf85 Dimitris Aragiorgis
    else:
2396 82e3bf85 Dimitris Aragiorgis
      return "pc"
2397 82e3bf85 Dimitris Aragiorgis
2398 874f6148 Michele Tartara
  def StopInstance(self, instance, force=False, retry=False, name=None,
2399 874f6148 Michele Tartara
                   timeout=None):
2400 eb58f9b1 Guido Trotter
    """Stop an instance.
2401 eb58f9b1 Guido Trotter

2402 eb58f9b1 Guido Trotter
    """
2403 874f6148 Michele Tartara
    assert(timeout is None or force is not None)
2404 874f6148 Michele Tartara
2405 bbcf7ad0 Iustin Pop
    if name is not None and not force:
2406 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
2407 bbcf7ad0 Iustin Pop
    if name is None:
2408 bbcf7ad0 Iustin Pop
      name = instance.name
2409 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
2410 bbcf7ad0 Iustin Pop
    else:
2411 bbcf7ad0 Iustin Pop
      acpi = False
2412 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
2413 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
2414 bbcf7ad0 Iustin Pop
      if force or not acpi:
2415 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
2416 eb58f9b1 Guido Trotter
      else:
2417 874f6148 Michele Tartara
        self._CallMonitorCommand(name, "system_powerdown", timeout)
2418 eb58f9b1 Guido Trotter
2419 3889f749 Dimitris Aragiorgis
  @classmethod
2420 3889f749 Dimitris Aragiorgis
  def _UnconfigureInstanceNICs(cls, instance_name, info=None):
2421 3889f749 Dimitris Aragiorgis
    """Get runtime NICs of an instance and unconfigure them
2422 3889f749 Dimitris Aragiorgis

2423 3889f749 Dimitris Aragiorgis
    """
2424 3889f749 Dimitris Aragiorgis
    _, kvm_nics, __, ___ = cls._LoadKVMRuntime(instance_name, info)
2425 3889f749 Dimitris Aragiorgis
    for nic in kvm_nics:
2426 3889f749 Dimitris Aragiorgis
      cls._UnconfigureNic(instance_name, nic)
2427 3889f749 Dimitris Aragiorgis
2428 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
2429 8904b35c Guido Trotter
    """Cleanup after a stopped instance
2430 8904b35c Guido Trotter

2431 8904b35c Guido Trotter
    """
2432 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
2433 8904b35c Guido Trotter
    if pid > 0 and alive:
2434 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
2435 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
2436 eb58f9b1 Guido Trotter
2437 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
2438 eb58f9b1 Guido Trotter
    """Reboot an instance.
2439 eb58f9b1 Guido Trotter

2440 eb58f9b1 Guido Trotter
    """
2441 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
2442 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
2443 eb58f9b1 Guido Trotter
    # to shutdown and restart.
2444 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
2445 1f8b3a27 Guido Trotter
    if not alive:
2446 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
2447 78411c60 Iustin Pop
                                   " not running" % instance.name)
2448 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
2449 f02881e0 Guido Trotter
    # ...first load it...
2450 79f3e9e9 Dimitris Aragiorgis
    kvm_runtime = self._LoadKVMRuntime(instance.name)
2451 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
2452 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
2453 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
2454 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
2455 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
2456 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2457 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2458 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
2459 eb58f9b1 Guido Trotter
2460 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
2461 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
2462 30e42c4e Guido Trotter

2463 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2464 30e42c4e Guido Trotter
    @param instance: instance to be migrated
2465 30e42c4e Guido Trotter
    @rtype: string
2466 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
2467 30e42c4e Guido Trotter

2468 30e42c4e Guido Trotter
    """
2469 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
2470 30e42c4e Guido Trotter
2471 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
2472 30e42c4e Guido Trotter
    """Prepare to accept an instance.
2473 30e42c4e Guido Trotter

2474 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2475 30e42c4e Guido Trotter
    @param instance: instance to be accepted
2476 30e42c4e Guido Trotter
    @type info: string
2477 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
2478 30e42c4e Guido Trotter
    @type target: string
2479 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
2480 30e42c4e Guido Trotter

2481 30e42c4e Guido Trotter
    """
2482 79f3e9e9 Dimitris Aragiorgis
    kvm_runtime = self._LoadKVMRuntime(instance.name, serialized_runtime=info)
2483 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
2484 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2485 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2486 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
2487 b73f1c59 Guido Trotter
                            incoming=incoming_address)
2488 30e42c4e Guido Trotter
2489 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
2490 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
2491 30e42c4e Guido Trotter

2492 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
2493 30e42c4e Guido Trotter

2494 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2495 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
2496 30e42c4e Guido Trotter

2497 30e42c4e Guido Trotter
    """
2498 30e42c4e Guido Trotter
    if success:
2499 79f3e9e9 Dimitris Aragiorgis
      kvm_runtime = self._LoadKVMRuntime(instance.name, serialized_runtime=info)
2500 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
2501 5d9bfd87 Apollon Oikonomopoulos
2502 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
2503 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
2504 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
2505 cc8a8ed7 Apollon Oikonomopoulos
          continue
2506 5d9bfd87 Apollon Oikonomopoulos
        try:
2507 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
2508 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
2509 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
2510 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
2511 5d9bfd87 Apollon Oikonomopoulos
          continue
2512 5d9bfd87 Apollon Oikonomopoulos
        try:
2513 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
2514 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
2515 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
2516 5d9bfd87 Apollon Oikonomopoulos
2517 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
2518 30e42c4e Guido Trotter
    else:
2519 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
2520 30e42c4e Guido Trotter
2521 bc0a2284 Helga Velroyen
  def MigrateInstance(self, cluster_name, instance, target, live):
2522 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
2523 30e42c4e Guido Trotter

2524 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
2525 30e42c4e Guido Trotter
    currently running.
2526 30e42c4e Guido Trotter

2527 bc0a2284 Helga Velroyen
    @type cluster_name: string
2528 bc0a2284 Helga Velroyen
    @param cluster_name: name of the cluster
2529 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
2530 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
2531 30e42c4e Guido Trotter
    @type target: string
2532 30e42c4e Guido Trotter
    @param target: ip address of the target node
2533 30e42c4e Guido Trotter
    @type live: boolean
2534 30e42c4e Guido Trotter
    @param live: perform a live migration
2535 30e42c4e Guido Trotter

2536 30e42c4e Guido Trotter
    """
2537 58d38b02 Iustin Pop
    instance_name = instance.name
2538 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
2539 6a1434d7 Andrea Spadaccini
    _, _, alive = self._InstancePidAlive(instance_name)
2540 30e42c4e Guido Trotter
    if not alive:
2541 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
2542 30e42c4e Guido Trotter
2543 30e42c4e Guido Trotter
    if not live:
2544 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
2545 30e42c4e Guido Trotter
2546 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
2547 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
2548 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2549 e43d4f9f Apollon Oikonomopoulos
2550 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
2551 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
2552 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2553 e43d4f9f Apollon Oikonomopoulos
2554 d93e2477 Dimitris Aragiorgis
    migration_caps = instance.hvparams[constants.HV_KVM_MIGRATION_CAPS]
2555 d93e2477 Dimitris Aragiorgis
    if migration_caps:
2556 d93e2477 Dimitris Aragiorgis
      for c in migration_caps.split(_MIGRATION_CAPS_DELIM):
2557 d93e2477 Dimitris Aragiorgis
        migrate_command = ("migrate_set_capability %s on" % c)
2558 d93e2477 Dimitris Aragiorgis
        self._CallMonitorCommand(instance_name, migrate_command)
2559 d93e2477 Dimitris Aragiorgis
2560 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
2561 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
2562 30e42c4e Guido Trotter
2563 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
2564 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
2565 6a1434d7 Andrea Spadaccini

2566 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2567 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
2568 6a1434d7 Andrea Spadaccini
    @type success: bool
2569 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
2570 6a1434d7 Andrea Spadaccini
    @type live: bool
2571 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
2572 6a1434d7 Andrea Spadaccini

2573 6a1434d7 Andrea Spadaccini
    """
2574 6a1434d7 Andrea Spadaccini
    if success:
2575 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
2576 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
2577 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
2578 6a1434d7 Andrea Spadaccini
    elif live:
2579 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
2580 6a1434d7 Andrea Spadaccini
2581 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
2582 6a1434d7 Andrea Spadaccini
    """Get the migration status
2583 6a1434d7 Andrea Spadaccini

2584 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2585 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
2586 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
2587 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
2588 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
2589 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
2590 6a1434d7 Andrea Spadaccini

2591 6a1434d7 Andrea Spadaccini
    """
2592 d0c8c01d Iustin Pop
    info_command = "info migrate"
2593 6a1434d7 Andrea Spadaccini
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
2594 6a1434d7 Andrea Spadaccini
      result = self._CallMonitorCommand(instance.name, info_command)
2595 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
2596 30e42c4e Guido Trotter
      if not match:
2597 c4e388a5 Guido Trotter
        if not result.stdout:
2598 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
2599 c4e388a5 Guido Trotter
        else:
2600 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
2601 c4e388a5 Guido Trotter
                          result.stdout)
2602 30e42c4e Guido Trotter
      else:
2603 30e42c4e Guido Trotter
        status = match.group(1)
2604 6a1434d7 Andrea Spadaccini
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
2605 6a1434d7 Andrea Spadaccini
          migration_status = objects.MigrationStatus(status=status)
2606 61643226 Andrea Spadaccini
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
2607 61643226 Andrea Spadaccini
          if match:
2608 61643226 Andrea Spadaccini
            migration_status.transferred_ram = match.group("transferred")
2609 61643226 Andrea Spadaccini
            migration_status.total_ram = match.group("total")
2610 61643226 Andrea Spadaccini
2611 6a1434d7 Andrea Spadaccini
          return migration_status
2612 30e42c4e Guido Trotter
2613 6a1434d7 Andrea Spadaccini
        logging.warning("KVM: unknown migration status '%s'", status)
2614 6a1434d7 Andrea Spadaccini
2615 6a1434d7 Andrea Spadaccini
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
2616 6a1434d7 Andrea Spadaccini
2617 62457f51 Iustin Pop
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
2618 30e42c4e Guido Trotter
2619 3d836750 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
2620 3d836750 Guido Trotter
    """Balloon an instance memory to a certain value.
2621 3d836750 Guido Trotter

2622 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
2623 3d836750 Guido Trotter
    @param instance: instance to be accepted
2624 3d836750 Guido Trotter
    @type mem: int
2625 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
2626 3d836750 Guido Trotter

2627 3d836750 Guido Trotter
    """
2628 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2629 3d836750 Guido Trotter
2630 fac489a5 Helga Velroyen
  def GetNodeInfo(self, hvparams=None):
2631 eb58f9b1 Guido Trotter
    """Return information about the node.
2632 eb58f9b1 Guido Trotter

2633 fac489a5 Helga Velroyen
    @type hvparams: dict of strings
2634 fac489a5 Helga Velroyen
    @param hvparams: hypervisor parameters, not used in this class
2635 fac489a5 Helga Velroyen

2636 ef14e128 Bernardo Dal Seno
    @return: a dict as returned by L{BaseHypervisor.GetLinuxNodeInfo} plus
2637 ef14e128 Bernardo Dal Seno
        the following keys:
2638 34fbc862 Andrea Spadaccini
          - hv_version: the hypervisor version in the form (major, minor,
2639 34fbc862 Andrea Spadaccini
                        revision)
2640 eb58f9b1 Guido Trotter

2641 eb58f9b1 Guido Trotter
    """
2642 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
2643 25bce647 Santi Raffa
    kvmpath = constants.KVM_PATH
2644 25bce647 Santi Raffa
    if hvparams is not None:
2645 25bce647 Santi Raffa
      kvmpath = hvparams.get(constants.HV_KVM_PATH, constants.KVM_PATH)
2646 25bce647 Santi Raffa
    _, v_major, v_min, v_rev = self._GetKVMVersion(kvmpath)
2647 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2648 34fbc862 Andrea Spadaccini
    return result
2649 eb58f9b1 Guido Trotter
2650 637ce7f9 Guido Trotter
  @classmethod
2651 1c3231aa Thomas Thrainer
  def GetInstanceConsole(cls, instance, primary_node, hvparams, beparams):
2652 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
2653 eb58f9b1 Guido Trotter

2654 eb58f9b1 Guido Trotter
    """
2655 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2656 9d9bded1 Michael Hanselmann
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2657 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2658 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2659 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
2660 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2661 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2662 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
2663 1c3231aa Thomas Thrainer
                                     host=primary_node.name,
2664 052783ff Michael Hanselmann
                                     user=constants.SSH_CONSOLE_USER,
2665 55cc0a44 Michael Hanselmann
                                     command=cmd)
2666 3be34f57 Guido Trotter
2667 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2668 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2669 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
2670 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2671 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
2672 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
2673 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
2674 55cc0a44 Michael Hanselmann
                                     display=display)
2675 55cc0a44 Michael Hanselmann
2676 4d2cdb5a Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2677 4d2cdb5a Andrea Spadaccini
    if spice_bind:
2678 4d2cdb5a Andrea Spadaccini
      return objects.InstanceConsole(instance=instance.name,
2679 4d2cdb5a Andrea Spadaccini
                                     kind=constants.CONS_SPICE,
2680 4d2cdb5a Andrea Spadaccini
                                     host=spice_bind,
2681 4d2cdb5a Andrea Spadaccini
                                     port=instance.network_port)
2682 4d2cdb5a Andrea Spadaccini
2683 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
2684 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
2685 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
2686 55cc0a44 Michael Hanselmann
                                            instance.name))
2687 eb58f9b1 Guido Trotter
2688 75bf3149 Helga Velroyen
  def Verify(self, hvparams=None):
2689 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
2690 eb58f9b1 Guido Trotter

2691 cd04dfd2 Michael Hanselmann
    Check that the required binaries exist.
2692 cd04dfd2 Michael Hanselmann

2693 75bf3149 Helga Velroyen
    @type hvparams: dict of strings
2694 75bf3149 Helga Velroyen
    @param hvparams: hypervisor parameters to be verified against, not used here
2695 75bf3149 Helga Velroyen

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

2698 eb58f9b1 Guido Trotter
    """
2699 1f4b9d39 Iustin Pop
    msgs = []
2700 25bce647 Santi Raffa
    kvmpath = constants.KVM_PATH
2701 25bce647 Santi Raffa
    if hvparams is not None:
2702 25bce647 Santi Raffa
      kvmpath = hvparams.get(constants.HV_KVM_PATH, constants.KVM_PATH)
2703 25bce647 Santi Raffa
    if not os.path.exists(kvmpath):
2704 25bce647 Santi Raffa
      msgs.append("The KVM binary ('%s') does not exist" % kvmpath)
2705 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2706 1f4b9d39 Iustin Pop
      msgs.append("The socat binary ('%s') does not exist" %
2707 1f4b9d39 Iustin Pop
                  constants.SOCAT_PATH)
2708 1f4b9d39 Iustin Pop
2709 1f4b9d39 Iustin Pop
    return self._FormatVerifyResults(msgs)
2710 14aa53cb Guido Trotter
2711 6b5605e8 Iustin Pop
  @classmethod
2712 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2713 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2714 6b5605e8 Iustin Pop

2715 6b5605e8 Iustin Pop
    @type hvparams:  dict
2716 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2717 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2718 6b5605e8 Iustin Pop

2719 6b5605e8 Iustin Pop
    """
2720 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2721 6b5605e8 Iustin Pop
2722 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
2723 df5ab9f0 Guido Trotter
    if kernel_path:
2724 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
2725 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
2726 205ab586 Iustin Pop
                                     " if a kernel is defined")
2727 6b5605e8 Iustin Pop
2728 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
2729 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
2730 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
2731 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
2732 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
2733 66d5dbef Guido Trotter
2734 14fd6c81 Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2735 14fd6c81 Guido Trotter
      serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2736 14fd6c81 Guido Trotter
      valid_speeds = constants.VALID_SERIAL_SPEEDS
2737 14fd6c81 Guido Trotter
      if not serial_speed or serial_speed not in valid_speeds:
2738 14fd6c81 Guido Trotter
        raise errors.HypervisorError("Invalid serial console speed, must be"
2739 14fd6c81 Guido Trotter
                                     " one of: %s" %
2740 14fd6c81 Guido Trotter
                                     utils.CommaJoin(valid_speeds))
2741 14fd6c81 Guido Trotter
2742 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2743 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
2744 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2745 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2746 835528af Iustin Pop
                                   " ISO path")
2747 f5118ade Iustin Pop
2748 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2749 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2750 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
2751 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
2752 d19d94db Guido Trotter
                                     " must be specified")
2753 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
2754 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
2755 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
2756 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
2757 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
2758 d19d94db Guido Trotter
2759 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2760 b451c4c7 Andrea Spadaccini
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2761 b1cb62bd Andrea Spadaccini
    if spice_bind:
2762 b1cb62bd Andrea Spadaccini
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2763 b1cb62bd Andrea Spadaccini
        # if an IP version is specified, the spice_bind parameter must be an
2764 b1cb62bd Andrea Spadaccini
        # IP of that family
2765 b1cb62bd Andrea Spadaccini
        if (netutils.IP4Address.IsValid(spice_bind) and
2766 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP4_VERSION):
2767 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv4 address (%s), but"
2768 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2769 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2770 b1cb62bd Andrea Spadaccini
2771 b1cb62bd Andrea Spadaccini
        if (netutils.IP6Address.IsValid(spice_bind) and
2772 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP6_VERSION):
2773 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv6 address (%s), but"
2774 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2775 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2776 b451c4c7 Andrea Spadaccini
    else:
2777 0e1b03b9 Andrea Spadaccini
      # All the other SPICE parameters depend on spice_bind being set. Raise an
2778 0e1b03b9 Andrea Spadaccini
      # error if any of them is set without it.
2779 07788a0b Michael Hanselmann
      for param in _SPICE_ADDITIONAL_PARAMS:
2780 0e1b03b9 Andrea Spadaccini
        if hvparams[param]:
2781 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: %s requires %s to be set" %
2782 0e1b03b9 Andrea Spadaccini
                                       (param, constants.HV_KVM_SPICE_BIND))
2783 b1cb62bd Andrea Spadaccini
2784 d19d94db Guido Trotter
  @classmethod
2785 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
2786 d19d94db Guido Trotter
    """Check the given parameters for validity.
2787 d19d94db Guido Trotter

2788 d19d94db Guido Trotter
    @type hvparams:  dict
2789 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2790 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2791 d19d94db Guido Trotter

2792 d19d94db Guido Trotter
    """
2793 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2794 d19d94db Guido Trotter
2795 82e3bf85 Dimitris Aragiorgis
    kvm_path = hvparams[constants.HV_KVM_PATH]
2796 82e3bf85 Dimitris Aragiorgis
2797 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2798 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2799 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2800 d19d94db Guido Trotter
      try:
2801 1feb39ec Guido Trotter
        pwd.getpwnam(username)
2802 d19d94db Guido Trotter
      except KeyError:
2803 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
2804 d19d94db Guido Trotter
                                     % username)
2805 d6e5767e Klaus Aehlig
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2806 d6e5767e Klaus Aehlig
    if vnc_bind_address:
2807 d6e5767e Klaus Aehlig
      bound_to_addr = netutils.IP4Address.IsValid(vnc_bind_address)
2808 d6e5767e Klaus Aehlig
      is_interface = netutils.IsValidInterface(vnc_bind_address)
2809 d6e5767e Klaus Aehlig
      is_path = utils.IsNormAbsPath(vnc_bind_address)
2810 d6e5767e Klaus Aehlig
      if not bound_to_addr and not is_interface and not is_path:
2811 d6e5767e Klaus Aehlig
        raise errors.HypervisorError("VNC: The %s parameter must be either"
2812 d6e5767e Klaus Aehlig
                                     " a valid IP address, an interface name,"
2813 d6e5767e Klaus Aehlig
                                     " or an absolute path" %
2814 d6e5767e Klaus Aehlig
                                     constants.HV_KVM_SPICE_BIND)
2815 d19d94db Guido Trotter
2816 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2817 b1cb62bd Andrea Spadaccini
    if spice_bind:
2818 b1cb62bd Andrea Spadaccini
      # only one of VNC and SPICE can be used currently.
2819 b1cb62bd Andrea Spadaccini
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2820 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("Both SPICE and VNC are configured, but"
2821 b1cb62bd Andrea Spadaccini
                                     " only one of them can be used at a"
2822 afa9bb2e Michael Hanselmann
                                     " given time")
2823 b1cb62bd Andrea Spadaccini
2824 3b59ec02 Guido Trotter
      # check that KVM supports SPICE
2825 6e043e60 Guido Trotter
      kvmhelp = cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP)
2826 0ad7f5d8 Guido Trotter
      if not cls._SPICE_RE.search(kvmhelp):
2827 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE is configured, but it is not"
2828 afa9bb2e Michael Hanselmann
                                     " supported according to 'kvm --help'")
2829 b1cb62bd Andrea Spadaccini
2830 b1cb62bd Andrea Spadaccini
      # if spice_bind is not an IP address, it must be a valid interface
2831 afa9bb2e Michael Hanselmann
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind) or
2832 afa9bb2e Michael Hanselmann
                       netutils.IP6Address.IsValid(spice_bind))
2833 b1cb62bd Andrea Spadaccini
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2834 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE: The %s parameter must be either"
2835 b1cb62bd Andrea Spadaccini
                                     " a valid IP address or interface name" %
2836 b1cb62bd Andrea Spadaccini
                                     constants.HV_KVM_SPICE_BIND)
2837 b1cb62bd Andrea Spadaccini
2838 82e3bf85 Dimitris Aragiorgis
    machine_version = hvparams[constants.HV_KVM_MACHINE_VERSION]
2839 82e3bf85 Dimitris Aragiorgis
    if machine_version:
2840 6e043e60 Guido Trotter
      output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2841 82e3bf85 Dimitris Aragiorgis
      if not cls._CHECK_MACHINE_VERSION_RE(machine_version).search(output):
2842 82e3bf85 Dimitris Aragiorgis
        raise errors.HypervisorError("Unsupported machine version: %s" %
2843 82e3bf85 Dimitris Aragiorgis
                                     machine_version)
2844 82e3bf85 Dimitris Aragiorgis
2845 f5118ade Iustin Pop
  @classmethod
2846 8ef418bb Helga Velroyen
  def PowercycleNode(cls, hvparams=None):
2847 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
2848 f5118ade Iustin Pop

2849 8ef418bb Helga Velroyen
    @type hvparams: dict of strings
2850 8ef418bb Helga Velroyen
    @param hvparams: hypervisor params to be used on this node
2851 8ef418bb Helga Velroyen

2852 f5118ade Iustin Pop
    """
2853 f5118ade Iustin Pop
    cls.LinuxPowercycle()