Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 185192f2

History | View | Annotate | Download (103.8 kB)

1 eb58f9b1 Guido Trotter
#
2 eb58f9b1 Guido Trotter
#
3 eb58f9b1 Guido Trotter
4 472cc1e9 Jose A. Lopes
# Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 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 27b6654e Jose A. Lopes
import urllib2
38 91c10532 Andrea Spadaccini
import socket
39 fc84cd5d Guido Trotter
import stat
40 91c10532 Andrea Spadaccini
import StringIO
41 2615646c Dimitris Aragiorgis
from bitarray import bitarray
42 b693125f Tsachy Shacham
try:
43 471a31b6 Andrea Spadaccini
  import affinity   # pylint: disable=F0401
44 b693125f Tsachy Shacham
except ImportError:
45 b693125f Tsachy Shacham
  affinity = None
46 97cd9092 Dimitris Aragiorgis
try:
47 97cd9092 Dimitris Aragiorgis
  import fdsend   # pylint: disable=F0401
48 97cd9092 Dimitris Aragiorgis
except ImportError:
49 97cd9092 Dimitris Aragiorgis
  fdsend = None
50 eb58f9b1 Guido Trotter
51 eb58f9b1 Guido Trotter
from ganeti import utils
52 eb58f9b1 Guido Trotter
from ganeti import constants
53 eb58f9b1 Guido Trotter
from ganeti import errors
54 38e250ba Guido Trotter
from ganeti import serializer
55 38e250ba Guido Trotter
from ganeti import objects
56 76431533 Guido Trotter
from ganeti import uidpool
57 76431533 Guido Trotter
from ganeti import ssconf
58 a744b676 Manuel Franceschini
from ganeti import netutils
59 9d9bded1 Michael Hanselmann
from ganeti import pathutils
60 9d9bded1 Michael Hanselmann
from ganeti.hypervisor import hv_base
61 5d9bfd87 Apollon Oikonomopoulos
from ganeti.utils import wrapper as utils_wrapper
62 eb58f9b1 Guido Trotter
63 eb58f9b1 Guido Trotter
64 0e1e0b6a Michael Hanselmann
_KVM_NETWORK_SCRIPT = pathutils.CONF_DIR + "/kvm-vif-bridge"
65 b693125f Tsachy Shacham
_KVM_START_PAUSED_FLAG = "-S"
66 748e4b5a Michael Hanselmann
67 199b2053 Apollon Oikonomopoulos
# TUN/TAP driver constants, taken from <linux/if_tun.h>
68 199b2053 Apollon Oikonomopoulos
# They are architecture-independent and already hardcoded in qemu-kvm source,
69 199b2053 Apollon Oikonomopoulos
# so we can safely include them here.
70 199b2053 Apollon Oikonomopoulos
TUNSETIFF = 0x400454ca
71 199b2053 Apollon Oikonomopoulos
TUNGETIFF = 0x800454d2
72 199b2053 Apollon Oikonomopoulos
TUNGETFEATURES = 0x800454cf
73 199b2053 Apollon Oikonomopoulos
IFF_TAP = 0x0002
74 199b2053 Apollon Oikonomopoulos
IFF_NO_PI = 0x1000
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 937ff984 Dimitris Aragiorgis
_MIGRATION_CAPS_DELIM = ":"
119 937ff984 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 2615646c 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 0fe22ad2 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 89473be8 Jose A. Lopes
def _OpenTap(vnet_hdr=True, name=""):
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 89473be8 Jose A. Lopes

304 89473be8 Jose A. Lopes
  @type name: string
305 89473be8 Jose A. Lopes
  @param name: name for the TAP interface being created; if an empty
306 89473be8 Jose A. Lopes
               string is passed, the OS will generate a unique name
307 89473be8 Jose A. Lopes

308 199b2053 Apollon Oikonomopoulos
  @return: (ifname, tapfd)
309 199b2053 Apollon Oikonomopoulos
  @rtype: tuple
310 199b2053 Apollon Oikonomopoulos

311 199b2053 Apollon Oikonomopoulos
  """
312 199b2053 Apollon Oikonomopoulos
  try:
313 199b2053 Apollon Oikonomopoulos
    tapfd = os.open("/dev/net/tun", os.O_RDWR)
314 199b2053 Apollon Oikonomopoulos
  except EnvironmentError:
315 199b2053 Apollon Oikonomopoulos
    raise errors.HypervisorError("Failed to open /dev/net/tun")
316 199b2053 Apollon Oikonomopoulos
317 199b2053 Apollon Oikonomopoulos
  flags = IFF_TAP | IFF_NO_PI
318 199b2053 Apollon Oikonomopoulos
319 199b2053 Apollon Oikonomopoulos
  if vnet_hdr and _ProbeTapVnetHdr(tapfd):
320 199b2053 Apollon Oikonomopoulos
    flags |= IFF_VNET_HDR
321 199b2053 Apollon Oikonomopoulos
322 199b2053 Apollon Oikonomopoulos
  # The struct ifreq ioctl request (see netdevice(7))
323 89473be8 Jose A. Lopes
  ifr = struct.pack("16sh", name, flags)
324 199b2053 Apollon Oikonomopoulos
325 199b2053 Apollon Oikonomopoulos
  try:
326 199b2053 Apollon Oikonomopoulos
    res = fcntl.ioctl(tapfd, TUNSETIFF, ifr)
327 6f1e1921 Michael Hanselmann
  except EnvironmentError, err:
328 6f1e1921 Michael Hanselmann
    raise errors.HypervisorError("Failed to allocate a new TAP device: %s" %
329 6f1e1921 Michael Hanselmann
                                 err)
330 199b2053 Apollon Oikonomopoulos
331 199b2053 Apollon Oikonomopoulos
  # Get the interface name from the ioctl
332 199b2053 Apollon Oikonomopoulos
  ifname = struct.unpack("16sh", res)[0].strip("\x00")
333 199b2053 Apollon Oikonomopoulos
  return (ifname, tapfd)
334 199b2053 Apollon Oikonomopoulos
335 748e4b5a Michael Hanselmann
336 364e1664 Jose A. Lopes
class HeadRequest(urllib2.Request):
337 364e1664 Jose A. Lopes
  def get_method(self):
338 364e1664 Jose A. Lopes
    return "HEAD"
339 364e1664 Jose A. Lopes
340 364e1664 Jose A. Lopes
341 27b6654e Jose A. Lopes
def _CheckUrl(url):
342 27b6654e Jose A. Lopes
  """Check if a given URL exists on the server
343 27b6654e Jose A. Lopes

344 27b6654e Jose A. Lopes
  """
345 27b6654e Jose A. Lopes
  try:
346 364e1664 Jose A. Lopes
    urllib2.urlopen(HeadRequest(url))
347 364e1664 Jose A. Lopes
    return True
348 27b6654e Jose A. Lopes
  except urllib2.URLError:
349 27b6654e Jose A. Lopes
    return False
350 27b6654e Jose A. Lopes
351 27b6654e Jose A. Lopes
352 91c10532 Andrea Spadaccini
class QmpMessage:
353 91c10532 Andrea Spadaccini
  """QEMU Messaging Protocol (QMP) message.
354 91c10532 Andrea Spadaccini

355 91c10532 Andrea Spadaccini
  """
356 91c10532 Andrea Spadaccini
  def __init__(self, data):
357 91c10532 Andrea Spadaccini
    """Creates a new QMP message based on the passed data.
358 91c10532 Andrea Spadaccini

359 91c10532 Andrea Spadaccini
    """
360 91c10532 Andrea Spadaccini
    if not isinstance(data, dict):
361 91c10532 Andrea Spadaccini
      raise TypeError("QmpMessage must be initialized with a dict")
362 91c10532 Andrea Spadaccini
363 91c10532 Andrea Spadaccini
    self.data = data
364 91c10532 Andrea Spadaccini
365 91c10532 Andrea Spadaccini
  def __getitem__(self, field_name):
366 91c10532 Andrea Spadaccini
    """Get the value of the required field if present, or None.
367 91c10532 Andrea Spadaccini

368 91c10532 Andrea Spadaccini
    Overrides the [] operator to provide access to the message data,
369 91c10532 Andrea Spadaccini
    returning None if the required item is not in the message
370 91c10532 Andrea Spadaccini
    @return: the value of the field_name field, or None if field_name
371 91c10532 Andrea Spadaccini
             is not contained in the message
372 91c10532 Andrea Spadaccini

373 91c10532 Andrea Spadaccini
    """
374 9b87c2cf Michael Hanselmann
    return self.data.get(field_name, None)
375 91c10532 Andrea Spadaccini
376 91c10532 Andrea Spadaccini
  def __setitem__(self, field_name, field_value):
377 91c10532 Andrea Spadaccini
    """Set the value of the required field_name to field_value.
378 91c10532 Andrea Spadaccini

379 91c10532 Andrea Spadaccini
    """
380 91c10532 Andrea Spadaccini
    self.data[field_name] = field_value
381 91c10532 Andrea Spadaccini
382 5e34123e Michele Tartara
  def __len__(self):
383 5e34123e Michele Tartara
    """Return the number of fields stored in this QmpMessage.
384 5e34123e Michele Tartara

385 5e34123e Michele Tartara
    """
386 5e34123e Michele Tartara
    return len(self.data)
387 5e34123e Michele Tartara
388 5e34123e Michele Tartara
  def __delitem__(self, key):
389 5e34123e Michele Tartara
    """Delete the specified element from the QmpMessage.
390 5e34123e Michele Tartara

391 5e34123e Michele Tartara
    """
392 5e34123e Michele Tartara
    del(self.data[key])
393 5e34123e Michele Tartara
394 91c10532 Andrea Spadaccini
  @staticmethod
395 91c10532 Andrea Spadaccini
  def BuildFromJsonString(json_string):
396 91c10532 Andrea Spadaccini
    """Build a QmpMessage from a JSON encoded string.
397 91c10532 Andrea Spadaccini

398 91c10532 Andrea Spadaccini
    @type json_string: str
399 91c10532 Andrea Spadaccini
    @param json_string: JSON string representing the message
400 91c10532 Andrea Spadaccini
    @rtype: L{QmpMessage}
401 91c10532 Andrea Spadaccini
    @return: a L{QmpMessage} built from json_string
402 91c10532 Andrea Spadaccini

403 91c10532 Andrea Spadaccini
    """
404 91c10532 Andrea Spadaccini
    # Parse the string
405 91c10532 Andrea Spadaccini
    data = serializer.LoadJson(json_string)
406 91c10532 Andrea Spadaccini
    return QmpMessage(data)
407 91c10532 Andrea Spadaccini
408 91c10532 Andrea Spadaccini
  def __str__(self):
409 a182a3ed Michael Hanselmann
    # The protocol expects the JSON object to be sent as a single line.
410 a182a3ed Michael Hanselmann
    return serializer.DumpJson(self.data)
411 91c10532 Andrea Spadaccini
412 91c10532 Andrea Spadaccini
  def __eq__(self, other):
413 91c10532 Andrea Spadaccini
    # When comparing two QmpMessages, we are interested in comparing
414 91c10532 Andrea Spadaccini
    # their internal representation of the message data
415 91c10532 Andrea Spadaccini
    return self.data == other.data
416 91c10532 Andrea Spadaccini
417 91c10532 Andrea Spadaccini
418 cad837b9 Dimitris Aragiorgis
class MonitorSocket(object):
419 91c10532 Andrea Spadaccini
  _SOCKET_TIMEOUT = 5
420 91c10532 Andrea Spadaccini
421 91c10532 Andrea Spadaccini
  def __init__(self, monitor_filename):
422 cad837b9 Dimitris Aragiorgis
    """Instantiates the MonitorSocket object.
423 91c10532 Andrea Spadaccini

424 91c10532 Andrea Spadaccini
    @type monitor_filename: string
425 91c10532 Andrea Spadaccini
    @param monitor_filename: the filename of the UNIX raw socket on which the
426 cad837b9 Dimitris Aragiorgis
                             monitor (QMP or simple one) is listening
427 91c10532 Andrea Spadaccini

428 91c10532 Andrea Spadaccini
    """
429 91c10532 Andrea Spadaccini
    self.monitor_filename = monitor_filename
430 91c10532 Andrea Spadaccini
    self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
431 91c10532 Andrea Spadaccini
    # We want to fail if the server doesn't send a complete message
432 91c10532 Andrea Spadaccini
    # in a reasonable amount of time
433 91c10532 Andrea Spadaccini
    self.sock.settimeout(self._SOCKET_TIMEOUT)
434 91c10532 Andrea Spadaccini
    self._connected = False
435 91c10532 Andrea Spadaccini
436 fc84cd5d Guido Trotter
  def _check_socket(self):
437 fc84cd5d Guido Trotter
    sock_stat = None
438 fc84cd5d Guido Trotter
    try:
439 fc84cd5d Guido Trotter
      sock_stat = os.stat(self.monitor_filename)
440 fc84cd5d Guido Trotter
    except EnvironmentError, err:
441 fc84cd5d Guido Trotter
      if err.errno == errno.ENOENT:
442 cad837b9 Dimitris Aragiorgis
        raise errors.HypervisorError("No monitor socket found")
443 fc84cd5d Guido Trotter
      else:
444 cad837b9 Dimitris Aragiorgis
        raise errors.HypervisorError("Error checking monitor socket: %s",
445 fc84cd5d Guido Trotter
                                     utils.ErrnoOrStr(err))
446 fc84cd5d Guido Trotter
    if not stat.S_ISSOCK(sock_stat.st_mode):
447 cad837b9 Dimitris Aragiorgis
      raise errors.HypervisorError("Monitor socket is not a socket")
448 fc84cd5d Guido Trotter
449 91c10532 Andrea Spadaccini
  def _check_connection(self):
450 91c10532 Andrea Spadaccini
    """Make sure that the connection is established.
451 91c10532 Andrea Spadaccini

452 91c10532 Andrea Spadaccini
    """
453 91c10532 Andrea Spadaccini
    if not self._connected:
454 cad837b9 Dimitris Aragiorgis
      raise errors.ProgrammerError("To use a MonitorSocket you need to first"
455 91c10532 Andrea Spadaccini
                                   " invoke connect() on it")
456 91c10532 Andrea Spadaccini
457 91c10532 Andrea Spadaccini
  def connect(self):
458 cad837b9 Dimitris Aragiorgis
    """Connects to the monitor.
459 91c10532 Andrea Spadaccini

460 cad837b9 Dimitris Aragiorgis
    Connects to the UNIX socket
461 91c10532 Andrea Spadaccini

462 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
463 91c10532 Andrea Spadaccini

464 91c10532 Andrea Spadaccini
    """
465 fc84cd5d Guido Trotter
    if self._connected:
466 fc84cd5d Guido Trotter
      raise errors.ProgrammerError("Cannot connect twice")
467 fc84cd5d Guido Trotter
468 fc84cd5d Guido Trotter
    self._check_socket()
469 fc84cd5d Guido Trotter
470 fc84cd5d Guido Trotter
    # Check file existance/stuff
471 fc84cd5d Guido Trotter
    try:
472 fc84cd5d Guido Trotter
      self.sock.connect(self.monitor_filename)
473 fc84cd5d Guido Trotter
    except EnvironmentError:
474 fc84cd5d Guido Trotter
      raise errors.HypervisorError("Can't connect to qmp socket")
475 91c10532 Andrea Spadaccini
    self._connected = True
476 91c10532 Andrea Spadaccini
477 cad837b9 Dimitris Aragiorgis
  def close(self):
478 cad837b9 Dimitris Aragiorgis
    """Closes the socket
479 cad837b9 Dimitris Aragiorgis

480 cad837b9 Dimitris Aragiorgis
    It cannot be used after this call.
481 cad837b9 Dimitris Aragiorgis

482 cad837b9 Dimitris Aragiorgis
    """
483 cad837b9 Dimitris Aragiorgis
    self.sock.close()
484 cad837b9 Dimitris Aragiorgis
485 cad837b9 Dimitris Aragiorgis
486 cad837b9 Dimitris Aragiorgis
class QmpConnection(MonitorSocket):
487 cad837b9 Dimitris Aragiorgis
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
488 cad837b9 Dimitris Aragiorgis

489 cad837b9 Dimitris Aragiorgis
  """
490 cad837b9 Dimitris Aragiorgis
  _FIRST_MESSAGE_KEY = "QMP"
491 cad837b9 Dimitris Aragiorgis
  _EVENT_KEY = "event"
492 cad837b9 Dimitris Aragiorgis
  _ERROR_KEY = "error"
493 cad837b9 Dimitris Aragiorgis
  _RETURN_KEY = RETURN_KEY = "return"
494 cad837b9 Dimitris Aragiorgis
  _ACTUAL_KEY = ACTUAL_KEY = "actual"
495 cad837b9 Dimitris Aragiorgis
  _ERROR_CLASS_KEY = "class"
496 cad837b9 Dimitris Aragiorgis
  _ERROR_DESC_KEY = "desc"
497 cad837b9 Dimitris Aragiorgis
  _EXECUTE_KEY = "execute"
498 cad837b9 Dimitris Aragiorgis
  _ARGUMENTS_KEY = "arguments"
499 cad837b9 Dimitris Aragiorgis
  _CAPABILITIES_COMMAND = "qmp_capabilities"
500 cad837b9 Dimitris Aragiorgis
  _MESSAGE_END_TOKEN = "\r\n"
501 cad837b9 Dimitris Aragiorgis
502 cad837b9 Dimitris Aragiorgis
  def __init__(self, monitor_filename):
503 cad837b9 Dimitris Aragiorgis
    super(QmpConnection, self).__init__(monitor_filename)
504 cad837b9 Dimitris Aragiorgis
    self._buf = ""
505 cad837b9 Dimitris Aragiorgis
506 cad837b9 Dimitris Aragiorgis
  def connect(self):
507 cad837b9 Dimitris Aragiorgis
    """Connects to the QMP monitor.
508 cad837b9 Dimitris Aragiorgis

509 cad837b9 Dimitris Aragiorgis
    Connects to the UNIX socket and makes sure that we can actually send and
510 cad837b9 Dimitris Aragiorgis
    receive data to the kvm instance via QMP.
511 cad837b9 Dimitris Aragiorgis

512 cad837b9 Dimitris Aragiorgis
    @raise errors.HypervisorError: when there are communication errors
513 cad837b9 Dimitris Aragiorgis
    @raise errors.ProgrammerError: when there are data serialization errors
514 cad837b9 Dimitris Aragiorgis

515 cad837b9 Dimitris Aragiorgis
    """
516 cad837b9 Dimitris Aragiorgis
    super(QmpConnection, self).connect()
517 91c10532 Andrea Spadaccini
    # Check if we receive a correct greeting message from the server
518 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 2.2)
519 91c10532 Andrea Spadaccini
    greeting = self._Recv()
520 91c10532 Andrea Spadaccini
    if not greeting[self._FIRST_MESSAGE_KEY]:
521 91c10532 Andrea Spadaccini
      self._connected = False
522 afa9bb2e Michael Hanselmann
      raise errors.HypervisorError("kvm: QMP communication error (wrong"
523 91c10532 Andrea Spadaccini
                                   " server greeting")
524 91c10532 Andrea Spadaccini
525 7231ca26 Dimitris Aragiorgis
    # This is needed because QMP can return more than one greetings
526 7231ca26 Dimitris Aragiorgis
    # see https://groups.google.com/d/msg/ganeti-devel/gZYcvHKDooU/SnukC8dgS5AJ
527 7231ca26 Dimitris Aragiorgis
    self._buf = ""
528 7231ca26 Dimitris Aragiorgis
529 91c10532 Andrea Spadaccini
    # Let's put the monitor in command mode using the qmp_capabilities
530 91c10532 Andrea Spadaccini
    # command, or else no command will be executable.
531 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 4)
532 91c10532 Andrea Spadaccini
    self.Execute(self._CAPABILITIES_COMMAND)
533 91c10532 Andrea Spadaccini
534 91c10532 Andrea Spadaccini
  def _ParseMessage(self, buf):
535 91c10532 Andrea Spadaccini
    """Extract and parse a QMP message from the given buffer.
536 91c10532 Andrea Spadaccini

537 91c10532 Andrea Spadaccini
    Seeks for a QMP message in the given buf. If found, it parses it and
538 91c10532 Andrea Spadaccini
    returns it together with the rest of the characters in the buf.
539 91c10532 Andrea Spadaccini
    If no message is found, returns None and the whole buffer.
540 91c10532 Andrea Spadaccini

541 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
542 91c10532 Andrea Spadaccini

543 91c10532 Andrea Spadaccini
    """
544 91c10532 Andrea Spadaccini
    message = None
545 91c10532 Andrea Spadaccini
    # Check if we got the message end token (CRLF, as per the QEMU Protocol
546 91c10532 Andrea Spadaccini
    # Specification 0.1 - Section 2.1.1)
547 91c10532 Andrea Spadaccini
    pos = buf.find(self._MESSAGE_END_TOKEN)
548 91c10532 Andrea Spadaccini
    if pos >= 0:
549 91c10532 Andrea Spadaccini
      try:
550 91c10532 Andrea Spadaccini
        message = QmpMessage.BuildFromJsonString(buf[:pos + 1])
551 91c10532 Andrea Spadaccini
      except Exception, err:
552 91c10532 Andrea Spadaccini
        raise errors.ProgrammerError("QMP data serialization error: %s" % err)
553 91c10532 Andrea Spadaccini
      buf = buf[pos + 1:]
554 91c10532 Andrea Spadaccini
555 91c10532 Andrea Spadaccini
    return (message, buf)
556 91c10532 Andrea Spadaccini
557 91c10532 Andrea Spadaccini
  def _Recv(self):
558 91c10532 Andrea Spadaccini
    """Receives a message from QMP and decodes the received JSON object.
559 91c10532 Andrea Spadaccini

560 91c10532 Andrea Spadaccini
    @rtype: QmpMessage
561 91c10532 Andrea Spadaccini
    @return: the received message
562 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
563 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
564 91c10532 Andrea Spadaccini

565 91c10532 Andrea Spadaccini
    """
566 91c10532 Andrea Spadaccini
    self._check_connection()
567 91c10532 Andrea Spadaccini
568 91c10532 Andrea Spadaccini
    # Check if there is already a message in the buffer
569 91c10532 Andrea Spadaccini
    (message, self._buf) = self._ParseMessage(self._buf)
570 91c10532 Andrea Spadaccini
    if message:
571 91c10532 Andrea Spadaccini
      return message
572 91c10532 Andrea Spadaccini
573 91c10532 Andrea Spadaccini
    recv_buffer = StringIO.StringIO(self._buf)
574 91c10532 Andrea Spadaccini
    recv_buffer.seek(len(self._buf))
575 91c10532 Andrea Spadaccini
    try:
576 91c10532 Andrea Spadaccini
      while True:
577 91c10532 Andrea Spadaccini
        data = self.sock.recv(4096)
578 91c10532 Andrea Spadaccini
        if not data:
579 91c10532 Andrea Spadaccini
          break
580 91c10532 Andrea Spadaccini
        recv_buffer.write(data)
581 91c10532 Andrea Spadaccini
582 91c10532 Andrea Spadaccini
        (message, self._buf) = self._ParseMessage(recv_buffer.getvalue())
583 91c10532 Andrea Spadaccini
        if message:
584 91c10532 Andrea Spadaccini
          return message
585 91c10532 Andrea Spadaccini
586 91c10532 Andrea Spadaccini
    except socket.timeout, err:
587 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while receiving a QMP message: "
588 91c10532 Andrea Spadaccini
                                   "%s" % (err))
589 91c10532 Andrea Spadaccini
    except socket.error, err:
590 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to receive data from KVM using the"
591 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
592 91c10532 Andrea Spadaccini
593 91c10532 Andrea Spadaccini
  def _Send(self, message):
594 91c10532 Andrea Spadaccini
    """Encodes and sends a message to KVM using QMP.
595 91c10532 Andrea Spadaccini

596 91c10532 Andrea Spadaccini
    @type message: QmpMessage
597 91c10532 Andrea Spadaccini
    @param message: message to send to KVM
598 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
599 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
600 91c10532 Andrea Spadaccini

601 91c10532 Andrea Spadaccini
    """
602 91c10532 Andrea Spadaccini
    self._check_connection()
603 91c10532 Andrea Spadaccini
    try:
604 91c10532 Andrea Spadaccini
      message_str = str(message)
605 91c10532 Andrea Spadaccini
    except Exception, err:
606 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("QMP data deserialization error: %s" % err)
607 91c10532 Andrea Spadaccini
608 91c10532 Andrea Spadaccini
    try:
609 91c10532 Andrea Spadaccini
      self.sock.sendall(message_str)
610 91c10532 Andrea Spadaccini
    except socket.timeout, err:
611 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while sending a QMP message: "
612 91c10532 Andrea Spadaccini
                                   "%s (%s)" % (err.string, err.errno))
613 91c10532 Andrea Spadaccini
    except socket.error, err:
614 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to send data from KVM using the"
615 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
616 91c10532 Andrea Spadaccini
617 91c10532 Andrea Spadaccini
  def Execute(self, command, arguments=None):
618 91c10532 Andrea Spadaccini
    """Executes a QMP command and returns the response of the server.
619 91c10532 Andrea Spadaccini

620 91c10532 Andrea Spadaccini
    @type command: str
621 91c10532 Andrea Spadaccini
    @param command: the command to execute
622 91c10532 Andrea Spadaccini
    @type arguments: dict
623 91c10532 Andrea Spadaccini
    @param arguments: dictionary of arguments to be passed to the command
624 91c10532 Andrea Spadaccini
    @rtype: dict
625 91c10532 Andrea Spadaccini
    @return: dictionary representing the received JSON object
626 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
627 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
628 91c10532 Andrea Spadaccini

629 91c10532 Andrea Spadaccini
    """
630 91c10532 Andrea Spadaccini
    self._check_connection()
631 91c10532 Andrea Spadaccini
    message = QmpMessage({self._EXECUTE_KEY: command})
632 91c10532 Andrea Spadaccini
    if arguments:
633 91c10532 Andrea Spadaccini
      message[self._ARGUMENTS_KEY] = arguments
634 91c10532 Andrea Spadaccini
    self._Send(message)
635 91c10532 Andrea Spadaccini
636 91c10532 Andrea Spadaccini
    # Events can occur between the sending of the command and the reception
637 91c10532 Andrea Spadaccini
    # of the response, so we need to filter out messages with the event key.
638 91c10532 Andrea Spadaccini
    while True:
639 91c10532 Andrea Spadaccini
      response = self._Recv()
640 91c10532 Andrea Spadaccini
      err = response[self._ERROR_KEY]
641 91c10532 Andrea Spadaccini
      if err:
642 91c10532 Andrea Spadaccini
        raise errors.HypervisorError("kvm: error executing the %s"
643 02d17fe3 Dimitris Aragiorgis
                                     " command: %s (%s):" %
644 91c10532 Andrea Spadaccini
                                     (command,
645 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DESC_KEY],
646 02d17fe3 Dimitris Aragiorgis
                                      err[self._ERROR_CLASS_KEY]))
647 91c10532 Andrea Spadaccini
648 91c10532 Andrea Spadaccini
      elif not response[self._EVENT_KEY]:
649 91c10532 Andrea Spadaccini
        return response
650 91c10532 Andrea Spadaccini
651 91c10532 Andrea Spadaccini
652 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
653 65107a2f Michael Hanselmann
  """KVM hypervisor interface
654 65107a2f Michael Hanselmann

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

845 98ec75d6 Iustin Pop
    """
846 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
847 98ec75d6 Iustin Pop
848 263b8de6 Guido Trotter
  @classmethod
849 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
850 7548396c Guido Trotter
    """Returns the instance uidfile.
851 7548396c Guido Trotter

852 7548396c Guido Trotter
    """
853 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
854 7548396c Guido Trotter
855 7548396c Guido Trotter
  @classmethod
856 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
857 263b8de6 Guido Trotter
    """Check pid file for instance information.
858 263b8de6 Guido Trotter

859 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
860 263b8de6 Guido Trotter
    information from its command line.
861 263b8de6 Guido Trotter

862 263b8de6 Guido Trotter
    @type pid: string or int
863 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
864 263b8de6 Guido Trotter
    @rtype: tuple
865 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
866 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
867 263b8de6 Guido Trotter

868 263b8de6 Guido Trotter
    """
869 263b8de6 Guido Trotter
    alive = utils.IsProcessAlive(pid)
870 263b8de6 Guido Trotter
    if not alive:
871 263b8de6 Guido Trotter
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
872 263b8de6 Guido Trotter
873 263b8de6 Guido Trotter
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
874 263b8de6 Guido Trotter
    try:
875 263b8de6 Guido Trotter
      cmdline = utils.ReadFile(cmdline_file)
876 263b8de6 Guido Trotter
    except EnvironmentError, err:
877 263b8de6 Guido Trotter
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
878 263b8de6 Guido Trotter
                                   (pid, err))
879 263b8de6 Guido Trotter
880 263b8de6 Guido Trotter
    instance = None
881 263b8de6 Guido Trotter
    memory = 0
882 263b8de6 Guido Trotter
    vcpus = 0
883 263b8de6 Guido Trotter
884 d0c8c01d Iustin Pop
    arg_list = cmdline.split("\x00")
885 263b8de6 Guido Trotter
    while arg_list:
886 e687ec01 Michael Hanselmann
      arg = arg_list.pop(0)
887 263b8de6 Guido Trotter
      if arg == "-name":
888 263b8de6 Guido Trotter
        instance = arg_list.pop(0)
889 263b8de6 Guido Trotter
      elif arg == "-m":
890 263b8de6 Guido Trotter
        memory = int(arg_list.pop(0))
891 263b8de6 Guido Trotter
      elif arg == "-smp":
892 4888a609 Guido Trotter
        vcpus = int(arg_list.pop(0).split(",")[0])
893 263b8de6 Guido Trotter
894 263b8de6 Guido Trotter
    if instance is None:
895 263b8de6 Guido Trotter
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
896 263b8de6 Guido Trotter
                                   " instance" % pid)
897 263b8de6 Guido Trotter
898 263b8de6 Guido Trotter
    return (instance, memory, vcpus)
899 263b8de6 Guido Trotter
900 70f25a49 Jose A. Lopes
  @classmethod
901 70f25a49 Jose A. Lopes
  def _InstancePidAlive(cls, instance_name):
902 263b8de6 Guido Trotter
    """Returns the instance pidfile, pid, and liveness.
903 263b8de6 Guido Trotter

904 263b8de6 Guido Trotter
    @type instance_name: string
905 263b8de6 Guido Trotter
    @param instance_name: instance name
906 263b8de6 Guido Trotter
    @rtype: tuple
907 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
908 1f8b3a27 Guido Trotter

909 1f8b3a27 Guido Trotter
    """
910 70f25a49 Jose A. Lopes
    pidfile = cls._InstancePidFile(instance_name)
911 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
912 263b8de6 Guido Trotter
913 263b8de6 Guido Trotter
    alive = False
914 263b8de6 Guido Trotter
    try:
915 70f25a49 Jose A. Lopes
      cmd_instance = cls._InstancePidInfo(pid)[0]
916 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
917 263b8de6 Guido Trotter
    except errors.HypervisorError:
918 263b8de6 Guido Trotter
      pass
919 1f8b3a27 Guido Trotter
920 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
921 1f8b3a27 Guido Trotter
922 70f25a49 Jose A. Lopes
  @classmethod
923 70f25a49 Jose A. Lopes
  def _CheckDown(cls, instance_name):
924 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
925 5905901c Iustin Pop

926 5905901c Iustin Pop
    """
927 70f25a49 Jose A. Lopes
    alive = cls._InstancePidAlive(instance_name)[2]
928 5905901c Iustin Pop
    if alive:
929 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
930 5905901c Iustin Pop
                                   (instance_name, "already running"))
931 5905901c Iustin Pop
932 0df4d98a Guido Trotter
  @classmethod
933 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
934 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
935 c4fbefc8 Guido Trotter

936 c4fbefc8 Guido Trotter
    """
937 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
938 c4fbefc8 Guido Trotter
939 0df4d98a Guido Trotter
  @classmethod
940 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
941 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
942 c4fbefc8 Guido Trotter

943 c4fbefc8 Guido Trotter
    """
944 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
945 c4fbefc8 Guido Trotter
946 91c10532 Andrea Spadaccini
  @classmethod
947 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
948 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
949 91c10532 Andrea Spadaccini

950 91c10532 Andrea Spadaccini
    """
951 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
952 91c10532 Andrea Spadaccini
953 95d70148 Jose A. Lopes
  @classmethod
954 95d70148 Jose A. Lopes
  def _InstanceShutdownMonitor(cls, instance_name):
955 95d70148 Jose A. Lopes
    """Returns the instance QMP output filename
956 95d70148 Jose A. Lopes

957 95d70148 Jose A. Lopes
    """
958 95d70148 Jose A. Lopes
    return utils.PathJoin(cls._CTRL_DIR, "%s.shutdown" % instance_name)
959 95d70148 Jose A. Lopes
960 86d6bc2a Guido Trotter
  @staticmethod
961 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
962 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
963 86d6bc2a Guido Trotter

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

966 86d6bc2a Guido Trotter
    """
967 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
968 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
969 86d6bc2a Guido Trotter
    else:
970 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
971 86d6bc2a Guido Trotter
972 0df4d98a Guido Trotter
  @classmethod
973 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
974 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
975 38e250ba Guido Trotter

976 38e250ba Guido Trotter
    """
977 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
978 38e250ba Guido Trotter
979 7e66c35b Guido Trotter
  @classmethod
980 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
981 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
982 547a63b7 Balazs Lecz

983 547a63b7 Balazs Lecz
    """
984 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
985 547a63b7 Balazs Lecz
986 547a63b7 Balazs Lecz
  @classmethod
987 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
988 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
989 5d9bfd87 Apollon Oikonomopoulos
    given instance.
990 5d9bfd87 Apollon Oikonomopoulos

991 5d9bfd87 Apollon Oikonomopoulos
    """
992 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
993 5d9bfd87 Apollon Oikonomopoulos
994 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
995 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
996 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
997 5d9bfd87 Apollon Oikonomopoulos

998 5d9bfd87 Apollon Oikonomopoulos
    """
999 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
1000 5d9bfd87 Apollon Oikonomopoulos
1001 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
1002 4f580fef Sรฉbastien Bocahu
  def _InstanceKeymapFile(cls, instance_name):
1003 4f580fef Sรฉbastien Bocahu
    """Returns the name of the file containing the keymap for a given instance
1004 4f580fef Sรฉbastien Bocahu

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

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

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

1067 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
1068 eb58f9b1 Guido Trotter
    @type instance: instance object
1069 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
1070 eb58f9b1 Guido Trotter
    @type seq: int
1071 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
1072 eb58f9b1 Guido Trotter
    @type nic: nic object
1073 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
1074 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
1075 eb58f9b1 Guido Trotter

1076 eb58f9b1 Guido Trotter
    """
1077 5d9bfd87 Apollon Oikonomopoulos
    env = {
1078 5d9bfd87 Apollon Oikonomopoulos
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
1079 5d9bfd87 Apollon Oikonomopoulos
      "INSTANCE": instance.name,
1080 5d9bfd87 Apollon Oikonomopoulos
      "MAC": nic.mac,
1081 5d9bfd87 Apollon Oikonomopoulos
      "MODE": nic.nicparams[constants.NIC_MODE],
1082 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE": tap,
1083 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE_INDEX": str(seq),
1084 cc6fd3da Dimitris Aragiorgis
      "INTERFACE_UUID": nic.uuid,
1085 2a3bbbaa Dimitris Aragiorgis
      "TAGS": " ".join(instance.GetTags()),
1086 5d9bfd87 Apollon Oikonomopoulos
    }
1087 5d9bfd87 Apollon Oikonomopoulos
1088 5d9bfd87 Apollon Oikonomopoulos
    if nic.ip:
1089 5d9bfd87 Apollon Oikonomopoulos
      env["IP"] = nic.ip
1090 5d9bfd87 Apollon Oikonomopoulos
1091 cc6fd3da Dimitris Aragiorgis
    if nic.name:
1092 cc6fd3da Dimitris Aragiorgis
      env["INTERFACE_NAME"] = nic.name
1093 cc6fd3da Dimitris Aragiorgis
1094 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_LINK]:
1095 5d9bfd87 Apollon Oikonomopoulos
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
1096 5d9bfd87 Apollon Oikonomopoulos
1097 747ee762 Dimitris Aragiorgis
    if nic.nicparams[constants.NIC_VLAN]:
1098 747ee762 Dimitris Aragiorgis
      env["VLAN"] = nic.nicparams[constants.NIC_VLAN]
1099 747ee762 Dimitris Aragiorgis
1100 a5ad5e58 Apollon Oikonomopoulos
    if nic.network:
1101 cbe4a0a5 Dimitris Aragiorgis
      n = objects.Network.FromDict(nic.netinfo)
1102 7e8f03e3 Dimitris Aragiorgis
      env.update(n.HooksDict())
1103 a5ad5e58 Apollon Oikonomopoulos
1104 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1105 5d9bfd87 Apollon Oikonomopoulos
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
1106 5d9bfd87 Apollon Oikonomopoulos
1107 9d9bded1 Michael Hanselmann
    result = utils.RunCmd([pathutils.KVM_IFUP, tap], env=env)
1108 5d9bfd87 Apollon Oikonomopoulos
    if result.failed:
1109 afa9bb2e Michael Hanselmann
      raise errors.HypervisorError("Failed to configure interface %s: %s;"
1110 afa9bb2e Michael Hanselmann
                                   " network configuration script output: %s" %
1111 5d9bfd87 Apollon Oikonomopoulos
                                   (tap, result.fail_reason, result.output))
1112 eb58f9b1 Guido Trotter
1113 b693125f Tsachy Shacham
  @staticmethod
1114 b693125f Tsachy Shacham
  def _VerifyAffinityPackage():
1115 b693125f Tsachy Shacham
    if affinity is None:
1116 b693125f Tsachy Shacham
      raise errors.HypervisorError("affinity Python package not"
1117 5ae4945a Iustin Pop
                                   " found; cannot use CPU pinning under KVM")
1118 b693125f Tsachy Shacham
1119 b693125f Tsachy Shacham
  @staticmethod
1120 b693125f Tsachy Shacham
  def _BuildAffinityCpuMask(cpu_list):
1121 b693125f Tsachy Shacham
    """Create a CPU mask suitable for sched_setaffinity from a list of
1122 b693125f Tsachy Shacham
    CPUs.
1123 b693125f Tsachy Shacham

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

1127 b693125f Tsachy Shacham
    @type cpu_list: list of int
1128 b693125f Tsachy Shacham
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
1129 b693125f Tsachy Shacham
    @rtype: int
1130 b693125f Tsachy Shacham
    @return: a bit mask of CPU affinities
1131 b693125f Tsachy Shacham

1132 b693125f Tsachy Shacham
    """
1133 b693125f Tsachy Shacham
    if cpu_list == constants.CPU_PINNING_OFF:
1134 b693125f Tsachy Shacham
      return constants.CPU_PINNING_ALL_KVM
1135 b693125f Tsachy Shacham
    else:
1136 b693125f Tsachy Shacham
      return sum(2 ** cpu for cpu in cpu_list)
1137 b693125f Tsachy Shacham
1138 b693125f Tsachy Shacham
  @classmethod
1139 b693125f Tsachy Shacham
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
1140 b693125f Tsachy Shacham
    """Change CPU affinity for running VM according to given CPU mask.
1141 b693125f Tsachy Shacham

1142 b693125f Tsachy Shacham
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
1143 b693125f Tsachy Shacham
    @type cpu_mask: string
1144 b693125f Tsachy Shacham
    @param process_id: process ID of KVM process. Used to pin entire VM
1145 b693125f Tsachy Shacham
                       to physical CPUs.
1146 b693125f Tsachy Shacham
    @type process_id: int
1147 b693125f Tsachy Shacham
    @param thread_dict: map of virtual CPUs to KVM thread IDs
1148 b693125f Tsachy Shacham
    @type thread_dict: dict int:int
1149 b693125f Tsachy Shacham

1150 b693125f Tsachy Shacham
    """
1151 b693125f Tsachy Shacham
    # Convert the string CPU mask to a list of list of int's
1152 b693125f Tsachy Shacham
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
1153 b693125f Tsachy Shacham
1154 b693125f Tsachy Shacham
    if len(cpu_list) == 1:
1155 b693125f Tsachy Shacham
      all_cpu_mapping = cpu_list[0]
1156 b693125f Tsachy Shacham
      if all_cpu_mapping == constants.CPU_PINNING_OFF:
1157 b693125f Tsachy Shacham
        # If CPU pinning has 1 entry that's "all", then do nothing
1158 b693125f Tsachy Shacham
        pass
1159 b693125f Tsachy Shacham
      else:
1160 b693125f Tsachy Shacham
        # If CPU pinning has one non-all entry, map the entire VM to
1161 b693125f Tsachy Shacham
        # one set of physical CPUs
1162 b693125f Tsachy Shacham
        cls._VerifyAffinityPackage()
1163 5ae4945a Iustin Pop
        affinity.set_process_affinity_mask(
1164 5ae4945a Iustin Pop
          process_id, cls._BuildAffinityCpuMask(all_cpu_mapping))
1165 b693125f Tsachy Shacham
    else:
1166 b693125f Tsachy Shacham
      # The number of vCPUs mapped should match the number of vCPUs
1167 b693125f Tsachy Shacham
      # reported by KVM. This was already verified earlier, so
1168 b693125f Tsachy Shacham
      # here only as a sanity check.
1169 b693125f Tsachy Shacham
      assert len(thread_dict) == len(cpu_list)
1170 b693125f Tsachy Shacham
      cls._VerifyAffinityPackage()
1171 b693125f Tsachy Shacham
1172 b693125f Tsachy Shacham
      # For each vCPU, map it to the proper list of physical CPUs
1173 b693125f Tsachy Shacham
      for vcpu, i in zip(cpu_list, range(len(cpu_list))):
1174 b693125f Tsachy Shacham
        affinity.set_process_affinity_mask(thread_dict[i],
1175 5ae4945a Iustin Pop
                                           cls._BuildAffinityCpuMask(vcpu))
1176 b693125f Tsachy Shacham
1177 b693125f Tsachy Shacham
  def _GetVcpuThreadIds(self, instance_name):
1178 b693125f Tsachy Shacham
    """Get a mapping of vCPU no. to thread IDs for the instance
1179 b693125f Tsachy Shacham

1180 b693125f Tsachy Shacham
    @type instance_name: string
1181 b693125f Tsachy Shacham
    @param instance_name: instance in question
1182 b693125f Tsachy Shacham
    @rtype: dictionary of int:int
1183 b693125f Tsachy Shacham
    @return: a dictionary mapping vCPU numbers to thread IDs
1184 b693125f Tsachy Shacham

1185 b693125f Tsachy Shacham
    """
1186 b693125f Tsachy Shacham
    result = {}
1187 b693125f Tsachy Shacham
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
1188 b693125f Tsachy Shacham
    for line in output.stdout.splitlines():
1189 b693125f Tsachy Shacham
      match = self._CPU_INFO_RE.search(line)
1190 b693125f Tsachy Shacham
      if not match:
1191 b693125f Tsachy Shacham
        continue
1192 b693125f Tsachy Shacham
      grp = map(int, match.groups())
1193 b693125f Tsachy Shacham
      result[grp[0]] = grp[1]
1194 b693125f Tsachy Shacham
1195 b693125f Tsachy Shacham
    return result
1196 b693125f Tsachy Shacham
1197 1d8a7812 Andrea Spadaccini
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
1198 1d8a7812 Andrea Spadaccini
    """Complete CPU pinning.
1199 b693125f Tsachy Shacham

1200 b693125f Tsachy Shacham
    @type instance_name: string
1201 b693125f Tsachy Shacham
    @param instance_name: name of instance
1202 b693125f Tsachy Shacham
    @type cpu_mask: string
1203 b693125f Tsachy Shacham
    @param cpu_mask: CPU pinning mask as entered by user
1204 b693125f Tsachy Shacham

1205 b693125f Tsachy Shacham
    """
1206 1d8a7812 Andrea Spadaccini
    # Get KVM process ID, to be used if need to pin entire VM
1207 1d8a7812 Andrea Spadaccini
    _, pid, _ = self._InstancePidAlive(instance_name)
1208 1d8a7812 Andrea Spadaccini
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
1209 1d8a7812 Andrea Spadaccini
    thread_dict = self._GetVcpuThreadIds(instance_name)
1210 1d8a7812 Andrea Spadaccini
    # Run CPU pinning, based on configured mask
1211 1d8a7812 Andrea Spadaccini
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
1212 b693125f Tsachy Shacham
1213 58e356a9 Helga Velroyen
  def ListInstances(self, hvparams=None):
1214 eb58f9b1 Guido Trotter
    """Get the list of running instances.
1215 eb58f9b1 Guido Trotter

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

1219 eb58f9b1 Guido Trotter
    """
1220 eb58f9b1 Guido Trotter
    result = []
1221 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1222 95d70148 Jose A. Lopes
      if self._InstancePidAlive(name)[2] or self._IsUserShutdown(name):
1223 eb58f9b1 Guido Trotter
        result.append(name)
1224 eb58f9b1 Guido Trotter
    return result
1225 eb58f9b1 Guido Trotter
1226 95d70148 Jose A. Lopes
  @classmethod
1227 95d70148 Jose A. Lopes
  def _IsUserShutdown(cls, instance_name):
1228 95d70148 Jose A. Lopes
    return os.path.exists(cls._InstanceShutdownMonitor(instance_name))
1229 95d70148 Jose A. Lopes
1230 95d70148 Jose A. Lopes
  @classmethod
1231 95d70148 Jose A. Lopes
  def _ClearUserShutdown(cls, instance_name):
1232 95d70148 Jose A. Lopes
    utils.RemoveFile(cls._InstanceShutdownMonitor(instance_name))
1233 95d70148 Jose A. Lopes
1234 0bbec3af Helga Velroyen
  def GetInstanceInfo(self, instance_name, hvparams=None):
1235 eb58f9b1 Guido Trotter
    """Get instance properties.
1236 eb58f9b1 Guido Trotter

1237 4fbb3c60 Guido Trotter
    @type instance_name: string
1238 c41eea6e Iustin Pop
    @param instance_name: the instance name
1239 0bbec3af Helga Velroyen
    @type hvparams: dict of strings
1240 0bbec3af Helga Velroyen
    @param hvparams: hvparams to be used with this instance
1241 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
1242 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
1243 eb58f9b1 Guido Trotter

1244 eb58f9b1 Guido Trotter
    """
1245 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
1246 1f8b3a27 Guido Trotter
    if not alive:
1247 95d70148 Jose A. Lopes
      if self._IsUserShutdown(instance_name):
1248 95d70148 Jose A. Lopes
        return (instance_name, -1, 0, 0, hv_base.HvInstanceState.SHUTDOWN, 0)
1249 95d70148 Jose A. Lopes
      else:
1250 95d70148 Jose A. Lopes
        return None
1251 eb58f9b1 Guido Trotter
1252 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
1253 a3f0f306 Jose A. Lopes
    istat = hv_base.HvInstanceState.RUNNING
1254 697e573c Hrvoje Ribicic
    times = 0
1255 eb58f9b1 Guido Trotter
1256 89da2ff3 Guido Trotter
    try:
1257 89da2ff3 Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
1258 89da2ff3 Guido Trotter
      qmp.connect()
1259 89da2ff3 Guido Trotter
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
1260 89da2ff3 Guido Trotter
      # Will fail if ballooning is not enabled, but we can then just resort to
1261 89da2ff3 Guido Trotter
      # the value above.
1262 89da2ff3 Guido Trotter
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
1263 89da2ff3 Guido Trotter
      memory = mem_bytes / 1048576
1264 89da2ff3 Guido Trotter
    except errors.HypervisorError:
1265 89da2ff3 Guido Trotter
      pass
1266 89da2ff3 Guido Trotter
1267 fc84cd5d Guido Trotter
    return (instance_name, pid, memory, vcpus, istat, times)
1268 eb58f9b1 Guido Trotter
1269 0200a1af Helga Velroyen
  def GetAllInstancesInfo(self, hvparams=None):
1270 eb58f9b1 Guido Trotter
    """Get properties of all instances.
1271 eb58f9b1 Guido Trotter

1272 0200a1af Helga Velroyen
    @type hvparams: dict of strings
1273 0200a1af Helga Velroyen
    @param hvparams: hypervisor parameter
1274 c41eea6e Iustin Pop
    @return: list of tuples (name, id, memory, vcpus, stat, times)
1275 c41eea6e Iustin Pop

1276 eb58f9b1 Guido Trotter
    """
1277 eb58f9b1 Guido Trotter
    data = []
1278 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1279 263b8de6 Guido Trotter
      try:
1280 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
1281 263b8de6 Guido Trotter
      except errors.HypervisorError:
1282 3bc145d8 Bernardo Dal Seno
        # Ignore exceptions due to instances being shut down
1283 263b8de6 Guido Trotter
        continue
1284 263b8de6 Guido Trotter
      if info:
1285 263b8de6 Guido Trotter
        data.append(info)
1286 eb58f9b1 Guido Trotter
    return data
1287 eb58f9b1 Guido Trotter
1288 41a878b5 Dimitris Aragiorgis
  def _GenerateKVMBlockDevicesOptions(self, instance, kvm_disks,
1289 43c6e76f Dimitris Aragiorgis
                                      kvmhelp, devlist):
1290 43c6e76f Dimitris Aragiorgis
    """Generate KVM options regarding instance's block devices.
1291 43c6e76f Dimitris Aragiorgis

1292 43c6e76f Dimitris Aragiorgis
    @type instance: L{objects.Instance}
1293 43c6e76f Dimitris Aragiorgis
    @param instance: the instance object
1294 41a878b5 Dimitris Aragiorgis
    @type kvm_disks: list of tuples
1295 41a878b5 Dimitris Aragiorgis
    @param kvm_disks: list of tuples [(disk, link_name, uri)..]
1296 43c6e76f Dimitris Aragiorgis
    @type kvmhelp: string
1297 43c6e76f Dimitris Aragiorgis
    @param kvmhelp: output of kvm --help
1298 43c6e76f Dimitris Aragiorgis
    @type devlist: string
1299 43c6e76f Dimitris Aragiorgis
    @param devlist: output of kvm -device ?
1300 43c6e76f Dimitris Aragiorgis
    @rtype: list
1301 43c6e76f Dimitris Aragiorgis
    @return: list of command line options eventually used by kvm executable
1302 af5db30c Dimitris Aragiorgis

1303 43c6e76f Dimitris Aragiorgis
    """
1304 af5db30c Dimitris Aragiorgis
    hvp = instance.hvparams
1305 43c6e76f Dimitris Aragiorgis
    kernel_path = hvp[constants.HV_KERNEL_PATH]
1306 43c6e76f Dimitris Aragiorgis
    if kernel_path:
1307 43c6e76f Dimitris Aragiorgis
      boot_disk = False
1308 43c6e76f Dimitris Aragiorgis
    else:
1309 43c6e76f Dimitris Aragiorgis
      boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
1310 af5db30c Dimitris Aragiorgis
1311 af5db30c Dimitris Aragiorgis
    # whether this is an older KVM version that uses the boot=on flag
1312 af5db30c Dimitris Aragiorgis
    # on devices
1313 af5db30c Dimitris Aragiorgis
    needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1314 af5db30c Dimitris Aragiorgis
1315 af5db30c Dimitris Aragiorgis
    dev_opts = []
1316 a16f0d77 Dimitris Aragiorgis
    device_driver = None
1317 af5db30c Dimitris Aragiorgis
    disk_type = hvp[constants.HV_DISK_TYPE]
1318 af5db30c Dimitris Aragiorgis
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
1319 af5db30c Dimitris Aragiorgis
      if_val = ",if=%s" % self._VIRTIO
1320 a16f0d77 Dimitris Aragiorgis
      try:
1321 a16f0d77 Dimitris Aragiorgis
        if self._VIRTIO_BLK_RE.search(devlist):
1322 a7ccf635 Dimitris Aragiorgis
          if_val = ",if=none"
1323 a16f0d77 Dimitris Aragiorgis
          # will be passed in -device option as driver
1324 a16f0d77 Dimitris Aragiorgis
          device_driver = self._VIRTIO_BLK_PCI
1325 a16f0d77 Dimitris Aragiorgis
      except errors.HypervisorError, _:
1326 a16f0d77 Dimitris Aragiorgis
        pass
1327 af5db30c Dimitris Aragiorgis
    else:
1328 af5db30c Dimitris Aragiorgis
      if_val = ",if=%s" % disk_type
1329 af5db30c Dimitris Aragiorgis
    # Cache mode
1330 af5db30c Dimitris Aragiorgis
    disk_cache = hvp[constants.HV_DISK_CACHE]
1331 af5db30c Dimitris Aragiorgis
    if instance.disk_template in constants.DTS_EXT_MIRROR:
1332 af5db30c Dimitris Aragiorgis
      if disk_cache != "none":
1333 af5db30c Dimitris Aragiorgis
        # TODO: make this a hard error, instead of a silent overwrite
1334 af5db30c Dimitris Aragiorgis
        logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
1335 af5db30c Dimitris Aragiorgis
                        " to prevent shared storage corruption on migration",
1336 af5db30c Dimitris Aragiorgis
                        disk_cache)
1337 af5db30c Dimitris Aragiorgis
      cache_val = ",cache=none"
1338 af5db30c Dimitris Aragiorgis
    elif disk_cache != constants.HT_CACHE_DEFAULT:
1339 af5db30c Dimitris Aragiorgis
      cache_val = ",cache=%s" % disk_cache
1340 af5db30c Dimitris Aragiorgis
    else:
1341 af5db30c Dimitris Aragiorgis
      cache_val = ""
1342 41a878b5 Dimitris Aragiorgis
    for cfdev, link_name, uri in kvm_disks:
1343 af5db30c Dimitris Aragiorgis
      if cfdev.mode != constants.DISK_RDWR:
1344 af5db30c Dimitris Aragiorgis
        raise errors.HypervisorError("Instance has read-only disks which"
1345 af5db30c Dimitris Aragiorgis
                                     " are not supported by KVM")
1346 af5db30c Dimitris Aragiorgis
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
1347 af5db30c Dimitris Aragiorgis
      boot_val = ""
1348 af5db30c Dimitris Aragiorgis
      if boot_disk:
1349 af5db30c Dimitris Aragiorgis
        dev_opts.extend(["-boot", "c"])
1350 af5db30c Dimitris Aragiorgis
        boot_disk = False
1351 af5db30c Dimitris Aragiorgis
        if needs_boot_flag and disk_type != constants.HT_DISK_IDE:
1352 af5db30c Dimitris Aragiorgis
          boot_val = ",boot=on"
1353 af5db30c Dimitris Aragiorgis
1354 af5db30c Dimitris Aragiorgis
      access_mode = cfdev.params.get(constants.LDP_ACCESS,
1355 af5db30c Dimitris Aragiorgis
                                     constants.DISK_KERNELSPACE)
1356 66d3d195 Dimitris Aragiorgis
      if (uri and access_mode == constants.DISK_USERSPACE):
1357 66d3d195 Dimitris Aragiorgis
        drive_uri = uri
1358 af5db30c Dimitris Aragiorgis
      else:
1359 66d3d195 Dimitris Aragiorgis
        drive_uri = link_name
1360 af5db30c Dimitris Aragiorgis
1361 af5db30c Dimitris Aragiorgis
      drive_val = "file=%s,format=raw%s%s%s" % \
1362 af5db30c Dimitris Aragiorgis
                  (drive_uri, if_val, boot_val, cache_val)
1363 af5db30c Dimitris Aragiorgis
1364 a16f0d77 Dimitris Aragiorgis
      if device_driver:
1365 41a878b5 Dimitris Aragiorgis
        # kvm_disks are the 4th entry of runtime file that did not exist in
1366 a7ccf635 Dimitris Aragiorgis
        # the past. That means that cfdev should always have pci slot and
1367 a7ccf635 Dimitris Aragiorgis
        # _GenerateDeviceKVMId() will not raise a exception.
1368 a7ccf635 Dimitris Aragiorgis
        kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_DISK, cfdev)
1369 a7ccf635 Dimitris Aragiorgis
        drive_val += (",id=%s" % kvm_devid)
1370 a7ccf635 Dimitris Aragiorgis
        drive_val += (",bus=0,unit=%d" % cfdev.pci)
1371 a7ccf635 Dimitris Aragiorgis
        dev_val = ("%s,drive=%s,id=%s" %
1372 a7ccf635 Dimitris Aragiorgis
                   (device_driver, kvm_devid, kvm_devid))
1373 a7ccf635 Dimitris Aragiorgis
        dev_val += ",bus=pci.0,addr=%s" % hex(cfdev.pci)
1374 a7ccf635 Dimitris Aragiorgis
        dev_opts.extend(["-device", dev_val])
1375 a7ccf635 Dimitris Aragiorgis
1376 af5db30c Dimitris Aragiorgis
      dev_opts.extend(["-drive", drive_val])
1377 af5db30c Dimitris Aragiorgis
1378 af5db30c Dimitris Aragiorgis
    return dev_opts
1379 af5db30c Dimitris Aragiorgis
1380 364e1664 Jose A. Lopes
  @staticmethod
1381 472cc1e9 Jose A. Lopes
  def _CdromOption(kvm_cmd, cdrom_disk_type, cdrom_image, cdrom_boot,
1382 472cc1e9 Jose A. Lopes
                   needs_boot_flag):
1383 364e1664 Jose A. Lopes
    """Extends L{kvm_cmd} with the '-drive' option for a cdrom, and
1384 364e1664 Jose A. Lopes
    optionally the '-boot' option.
1385 364e1664 Jose A. Lopes

1386 364e1664 Jose A. Lopes
    Example: -drive file=cdrom.iso,media=cdrom,format=raw,if=ide -boot d
1387 364e1664 Jose A. Lopes

1388 364e1664 Jose A. Lopes
    Example: -drive file=cdrom.iso,media=cdrom,format=raw,if=ide,boot=on
1389 364e1664 Jose A. Lopes

1390 364e1664 Jose A. Lopes
    Example: -drive file=http://hostname.com/cdrom.iso,media=cdrom
1391 364e1664 Jose A. Lopes

1392 364e1664 Jose A. Lopes
    @type kvm_cmd: string
1393 364e1664 Jose A. Lopes
    @param kvm_cmd: KVM command line
1394 364e1664 Jose A. Lopes

1395 364e1664 Jose A. Lopes
    @type cdrom_disk_type:
1396 364e1664 Jose A. Lopes
    @param cdrom_disk_type:
1397 364e1664 Jose A. Lopes

1398 364e1664 Jose A. Lopes
    @type cdrom_image:
1399 364e1664 Jose A. Lopes
    @param cdrom_image:
1400 364e1664 Jose A. Lopes

1401 364e1664 Jose A. Lopes
    @type cdrom_boot:
1402 364e1664 Jose A. Lopes
    @param cdrom_boot:
1403 364e1664 Jose A. Lopes

1404 364e1664 Jose A. Lopes
    @type needs_boot_flag:
1405 364e1664 Jose A. Lopes
    @param needs_boot_flag:
1406 364e1664 Jose A. Lopes

1407 364e1664 Jose A. Lopes
    """
1408 364e1664 Jose A. Lopes
    # Check that the ISO image is accessible
1409 364e1664 Jose A. Lopes
    # See https://bugs.launchpad.net/qemu/+bug/597575
1410 364e1664 Jose A. Lopes
    if utils.IsUrl(cdrom_image) and not _CheckUrl(cdrom_image):
1411 364e1664 Jose A. Lopes
      raise errors.HypervisorError("Cdrom ISO image '%s' is not accessible" %
1412 364e1664 Jose A. Lopes
                                   cdrom_image)
1413 364e1664 Jose A. Lopes
1414 364e1664 Jose A. Lopes
    # set cdrom 'media' and 'format', if needed
1415 364e1664 Jose A. Lopes
    if utils.IsUrl(cdrom_image):
1416 364e1664 Jose A. Lopes
      options = ",media=cdrom"
1417 364e1664 Jose A. Lopes
    else:
1418 364e1664 Jose A. Lopes
      options = ",media=cdrom,format=raw"
1419 364e1664 Jose A. Lopes
1420 364e1664 Jose A. Lopes
    # set cdrom 'if' type
1421 364e1664 Jose A. Lopes
    if cdrom_boot:
1422 364e1664 Jose A. Lopes
      if_val = ",if=" + constants.HT_DISK_IDE
1423 364e1664 Jose A. Lopes
    elif cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1424 364e1664 Jose A. Lopes
      if_val = ",if=virtio"
1425 364e1664 Jose A. Lopes
    else:
1426 364e1664 Jose A. Lopes
      if_val = ",if=" + cdrom_disk_type
1427 364e1664 Jose A. Lopes
1428 364e1664 Jose A. Lopes
    # set boot flag, if needed
1429 364e1664 Jose A. Lopes
    boot_val = ""
1430 364e1664 Jose A. Lopes
    if cdrom_boot:
1431 364e1664 Jose A. Lopes
      kvm_cmd.extend(["-boot", "d"])
1432 364e1664 Jose A. Lopes
1433 364e1664 Jose A. Lopes
      # whether this is an older KVM version that requires the 'boot=on' flag
1434 364e1664 Jose A. Lopes
      # on devices
1435 364e1664 Jose A. Lopes
      if needs_boot_flag:
1436 364e1664 Jose A. Lopes
        boot_val = ",boot=on"
1437 364e1664 Jose A. Lopes
1438 364e1664 Jose A. Lopes
    # build '-drive' option
1439 364e1664 Jose A. Lopes
    drive_val = "file=%s%s%s%s" % (cdrom_image, options, if_val, boot_val)
1440 364e1664 Jose A. Lopes
    kvm_cmd.extend(["-drive", drive_val])
1441 364e1664 Jose A. Lopes
1442 b73f1c59 Guido Trotter
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused,
1443 b73f1c59 Guido Trotter
                          kvmhelp):
1444 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
1445 eb58f9b1 Guido Trotter

1446 b73f1c59 Guido Trotter
    @type kvmhelp: string
1447 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1448 839642c2 Iustin Pop
    @attention: this function must not have any side-effects; for
1449 839642c2 Iustin Pop
        example, it must not write to the filesystem, or read values
1450 839642c2 Iustin Pop
        from the current system the are expected to differ between
1451 839642c2 Iustin Pop
        nodes, since it is only run once at instance startup;
1452 839642c2 Iustin Pop
        actions/kvm arguments that can vary between systems should be
1453 839642c2 Iustin Pop
        done in L{_ExecuteKVMRuntime}
1454 839642c2 Iustin Pop

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

1796 38e250ba Guido Trotter
    """
1797 38e250ba Guido Trotter
    try:
1798 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1799 38e250ba Guido Trotter
                      data=data)
1800 90c024f6 Guido Trotter
    except EnvironmentError, err:
1801 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1802 38e250ba Guido Trotter
1803 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
1804 38e250ba Guido Trotter
    """Read an instance's KVM runtime
1805 38e250ba Guido Trotter

1806 38e250ba Guido Trotter
    """
1807 38e250ba Guido Trotter
    try:
1808 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1809 90c024f6 Guido Trotter
    except EnvironmentError, err:
1810 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1811 38e250ba Guido Trotter
    return file_content
1812 38e250ba Guido Trotter
1813 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1814 38e250ba Guido Trotter
    """Save an instance's KVM runtime
1815 38e250ba Guido Trotter

1816 38e250ba Guido Trotter
    """
1817 41a878b5 Dimitris Aragiorgis
    kvm_cmd, kvm_nics, hvparams, kvm_disks = kvm_runtime
1818 0fe22ad2 Dimitris Aragiorgis
1819 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1820 41a878b5 Dimitris Aragiorgis
    serialized_disks = [(blk.ToDict(), link, uri)
1821 41a878b5 Dimitris Aragiorgis
                        for blk, link, uri in kvm_disks]
1822 0fe22ad2 Dimitris Aragiorgis
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams,
1823 41a878b5 Dimitris Aragiorgis
                                      serialized_disks))
1824 0fe22ad2 Dimitris Aragiorgis
1825 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
1826 38e250ba Guido Trotter
1827 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1828 38e250ba Guido Trotter
    """Load an instance's KVM runtime
1829 38e250ba Guido Trotter

1830 38e250ba Guido Trotter
    """
1831 30e42c4e Guido Trotter
    if not serialized_runtime:
1832 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1833 0fe22ad2 Dimitris Aragiorgis
1834 0fe22ad2 Dimitris Aragiorgis
    return _AnalyzeSerializedRuntime(serialized_runtime)
1835 38e250ba Guido Trotter
1836 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1837 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
1838 76431533 Guido Trotter

1839 76431533 Guido Trotter
    @type name: string
1840 76431533 Guido Trotter
    @param name: instance name
1841 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1842 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1843 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1844 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1845 76431533 Guido Trotter

1846 76431533 Guido Trotter
    """
1847 5d9bfd87 Apollon Oikonomopoulos
    try:
1848 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1849 5d9bfd87 Apollon Oikonomopoulos
    finally:
1850 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
1851 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
1852 5d9bfd87 Apollon Oikonomopoulos
1853 76431533 Guido Trotter
    if result.failed:
1854 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1855 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
1856 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
1857 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
1858 76431533 Guido Trotter
1859 81c717cd Jose A. Lopes
  @staticmethod
1860 81c717cd Jose A. Lopes
  def _GenerateTapName(nic):
1861 81c717cd Jose A. Lopes
    """Generate a TAP network interface name for a NIC.
1862 81c717cd Jose A. Lopes

1863 81c717cd Jose A. Lopes
    This helper function generates a special TAP network interface
1864 81c717cd Jose A. Lopes
    name for NICs that are meant to be used in instance communication.
1865 81c717cd Jose A. Lopes
    This function checks the existing TAP interfaces in order to find
1866 81c717cd Jose A. Lopes
    a unique name for the new TAP network interface.  The TAP network
1867 81c717cd Jose A. Lopes
    interface names are of the form 'gnt.com.%d', where '%d' is a
1868 81c717cd Jose A. Lopes
    unique number within the node.
1869 81c717cd Jose A. Lopes

1870 81c717cd Jose A. Lopes
    @type nic: ganeti.objects.NIC
1871 81c717cd Jose A. Lopes
    @param nic: NIC object for the name should be generated
1872 81c717cd Jose A. Lopes

1873 81c717cd Jose A. Lopes
    @rtype: string
1874 81c717cd Jose A. Lopes
    @return: TAP network interface name, or the empty string if the
1875 81c717cd Jose A. Lopes
             NIC is not used in instance communication
1876 81c717cd Jose A. Lopes

1877 81c717cd Jose A. Lopes
    """
1878 81c717cd Jose A. Lopes
    if nic.name is None or not \
1879 81c717cd Jose A. Lopes
          nic.name.startswith(constants.INSTANCE_COMMUNICATION_NIC_PREFIX):
1880 81c717cd Jose A. Lopes
      return ""
1881 81c717cd Jose A. Lopes
1882 81c717cd Jose A. Lopes
    result = utils.RunCmd(["ip", "tuntap", "list"])
1883 81c717cd Jose A. Lopes
1884 81c717cd Jose A. Lopes
    if result.failed:
1885 81c717cd Jose A. Lopes
      raise errors.HypervisorError("Failed to list TUN/TAP interfaces")
1886 81c717cd Jose A. Lopes
1887 81c717cd Jose A. Lopes
    idxs = set()
1888 81c717cd Jose A. Lopes
1889 81c717cd Jose A. Lopes
    for line in result.output.splitlines():
1890 81c717cd Jose A. Lopes
      parts = line.split(": ", 1)
1891 81c717cd Jose A. Lopes
1892 81c717cd Jose A. Lopes
      if len(parts) < 2:
1893 81c717cd Jose A. Lopes
        raise errors.HypervisorError("Failed to parse TUN/TAP interfaces")
1894 81c717cd Jose A. Lopes
1895 81c717cd Jose A. Lopes
      r = re.match(r"gnt\.com\.([0-9]+)", parts[0])
1896 81c717cd Jose A. Lopes
1897 81c717cd Jose A. Lopes
      if r is not None:
1898 81c717cd Jose A. Lopes
        idxs.add(int(r.group(1)))
1899 81c717cd Jose A. Lopes
1900 81c717cd Jose A. Lopes
    if idxs:
1901 81c717cd Jose A. Lopes
      idx = max(idxs) + 1
1902 81c717cd Jose A. Lopes
    else:
1903 81c717cd Jose A. Lopes
      idx = 0
1904 81c717cd Jose A. Lopes
1905 81c717cd Jose A. Lopes
    return "gnt.com.%d" % idx
1906 81c717cd Jose A. Lopes
1907 41a878b5 Dimitris Aragiorgis
  # too many local variables
1908 0fe22ad2 Dimitris Aragiorgis
  # pylint: disable=R0914
1909 b73f1c59 Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1910 839642c2 Iustin Pop
    """Execute a KVM cmd, after completing it with some last minute data.
1911 ee5f20b0 Guido Trotter

1912 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1913 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1914 b73f1c59 Guido Trotter
    @type kvmhelp: string
1915 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1916 30e42c4e Guido Trotter

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

2140 95d70148 Jose A. Lopes
    """
2141 95d70148 Jose A. Lopes
    if hvparams is None \
2142 95d70148 Jose A. Lopes
          or not hvparams[constants.HV_KVM_USER_SHUTDOWN] \
2143 95d70148 Jose A. Lopes
          or utils.IsDaemonAlive(constants.KVMD):
2144 95d70148 Jose A. Lopes
      return
2145 95d70148 Jose A. Lopes
2146 95d70148 Jose A. Lopes
    result = utils.RunCmd(constants.KVMD)
2147 95d70148 Jose A. Lopes
2148 95d70148 Jose A. Lopes
    if result.failed:
2149 95d70148 Jose A. Lopes
      raise errors.HypervisorError("Failed to start KVM daemon")
2150 95d70148 Jose A. Lopes
2151 323f9095 Stephen Shirley
  def StartInstance(self, instance, block_devices, startup_paused):
2152 ee5f20b0 Guido Trotter
    """Start an instance.
2153 ee5f20b0 Guido Trotter

2154 ee5f20b0 Guido Trotter
    """
2155 5905901c Iustin Pop
    self._CheckDown(instance.name)
2156 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2157 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2158 7238edb5 Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
2159 b73f1c59 Guido Trotter
                                           startup_paused, kvmhelp)
2160 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
2161 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
2162 ee5f20b0 Guido Trotter
2163 70f25a49 Jose A. Lopes
  @classmethod
2164 205d3309 Klaus Aehlig
  def _CallMonitorCommand(cls, instance_name, command, timeout=None):
2165 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
2166 6567aff3 Guido Trotter

2167 6567aff3 Guido Trotter
    """
2168 2a2d087a Michele Tartara
    if timeout is not None:
2169 2a2d087a Michele Tartara
      timeout_cmd = "timeout %s" % (timeout, )
2170 2a2d087a Michele Tartara
    else:
2171 2a2d087a Michele Tartara
      timeout_cmd = ""
2172 2a2d087a Michele Tartara
2173 eace6157 Michael Hanselmann
    # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
2174 eace6157 Michael Hanselmann
    # version. The monitor protocol is designed for human consumption, whereas
2175 eace6157 Michael Hanselmann
    # QMP is made for programmatic usage. In the worst case QMP can also
2176 eace6157 Michael Hanselmann
    # execute monitor commands. As it is, all calls to socat take at least
2177 eace6157 Michael Hanselmann
    # 500ms and likely more: socat can't detect the end of the reply and waits
2178 eace6157 Michael Hanselmann
    # for 500ms of no data received before exiting (500 ms is the default for
2179 eace6157 Michael Hanselmann
    # the "-t" parameter).
2180 874f6148 Michele Tartara
    socat = ("echo %s | %s %s STDIO UNIX-CONNECT:%s" %
2181 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
2182 874f6148 Michele Tartara
              timeout_cmd,
2183 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
2184 70f25a49 Jose A. Lopes
              utils.ShellQuote(cls._InstanceMonitor(instance_name))))
2185 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
2186 6567aff3 Guido Trotter
    if result.failed:
2187 afa9bb2e Michael Hanselmann
      msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
2188 afa9bb2e Michael Hanselmann
             " output: %s" %
2189 afa9bb2e Michael Hanselmann
             (command, instance_name, result.fail_reason, result.output))
2190 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
2191 6567aff3 Guido Trotter
2192 6567aff3 Guido Trotter
    return result
2193 6567aff3 Guido Trotter
2194 2615646c Dimitris Aragiorgis
  def _GetFreePCISlot(self, instance, dev):
2195 2615646c Dimitris Aragiorgis
    """Get the first available pci slot of a runnung instance.
2196 2615646c Dimitris Aragiorgis

2197 2615646c Dimitris Aragiorgis
    """
2198 2615646c Dimitris Aragiorgis
    slots = bitarray(32)
2199 2615646c Dimitris Aragiorgis
    slots.setall(False) # pylint: disable=E1101
2200 2615646c Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance.name, self._INFO_PCI_CMD)
2201 2615646c Dimitris Aragiorgis
    for line in output.stdout.splitlines():
2202 2615646c Dimitris Aragiorgis
      match = self._INFO_PCI_RE.search(line)
2203 2615646c Dimitris Aragiorgis
      if match:
2204 2615646c Dimitris Aragiorgis
        slot = int(match.group(1))
2205 2615646c Dimitris Aragiorgis
        slots[slot] = True
2206 2615646c Dimitris Aragiorgis
2207 d13fb3f1 Dimitris Aragiorgis
    dev.pci = _GetFreeSlot(slots)
2208 2615646c Dimitris Aragiorgis
2209 50e0f1d9 Dimitris Aragiorgis
  def VerifyHotplugSupport(self, instance, action, dev_type):
2210 50e0f1d9 Dimitris Aragiorgis
    """Verifies that hotplug is supported.
2211 97cd9092 Dimitris Aragiorgis

2212 97cd9092 Dimitris Aragiorgis
    Hotplug is *not* supported in case of:
2213 97cd9092 Dimitris Aragiorgis
     - security models and chroot (disk hotplug)
2214 97cd9092 Dimitris Aragiorgis
     - fdsend module is missing (nic hot-add)
2215 97cd9092 Dimitris Aragiorgis

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

2218 97cd9092 Dimitris Aragiorgis
    """
2219 97cd9092 Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2220 97cd9092 Dimitris Aragiorgis
      hvp = instance.hvparams
2221 97cd9092 Dimitris Aragiorgis
      security_model = hvp[constants.HV_SECURITY_MODEL]
2222 97cd9092 Dimitris Aragiorgis
      use_chroot = hvp[constants.HV_KVM_USE_CHROOT]
2223 97cd9092 Dimitris Aragiorgis
      if use_chroot:
2224 97cd9092 Dimitris Aragiorgis
        raise errors.HotplugError("Disk hotplug is not supported"
2225 97cd9092 Dimitris Aragiorgis
                                  " in case of chroot.")
2226 97cd9092 Dimitris Aragiorgis
      if security_model != constants.HT_SM_NONE:
2227 97cd9092 Dimitris Aragiorgis
        raise errors.HotplugError("Disk Hotplug is not supported in case"
2228 97cd9092 Dimitris Aragiorgis
                                  " security models are used.")
2229 97cd9092 Dimitris Aragiorgis
2230 97cd9092 Dimitris Aragiorgis
    if (dev_type == constants.HOTPLUG_TARGET_NIC and
2231 97cd9092 Dimitris Aragiorgis
        action == constants.HOTPLUG_ACTION_ADD and not fdsend):
2232 97cd9092 Dimitris Aragiorgis
      raise errors.HotplugError("Cannot hot-add NIC."
2233 97cd9092 Dimitris Aragiorgis
                                " fdsend python module is missing.")
2234 97cd9092 Dimitris Aragiorgis
2235 24711492 Dimitris Aragiorgis
  def HotplugSupported(self, instance):
2236 24711492 Dimitris Aragiorgis
    """Checks if hotplug is generally supported.
2237 24711492 Dimitris Aragiorgis

2238 24711492 Dimitris Aragiorgis
    Hotplug is *not* supported in case of:
2239 24711492 Dimitris Aragiorgis
     - qemu versions < 1.0
2240 24711492 Dimitris Aragiorgis
     - for stopped instances
2241 24711492 Dimitris Aragiorgis

2242 24711492 Dimitris Aragiorgis
    @raise errors.HypervisorError: in one of the previous cases
2243 24711492 Dimitris Aragiorgis

2244 24711492 Dimitris Aragiorgis
    """
2245 96ed3a3e Dimitris Aragiorgis
    try:
2246 96ed3a3e Dimitris Aragiorgis
      output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD)
2247 96ed3a3e Dimitris Aragiorgis
    except errors.HypervisorError:
2248 96ed3a3e Dimitris Aragiorgis
      raise errors.HotplugError("Instance is probably down")
2249 96ed3a3e Dimitris Aragiorgis
2250 24711492 Dimitris Aragiorgis
    # TODO: search for netdev_add, drive_add, device_add.....
2251 24711492 Dimitris Aragiorgis
    match = self._INFO_VERSION_RE.search(output.stdout)
2252 24711492 Dimitris Aragiorgis
    if not match:
2253 96ed3a3e Dimitris Aragiorgis
      raise errors.HotplugError("Cannot parse qemu version via monitor")
2254 96ed3a3e Dimitris Aragiorgis
2255 24711492 Dimitris Aragiorgis
    v_major, v_min, _, _ = match.groups()
2256 24711492 Dimitris Aragiorgis
    if (int(v_major), int(v_min)) < (1, 0):
2257 24711492 Dimitris Aragiorgis
      raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0")
2258 24711492 Dimitris Aragiorgis
2259 89c10241 Dimitris Aragiorgis
  def _CallHotplugCommands(self, name, cmds):
2260 89c10241 Dimitris Aragiorgis
    for c in cmds:
2261 066f16b0 Dimitris Aragiorgis
      self._CallMonitorCommand(name, c)
2262 89c10241 Dimitris Aragiorgis
      time.sleep(1)
2263 97cd9092 Dimitris Aragiorgis
2264 066f16b0 Dimitris Aragiorgis
  def _VerifyHotplugCommand(self, instance_name, device, dev_type,
2265 066f16b0 Dimitris Aragiorgis
                            should_exist):
2266 066f16b0 Dimitris Aragiorgis
    """Checks if a previous hotplug command has succeeded.
2267 066f16b0 Dimitris Aragiorgis

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

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

2273 066f16b0 Dimitris Aragiorgis
    """
2274 066f16b0 Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance_name, self._INFO_PCI_CMD)
2275 066f16b0 Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, device)
2276 066f16b0 Dimitris Aragiorgis
    match = \
2277 066f16b0 Dimitris Aragiorgis
      self._FIND_PCI_DEVICE_RE(device.pci, kvm_devid).search(output.stdout)
2278 066f16b0 Dimitris Aragiorgis
    if match and not should_exist:
2279 066f16b0 Dimitris Aragiorgis
      msg = "Device %s should have been removed but is still there" % kvm_devid
2280 066f16b0 Dimitris Aragiorgis
      raise errors.HypervisorError(msg)
2281 066f16b0 Dimitris Aragiorgis
2282 066f16b0 Dimitris Aragiorgis
    if not match and should_exist:
2283 066f16b0 Dimitris Aragiorgis
      msg = "Device %s should have been added but is missing" % kvm_devid
2284 066f16b0 Dimitris Aragiorgis
      raise errors.HypervisorError(msg)
2285 066f16b0 Dimitris Aragiorgis
2286 066f16b0 Dimitris Aragiorgis
    logging.info("Device %s has been correctly hot-plugged", kvm_devid)
2287 97cd9092 Dimitris Aragiorgis
2288 4b82125b Dimitris Aragiorgis
  def HotAddDevice(self, instance, dev_type, device, extra, seq):
2289 4b82125b Dimitris Aragiorgis
    """ Helper method to hot-add a new device
2290 4b82125b Dimitris Aragiorgis

2291 4b82125b Dimitris Aragiorgis
    It gets free pci slot generates the device name and invokes the
2292 4b82125b Dimitris Aragiorgis
    device specific method.
2293 4b82125b Dimitris Aragiorgis

2294 4b82125b Dimitris Aragiorgis
    """
2295 4b82125b Dimitris Aragiorgis
    # in case of hot-mod this is given
2296 4b82125b Dimitris Aragiorgis
    if device.pci is None:
2297 4b82125b Dimitris Aragiorgis
      self._GetFreePCISlot(instance, device)
2298 4b82125b Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, device)
2299 4b82125b Dimitris Aragiorgis
    runtime = self._LoadKVMRuntime(instance)
2300 4b82125b Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2301 89c10241 Dimitris Aragiorgis
      cmds = ["drive_add dummy file=%s,if=none,id=%s,format=raw" %
2302 89c10241 Dimitris Aragiorgis
                (extra, kvm_devid)]
2303 89c10241 Dimitris Aragiorgis
      cmds += ["device_add virtio-blk-pci,bus=pci.0,addr=%s,drive=%s,id=%s" %
2304 89c10241 Dimitris Aragiorgis
                (hex(device.pci), kvm_devid, kvm_devid)]
2305 4b82125b Dimitris Aragiorgis
    elif dev_type == constants.HOTPLUG_TARGET_NIC:
2306 4b82125b Dimitris Aragiorgis
      (tap, fd) = _OpenTap()
2307 4b82125b Dimitris Aragiorgis
      self._ConfigureNIC(instance, seq, device, tap)
2308 4b82125b Dimitris Aragiorgis
      self._PassTapFd(instance, fd, device)
2309 89c10241 Dimitris Aragiorgis
      cmds = ["netdev_add tap,id=%s,fd=%s" % (kvm_devid, kvm_devid)]
2310 4b82125b Dimitris Aragiorgis
      args = "virtio-net-pci,bus=pci.0,addr=%s,mac=%s,netdev=%s,id=%s" % \
2311 4b82125b Dimitris Aragiorgis
               (hex(device.pci), device.mac, kvm_devid, kvm_devid)
2312 89c10241 Dimitris Aragiorgis
      cmds += ["device_add %s" % args]
2313 4b82125b Dimitris Aragiorgis
      utils.WriteFile(self._InstanceNICFile(instance.name, seq), data=tap)
2314 4b82125b Dimitris Aragiorgis
2315 89c10241 Dimitris Aragiorgis
    self._CallHotplugCommands(instance.name, cmds)
2316 066f16b0 Dimitris Aragiorgis
    self._VerifyHotplugCommand(instance.name, device, dev_type, True)
2317 4b82125b Dimitris Aragiorgis
    # update relevant entries in runtime file
2318 4b82125b Dimitris Aragiorgis
    index = _DEVICE_RUNTIME_INDEX[dev_type]
2319 4b82125b Dimitris Aragiorgis
    entry = _RUNTIME_ENTRY[dev_type](device, extra)
2320 4b82125b Dimitris Aragiorgis
    runtime[index].append(entry)
2321 4b82125b Dimitris Aragiorgis
    self._SaveKVMRuntime(instance, runtime)
2322 4b82125b Dimitris Aragiorgis
2323 4b82125b Dimitris Aragiorgis
  def HotDelDevice(self, instance, dev_type, device, _, seq):
2324 4b82125b Dimitris Aragiorgis
    """ Helper method for hot-del device
2325 4b82125b Dimitris Aragiorgis

2326 4b82125b Dimitris Aragiorgis
    It gets device info from runtime file, generates the device name and
2327 4b82125b Dimitris Aragiorgis
    invokes the device specific method.
2328 4b82125b Dimitris Aragiorgis

2329 4b82125b Dimitris Aragiorgis
    """
2330 4b82125b Dimitris Aragiorgis
    runtime = self._LoadKVMRuntime(instance)
2331 4b82125b Dimitris Aragiorgis
    entry = _GetExistingDeviceInfo(dev_type, device, runtime)
2332 4b82125b Dimitris Aragiorgis
    kvm_device = _RUNTIME_DEVICE[dev_type](entry)
2333 4b82125b Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, kvm_device)
2334 4b82125b Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2335 89c10241 Dimitris Aragiorgis
      cmds = ["device_del %s" % kvm_devid]
2336 89c10241 Dimitris Aragiorgis
      cmds += ["drive_del %s" % kvm_devid]
2337 4b82125b Dimitris Aragiorgis
    elif dev_type == constants.HOTPLUG_TARGET_NIC:
2338 89c10241 Dimitris Aragiorgis
      cmds = ["device_del %s" % kvm_devid]
2339 89c10241 Dimitris Aragiorgis
      cmds += ["netdev_del %s" % kvm_devid]
2340 4b82125b Dimitris Aragiorgis
      utils.RemoveFile(self._InstanceNICFile(instance.name, seq))
2341 89c10241 Dimitris Aragiorgis
    self._CallHotplugCommands(instance.name, cmds)
2342 066f16b0 Dimitris Aragiorgis
    self._VerifyHotplugCommand(instance.name, kvm_device, dev_type, False)
2343 4b82125b Dimitris Aragiorgis
    index = _DEVICE_RUNTIME_INDEX[dev_type]
2344 4b82125b Dimitris Aragiorgis
    runtime[index].remove(entry)
2345 4b82125b Dimitris Aragiorgis
    self._SaveKVMRuntime(instance, runtime)
2346 4b82125b Dimitris Aragiorgis
2347 4b82125b Dimitris Aragiorgis
    return kvm_device.pci
2348 4b82125b Dimitris Aragiorgis
2349 4b82125b Dimitris Aragiorgis
  def HotModDevice(self, instance, dev_type, device, _, seq):
2350 4b82125b Dimitris Aragiorgis
    """ Helper method for hot-mod device
2351 4b82125b Dimitris Aragiorgis

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

2355 4b82125b Dimitris Aragiorgis
    """
2356 4b82125b Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_NIC:
2357 4b82125b Dimitris Aragiorgis
      # putting it back in the same pci slot
2358 4b82125b Dimitris Aragiorgis
      device.pci = self.HotDelDevice(instance, dev_type, device, _, seq)
2359 4b82125b Dimitris Aragiorgis
      self.HotAddDevice(instance, dev_type, device, _, seq)
2360 4b82125b Dimitris Aragiorgis
2361 4b82125b Dimitris Aragiorgis
  def _PassTapFd(self, instance, fd, nic):
2362 4b82125b Dimitris Aragiorgis
    """Pass file descriptor to kvm process via monitor socket using SCM_RIGHTS
2363 4b82125b Dimitris Aragiorgis

2364 4b82125b Dimitris Aragiorgis
    """
2365 4b82125b Dimitris Aragiorgis
    # TODO: factor out code related to unix sockets.
2366 4b82125b Dimitris Aragiorgis
    #       squash common parts between monitor and qmp
2367 4b82125b Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_NIC, nic)
2368 4b82125b Dimitris Aragiorgis
    command = "getfd %s\n" % kvm_devid
2369 4b82125b Dimitris Aragiorgis
    fds = [fd]
2370 4b82125b Dimitris Aragiorgis
    logging.info("%s", fds)
2371 4b82125b Dimitris Aragiorgis
    try:
2372 4b82125b Dimitris Aragiorgis
      monsock = MonitorSocket(self._InstanceMonitor(instance.name))
2373 4b82125b Dimitris Aragiorgis
      monsock.connect()
2374 4b82125b Dimitris Aragiorgis
      fdsend.sendfds(monsock.sock, command, fds=fds)
2375 4b82125b Dimitris Aragiorgis
    finally:
2376 4b82125b Dimitris Aragiorgis
      monsock.close()
2377 4b82125b Dimitris Aragiorgis
2378 b52d85c1 Guido Trotter
  @classmethod
2379 585c8187 Guido Trotter
  def _ParseKVMVersion(cls, text):
2380 585c8187 Guido Trotter
    """Parse the KVM version from the --help output.
2381 585c8187 Guido Trotter

2382 585c8187 Guido Trotter
    @type text: string
2383 585c8187 Guido Trotter
    @param text: output of kvm --help
2384 585c8187 Guido Trotter
    @return: (version, v_maj, v_min, v_rev)
2385 5c3d5dfd Iustin Pop
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
2386 585c8187 Guido Trotter

2387 585c8187 Guido Trotter
    """
2388 585c8187 Guido Trotter
    match = cls._VERSION_RE.search(text.splitlines()[0])
2389 585c8187 Guido Trotter
    if not match:
2390 585c8187 Guido Trotter
      raise errors.HypervisorError("Unable to get KVM version")
2391 585c8187 Guido Trotter
2392 585c8187 Guido Trotter
    v_all = match.group(0)
2393 585c8187 Guido Trotter
    v_maj = int(match.group(1))
2394 585c8187 Guido Trotter
    v_min = int(match.group(2))
2395 585c8187 Guido Trotter
    if match.group(4):
2396 585c8187 Guido Trotter
      v_rev = int(match.group(4))
2397 585c8187 Guido Trotter
    else:
2398 585c8187 Guido Trotter
      v_rev = 0
2399 585c8187 Guido Trotter
    return (v_all, v_maj, v_min, v_rev)
2400 585c8187 Guido Trotter
2401 585c8187 Guido Trotter
  @classmethod
2402 6e043e60 Guido Trotter
  def _GetKVMOutput(cls, kvm_path, option):
2403 6e043e60 Guido Trotter
    """Return the output of a kvm invocation
2404 e3b89628 Guido Trotter

2405 bc0fed4b Guido Trotter
    @type kvm_path: string
2406 bc0fed4b Guido Trotter
    @param kvm_path: path to the kvm executable
2407 bc0fed4b Guido Trotter
    @type option: a key of _KVMOPTS_CMDS
2408 bc0fed4b Guido Trotter
    @param option: kvm option to fetch the output from
2409 6e043e60 Guido Trotter
    @return: output a supported kvm invocation
2410 e3b89628 Guido Trotter
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
2411 e3b89628 Guido Trotter

2412 e3b89628 Guido Trotter
    """
2413 6e043e60 Guido Trotter
    assert option in cls._KVMOPTS_CMDS, "Invalid output option"
2414 6e043e60 Guido Trotter
2415 bc0fed4b Guido Trotter
    optlist, can_fail = cls._KVMOPTS_CMDS[option]
2416 bc0fed4b Guido Trotter
2417 bc0fed4b Guido Trotter
    result = utils.RunCmd([kvm_path] + optlist)
2418 bc0fed4b Guido Trotter
    if result.failed and not can_fail:
2419 af89fa76 Helga Velroyen
      raise errors.HypervisorError("Unable to get KVM %s output" %
2420 3ddc7650 Jose A. Lopes
                                    " ".join(optlist))
2421 e3b89628 Guido Trotter
    return result.output
2422 e3b89628 Guido Trotter
2423 e3b89628 Guido Trotter
  @classmethod
2424 3b59ec02 Guido Trotter
  def _GetKVMVersion(cls, kvm_path):
2425 d7e4a2b1 Andrea Spadaccini
    """Return the installed KVM version.
2426 b52d85c1 Guido Trotter

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

2430 b52d85c1 Guido Trotter
    """
2431 6e043e60 Guido Trotter
    return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
2432 82e3bf85 Dimitris Aragiorgis
2433 82e3bf85 Dimitris Aragiorgis
  @classmethod
2434 82e3bf85 Dimitris Aragiorgis
  def _GetDefaultMachineVersion(cls, kvm_path):
2435 82e3bf85 Dimitris Aragiorgis
    """Return the default hardware revision (e.g. pc-1.1)
2436 82e3bf85 Dimitris Aragiorgis

2437 82e3bf85 Dimitris Aragiorgis
    """
2438 6e043e60 Guido Trotter
    output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2439 82e3bf85 Dimitris Aragiorgis
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
2440 82e3bf85 Dimitris Aragiorgis
    if match:
2441 82e3bf85 Dimitris Aragiorgis
      return match.group(1)
2442 82e3bf85 Dimitris Aragiorgis
    else:
2443 82e3bf85 Dimitris Aragiorgis
      return "pc"
2444 82e3bf85 Dimitris Aragiorgis
2445 70f25a49 Jose A. Lopes
  @classmethod
2446 205d3309 Klaus Aehlig
  def _StopInstance(cls, instance, force=False, name=None, timeout=None):
2447 eb58f9b1 Guido Trotter
    """Stop an instance.
2448 eb58f9b1 Guido Trotter

2449 eb58f9b1 Guido Trotter
    """
2450 874f6148 Michele Tartara
    assert(timeout is None or force is not None)
2451 874f6148 Michele Tartara
2452 bbcf7ad0 Iustin Pop
    if name is not None and not force:
2453 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
2454 bbcf7ad0 Iustin Pop
    if name is None:
2455 bbcf7ad0 Iustin Pop
      name = instance.name
2456 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
2457 bbcf7ad0 Iustin Pop
    else:
2458 bbcf7ad0 Iustin Pop
      acpi = False
2459 70f25a49 Jose A. Lopes
    _, pid, alive = cls._InstancePidAlive(name)
2460 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
2461 bbcf7ad0 Iustin Pop
      if force or not acpi:
2462 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
2463 eb58f9b1 Guido Trotter
      else:
2464 205d3309 Klaus Aehlig
        cls._CallMonitorCommand(name, "system_powerdown", timeout)
2465 95d70148 Jose A. Lopes
    cls._ClearUserShutdown(instance.name)
2466 70f25a49 Jose A. Lopes
2467 205d3309 Klaus Aehlig
  def StopInstance(self, instance, force=False, retry=False, name=None,
2468 205d3309 Klaus Aehlig
                   timeout=None):
2469 70f25a49 Jose A. Lopes
    """Stop an instance.
2470 70f25a49 Jose A. Lopes

2471 70f25a49 Jose A. Lopes
    """
2472 205d3309 Klaus Aehlig
    self._StopInstance(instance, force, name=name, timeout=timeout)
2473 eb58f9b1 Guido Trotter
2474 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
2475 8904b35c Guido Trotter
    """Cleanup after a stopped instance
2476 8904b35c Guido Trotter

2477 8904b35c Guido Trotter
    """
2478 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
2479 8904b35c Guido Trotter
    if pid > 0 and alive:
2480 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
2481 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
2482 95d70148 Jose A. Lopes
    self._ClearUserShutdown(instance_name)
2483 eb58f9b1 Guido Trotter
2484 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
2485 eb58f9b1 Guido Trotter
    """Reboot an instance.
2486 eb58f9b1 Guido Trotter

2487 eb58f9b1 Guido Trotter
    """
2488 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
2489 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
2490 eb58f9b1 Guido Trotter
    # to shutdown and restart.
2491 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
2492 1f8b3a27 Guido Trotter
    if not alive:
2493 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
2494 78411c60 Iustin Pop
                                   " not running" % instance.name)
2495 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
2496 f02881e0 Guido Trotter
    # ...first load it...
2497 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
2498 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
2499 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
2500 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
2501 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
2502 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
2503 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2504 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2505 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
2506 eb58f9b1 Guido Trotter
2507 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
2508 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
2509 30e42c4e Guido Trotter

2510 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2511 30e42c4e Guido Trotter
    @param instance: instance to be migrated
2512 30e42c4e Guido Trotter
    @rtype: string
2513 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
2514 30e42c4e Guido Trotter

2515 30e42c4e Guido Trotter
    """
2516 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
2517 30e42c4e Guido Trotter
2518 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
2519 30e42c4e Guido Trotter
    """Prepare to accept an instance.
2520 30e42c4e Guido Trotter

2521 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2522 30e42c4e Guido Trotter
    @param instance: instance to be accepted
2523 30e42c4e Guido Trotter
    @type info: string
2524 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
2525 30e42c4e Guido Trotter
    @type target: string
2526 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
2527 30e42c4e Guido Trotter

2528 30e42c4e Guido Trotter
    """
2529 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2530 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
2531 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2532 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2533 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
2534 b73f1c59 Guido Trotter
                            incoming=incoming_address)
2535 30e42c4e Guido Trotter
2536 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
2537 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
2538 30e42c4e Guido Trotter

2539 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
2540 30e42c4e Guido Trotter

2541 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2542 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
2543 30e42c4e Guido Trotter

2544 30e42c4e Guido Trotter
    """
2545 30e42c4e Guido Trotter
    if success:
2546 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2547 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
2548 5d9bfd87 Apollon Oikonomopoulos
2549 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
2550 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
2551 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
2552 cc8a8ed7 Apollon Oikonomopoulos
          continue
2553 5d9bfd87 Apollon Oikonomopoulos
        try:
2554 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
2555 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
2556 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
2557 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
2558 5d9bfd87 Apollon Oikonomopoulos
          continue
2559 5d9bfd87 Apollon Oikonomopoulos
        try:
2560 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
2561 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
2562 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
2563 5d9bfd87 Apollon Oikonomopoulos
2564 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
2565 30e42c4e Guido Trotter
    else:
2566 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
2567 30e42c4e Guido Trotter
2568 bc0a2284 Helga Velroyen
  def MigrateInstance(self, cluster_name, instance, target, live):
2569 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
2570 30e42c4e Guido Trotter

2571 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
2572 30e42c4e Guido Trotter
    currently running.
2573 30e42c4e Guido Trotter

2574 bc0a2284 Helga Velroyen
    @type cluster_name: string
2575 bc0a2284 Helga Velroyen
    @param cluster_name: name of the cluster
2576 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
2577 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
2578 30e42c4e Guido Trotter
    @type target: string
2579 30e42c4e Guido Trotter
    @param target: ip address of the target node
2580 30e42c4e Guido Trotter
    @type live: boolean
2581 30e42c4e Guido Trotter
    @param live: perform a live migration
2582 30e42c4e Guido Trotter

2583 30e42c4e Guido Trotter
    """
2584 58d38b02 Iustin Pop
    instance_name = instance.name
2585 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
2586 6a1434d7 Andrea Spadaccini
    _, _, alive = self._InstancePidAlive(instance_name)
2587 30e42c4e Guido Trotter
    if not alive:
2588 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
2589 30e42c4e Guido Trotter
2590 30e42c4e Guido Trotter
    if not live:
2591 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
2592 30e42c4e Guido Trotter
2593 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
2594 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
2595 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2596 e43d4f9f Apollon Oikonomopoulos
2597 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
2598 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
2599 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2600 e43d4f9f Apollon Oikonomopoulos
2601 937ff984 Dimitris Aragiorgis
    migration_caps = instance.hvparams[constants.HV_KVM_MIGRATION_CAPS]
2602 937ff984 Dimitris Aragiorgis
    if migration_caps:
2603 937ff984 Dimitris Aragiorgis
      for c in migration_caps.split(_MIGRATION_CAPS_DELIM):
2604 937ff984 Dimitris Aragiorgis
        migrate_command = ("migrate_set_capability %s on" % c)
2605 937ff984 Dimitris Aragiorgis
        self._CallMonitorCommand(instance_name, migrate_command)
2606 937ff984 Dimitris Aragiorgis
2607 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
2608 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
2609 30e42c4e Guido Trotter
2610 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
2611 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
2612 6a1434d7 Andrea Spadaccini

2613 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2614 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
2615 6a1434d7 Andrea Spadaccini
    @type success: bool
2616 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
2617 6a1434d7 Andrea Spadaccini
    @type live: bool
2618 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
2619 6a1434d7 Andrea Spadaccini

2620 6a1434d7 Andrea Spadaccini
    """
2621 6a1434d7 Andrea Spadaccini
    if success:
2622 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
2623 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
2624 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
2625 6a1434d7 Andrea Spadaccini
    elif live:
2626 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
2627 95d70148 Jose A. Lopes
    self._ClearUserShutdown(instance.name)
2628 6a1434d7 Andrea Spadaccini
2629 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
2630 6a1434d7 Andrea Spadaccini
    """Get the migration status
2631 6a1434d7 Andrea Spadaccini

2632 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2633 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
2634 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
2635 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
2636 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
2637 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
2638 6a1434d7 Andrea Spadaccini

2639 6a1434d7 Andrea Spadaccini
    """
2640 d0c8c01d Iustin Pop
    info_command = "info migrate"
2641 6a1434d7 Andrea Spadaccini
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
2642 6a1434d7 Andrea Spadaccini
      result = self._CallMonitorCommand(instance.name, info_command)
2643 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
2644 30e42c4e Guido Trotter
      if not match:
2645 c4e388a5 Guido Trotter
        if not result.stdout:
2646 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
2647 c4e388a5 Guido Trotter
        else:
2648 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
2649 c4e388a5 Guido Trotter
                          result.stdout)
2650 30e42c4e Guido Trotter
      else:
2651 30e42c4e Guido Trotter
        status = match.group(1)
2652 6a1434d7 Andrea Spadaccini
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
2653 6a1434d7 Andrea Spadaccini
          migration_status = objects.MigrationStatus(status=status)
2654 61643226 Andrea Spadaccini
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
2655 61643226 Andrea Spadaccini
          if match:
2656 61643226 Andrea Spadaccini
            migration_status.transferred_ram = match.group("transferred")
2657 61643226 Andrea Spadaccini
            migration_status.total_ram = match.group("total")
2658 61643226 Andrea Spadaccini
2659 6a1434d7 Andrea Spadaccini
          return migration_status
2660 30e42c4e Guido Trotter
2661 6a1434d7 Andrea Spadaccini
        logging.warning("KVM: unknown migration status '%s'", status)
2662 6a1434d7 Andrea Spadaccini
2663 6a1434d7 Andrea Spadaccini
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
2664 6a1434d7 Andrea Spadaccini
2665 62457f51 Iustin Pop
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
2666 30e42c4e Guido Trotter
2667 3d836750 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
2668 3d836750 Guido Trotter
    """Balloon an instance memory to a certain value.
2669 3d836750 Guido Trotter

2670 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
2671 3d836750 Guido Trotter
    @param instance: instance to be accepted
2672 3d836750 Guido Trotter
    @type mem: int
2673 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
2674 3d836750 Guido Trotter

2675 3d836750 Guido Trotter
    """
2676 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2677 3d836750 Guido Trotter
2678 fac489a5 Helga Velroyen
  def GetNodeInfo(self, hvparams=None):
2679 eb58f9b1 Guido Trotter
    """Return information about the node.
2680 eb58f9b1 Guido Trotter

2681 fac489a5 Helga Velroyen
    @type hvparams: dict of strings
2682 fac489a5 Helga Velroyen
    @param hvparams: hypervisor parameters, not used in this class
2683 fac489a5 Helga Velroyen

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

2689 eb58f9b1 Guido Trotter
    """
2690 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
2691 25bce647 Santi Raffa
    kvmpath = constants.KVM_PATH
2692 25bce647 Santi Raffa
    if hvparams is not None:
2693 25bce647 Santi Raffa
      kvmpath = hvparams.get(constants.HV_KVM_PATH, constants.KVM_PATH)
2694 25bce647 Santi Raffa
    _, v_major, v_min, v_rev = self._GetKVMVersion(kvmpath)
2695 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2696 34fbc862 Andrea Spadaccini
    return result
2697 eb58f9b1 Guido Trotter
2698 637ce7f9 Guido Trotter
  @classmethod
2699 c42be2c0 Petr Pudlak
  def GetInstanceConsole(cls, instance, primary_node, node_group,
2700 c42be2c0 Petr Pudlak
                         hvparams, beparams):
2701 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
2702 eb58f9b1 Guido Trotter

2703 eb58f9b1 Guido Trotter
    """
2704 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2705 9d9bded1 Michael Hanselmann
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2706 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2707 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2708 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
2709 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2710 c42be2c0 Petr Pudlak
      ndparams = node_group.FillND(primary_node)
2711 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2712 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
2713 1c3231aa Thomas Thrainer
                                     host=primary_node.name,
2714 c42be2c0 Petr Pudlak
                                     port=ndparams.get(constants.ND_SSH_PORT),
2715 052783ff Michael Hanselmann
                                     user=constants.SSH_CONSOLE_USER,
2716 55cc0a44 Michael Hanselmann
                                     command=cmd)
2717 3be34f57 Guido Trotter
2718 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2719 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2720 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
2721 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2722 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
2723 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
2724 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
2725 55cc0a44 Michael Hanselmann
                                     display=display)
2726 55cc0a44 Michael Hanselmann
2727 4d2cdb5a Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2728 4d2cdb5a Andrea Spadaccini
    if spice_bind:
2729 4d2cdb5a Andrea Spadaccini
      return objects.InstanceConsole(instance=instance.name,
2730 4d2cdb5a Andrea Spadaccini
                                     kind=constants.CONS_SPICE,
2731 4d2cdb5a Andrea Spadaccini
                                     host=spice_bind,
2732 4d2cdb5a Andrea Spadaccini
                                     port=instance.network_port)
2733 4d2cdb5a Andrea Spadaccini
2734 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
2735 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
2736 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
2737 55cc0a44 Michael Hanselmann
                                            instance.name))
2738 eb58f9b1 Guido Trotter
2739 75bf3149 Helga Velroyen
  def Verify(self, hvparams=None):
2740 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
2741 eb58f9b1 Guido Trotter

2742 cd04dfd2 Michael Hanselmann
    Check that the required binaries exist.
2743 cd04dfd2 Michael Hanselmann

2744 75bf3149 Helga Velroyen
    @type hvparams: dict of strings
2745 75bf3149 Helga Velroyen
    @param hvparams: hypervisor parameters to be verified against, not used here
2746 75bf3149 Helga Velroyen

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

2749 eb58f9b1 Guido Trotter
    """
2750 1f4b9d39 Iustin Pop
    msgs = []
2751 25bce647 Santi Raffa
    kvmpath = constants.KVM_PATH
2752 25bce647 Santi Raffa
    if hvparams is not None:
2753 25bce647 Santi Raffa
      kvmpath = hvparams.get(constants.HV_KVM_PATH, constants.KVM_PATH)
2754 25bce647 Santi Raffa
    if not os.path.exists(kvmpath):
2755 25bce647 Santi Raffa
      msgs.append("The KVM binary ('%s') does not exist" % kvmpath)
2756 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2757 1f4b9d39 Iustin Pop
      msgs.append("The socat binary ('%s') does not exist" %
2758 1f4b9d39 Iustin Pop
                  constants.SOCAT_PATH)
2759 1f4b9d39 Iustin Pop
2760 1f4b9d39 Iustin Pop
    return self._FormatVerifyResults(msgs)
2761 14aa53cb Guido Trotter
2762 6b5605e8 Iustin Pop
  @classmethod
2763 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2764 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2765 6b5605e8 Iustin Pop

2766 6b5605e8 Iustin Pop
    @type hvparams:  dict
2767 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2768 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2769 6b5605e8 Iustin Pop

2770 6b5605e8 Iustin Pop
    """
2771 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2772 6b5605e8 Iustin Pop
2773 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
2774 df5ab9f0 Guido Trotter
    if kernel_path:
2775 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
2776 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
2777 205ab586 Iustin Pop
                                     " if a kernel is defined")
2778 6b5605e8 Iustin Pop
2779 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
2780 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
2781 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
2782 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
2783 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
2784 66d5dbef Guido Trotter
2785 14fd6c81 Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2786 14fd6c81 Guido Trotter
      serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2787 14fd6c81 Guido Trotter
      valid_speeds = constants.VALID_SERIAL_SPEEDS
2788 14fd6c81 Guido Trotter
      if not serial_speed or serial_speed not in valid_speeds:
2789 14fd6c81 Guido Trotter
        raise errors.HypervisorError("Invalid serial console speed, must be"
2790 14fd6c81 Guido Trotter
                                     " one of: %s" %
2791 14fd6c81 Guido Trotter
                                     utils.CommaJoin(valid_speeds))
2792 14fd6c81 Guido Trotter
2793 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2794 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
2795 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2796 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2797 835528af Iustin Pop
                                   " ISO path")
2798 f5118ade Iustin Pop
2799 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2800 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2801 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
2802 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
2803 d19d94db Guido Trotter
                                     " must be specified")
2804 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
2805 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
2806 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
2807 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
2808 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
2809 d19d94db Guido Trotter
2810 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2811 b451c4c7 Andrea Spadaccini
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2812 b1cb62bd Andrea Spadaccini
    if spice_bind:
2813 b1cb62bd Andrea Spadaccini
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2814 b1cb62bd Andrea Spadaccini
        # if an IP version is specified, the spice_bind parameter must be an
2815 b1cb62bd Andrea Spadaccini
        # IP of that family
2816 b1cb62bd Andrea Spadaccini
        if (netutils.IP4Address.IsValid(spice_bind) and
2817 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP4_VERSION):
2818 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv4 address (%s), but"
2819 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2820 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2821 b1cb62bd Andrea Spadaccini
2822 b1cb62bd Andrea Spadaccini
        if (netutils.IP6Address.IsValid(spice_bind) and
2823 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP6_VERSION):
2824 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv6 address (%s), but"
2825 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2826 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2827 b451c4c7 Andrea Spadaccini
    else:
2828 0e1b03b9 Andrea Spadaccini
      # All the other SPICE parameters depend on spice_bind being set. Raise an
2829 0e1b03b9 Andrea Spadaccini
      # error if any of them is set without it.
2830 07788a0b Michael Hanselmann
      for param in _SPICE_ADDITIONAL_PARAMS:
2831 0e1b03b9 Andrea Spadaccini
        if hvparams[param]:
2832 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: %s requires %s to be set" %
2833 0e1b03b9 Andrea Spadaccini
                                       (param, constants.HV_KVM_SPICE_BIND))
2834 b1cb62bd Andrea Spadaccini
2835 d19d94db Guido Trotter
  @classmethod
2836 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
2837 d19d94db Guido Trotter
    """Check the given parameters for validity.
2838 d19d94db Guido Trotter

2839 d19d94db Guido Trotter
    @type hvparams:  dict
2840 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2841 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2842 d19d94db Guido Trotter

2843 d19d94db Guido Trotter
    """
2844 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2845 d19d94db Guido Trotter
2846 82e3bf85 Dimitris Aragiorgis
    kvm_path = hvparams[constants.HV_KVM_PATH]
2847 82e3bf85 Dimitris Aragiorgis
2848 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2849 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2850 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2851 d19d94db Guido Trotter
      try:
2852 1feb39ec Guido Trotter
        pwd.getpwnam(username)
2853 d19d94db Guido Trotter
      except KeyError:
2854 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
2855 d19d94db Guido Trotter
                                     % username)
2856 d6e5767e Klaus Aehlig
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2857 d6e5767e Klaus Aehlig
    if vnc_bind_address:
2858 d6e5767e Klaus Aehlig
      bound_to_addr = netutils.IP4Address.IsValid(vnc_bind_address)
2859 d6e5767e Klaus Aehlig
      is_interface = netutils.IsValidInterface(vnc_bind_address)
2860 d6e5767e Klaus Aehlig
      is_path = utils.IsNormAbsPath(vnc_bind_address)
2861 d6e5767e Klaus Aehlig
      if not bound_to_addr and not is_interface and not is_path:
2862 d6e5767e Klaus Aehlig
        raise errors.HypervisorError("VNC: The %s parameter must be either"
2863 d6e5767e Klaus Aehlig
                                     " a valid IP address, an interface name,"
2864 d6e5767e Klaus Aehlig
                                     " or an absolute path" %
2865 d6e5767e Klaus Aehlig
                                     constants.HV_KVM_SPICE_BIND)
2866 d19d94db Guido Trotter
2867 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2868 b1cb62bd Andrea Spadaccini
    if spice_bind:
2869 b1cb62bd Andrea Spadaccini
      # only one of VNC and SPICE can be used currently.
2870 b1cb62bd Andrea Spadaccini
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2871 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("Both SPICE and VNC are configured, but"
2872 b1cb62bd Andrea Spadaccini
                                     " only one of them can be used at a"
2873 afa9bb2e Michael Hanselmann
                                     " given time")
2874 b1cb62bd Andrea Spadaccini
2875 3b59ec02 Guido Trotter
      # check that KVM supports SPICE
2876 6e043e60 Guido Trotter
      kvmhelp = cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP)
2877 0ad7f5d8 Guido Trotter
      if not cls._SPICE_RE.search(kvmhelp):
2878 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE is configured, but it is not"
2879 afa9bb2e Michael Hanselmann
                                     " supported according to 'kvm --help'")
2880 b1cb62bd Andrea Spadaccini
2881 b1cb62bd Andrea Spadaccini
      # if spice_bind is not an IP address, it must be a valid interface
2882 afa9bb2e Michael Hanselmann
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind) or
2883 afa9bb2e Michael Hanselmann
                       netutils.IP6Address.IsValid(spice_bind))
2884 b1cb62bd Andrea Spadaccini
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2885 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE: The %s parameter must be either"
2886 b1cb62bd Andrea Spadaccini
                                     " a valid IP address or interface name" %
2887 b1cb62bd Andrea Spadaccini
                                     constants.HV_KVM_SPICE_BIND)
2888 b1cb62bd Andrea Spadaccini
2889 82e3bf85 Dimitris Aragiorgis
    machine_version = hvparams[constants.HV_KVM_MACHINE_VERSION]
2890 82e3bf85 Dimitris Aragiorgis
    if machine_version:
2891 6e043e60 Guido Trotter
      output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2892 82e3bf85 Dimitris Aragiorgis
      if not cls._CHECK_MACHINE_VERSION_RE(machine_version).search(output):
2893 82e3bf85 Dimitris Aragiorgis
        raise errors.HypervisorError("Unsupported machine version: %s" %
2894 82e3bf85 Dimitris Aragiorgis
                                     machine_version)
2895 82e3bf85 Dimitris Aragiorgis
2896 f5118ade Iustin Pop
  @classmethod
2897 8ef418bb Helga Velroyen
  def PowercycleNode(cls, hvparams=None):
2898 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
2899 f5118ade Iustin Pop

2900 8ef418bb Helga Velroyen
    @type hvparams: dict of strings
2901 8ef418bb Helga Velroyen
    @param hvparams: hypervisor params to be used on this node
2902 8ef418bb Helga Velroyen

2903 f5118ade Iustin Pop
    """
2904 f5118ade Iustin Pop
    cls.LinuxPowercycle()