Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ e2800fca

History | View | Annotate | Download (94.9 kB)

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

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

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

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

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

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

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

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

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

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

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

194 e2800fca Dimitris Aragiorgis
  Remove any deprecated fields or change the format of the data.
195 e2800fca Dimitris Aragiorgis
  The runtime files are not upgraded when Ganeti is upgraded, so the required
196 e2800fca Dimitris Aragiorgis
  modification have to be performed here.
197 58502c9e Dimitris Aragiorgis

198 58502c9e Dimitris Aragiorgis
  @type serialized_runtime: string
199 58502c9e Dimitris Aragiorgis
  @param serialized_runtime: raw text data read from actual runtime file
200 e2800fca Dimitris Aragiorgis
  @return: (cmd, nic dicts, hvparams, bdev dicts)
201 e2800fca Dimitris Aragiorgis
  @rtype: tuple
202 58502c9e Dimitris Aragiorgis

203 58502c9e Dimitris Aragiorgis
  """
204 58502c9e Dimitris Aragiorgis
  loaded_runtime = serializer.Load(serialized_runtime)
205 e2800fca Dimitris Aragiorgis
  kvm_cmd, serialized_nics, hvparams = loaded_runtime[:3]
206 e2800fca Dimitris Aragiorgis
  if len(loaded_runtime) >= 4:
207 e2800fca Dimitris Aragiorgis
    serialized_disks = loaded_runtime[3]
208 58502c9e Dimitris Aragiorgis
  else:
209 e2800fca Dimitris Aragiorgis
    serialized_disks = []
210 e2800fca Dimitris Aragiorgis
211 e2800fca Dimitris Aragiorgis
  for nic in serialized_nics:
212 e2800fca Dimitris Aragiorgis
    # Add a dummy uuid slot if an pre-2.8 NIC is found
213 e2800fca Dimitris Aragiorgis
    if "uuid" not in nic:
214 e2800fca Dimitris Aragiorgis
      nic["uuid"] = utils.NewUUID()
215 e2800fca Dimitris Aragiorgis
216 e2800fca Dimitris Aragiorgis
  return kvm_cmd, serialized_nics, hvparams, serialized_disks
217 e2800fca Dimitris Aragiorgis
218 58502c9e Dimitris Aragiorgis
219 e2800fca Dimitris Aragiorgis
def _AnalyzeSerializedRuntime(serialized_runtime):
220 e2800fca Dimitris Aragiorgis
  """Return runtime entries for a serialized runtime file
221 e2800fca Dimitris Aragiorgis

222 e2800fca Dimitris Aragiorgis
  @type serialized_runtime: string
223 e2800fca Dimitris Aragiorgis
  @param serialized_runtime: raw text data read from actual runtime file
224 e2800fca Dimitris Aragiorgis
  @return: (cmd, nics, hvparams, bdevs)
225 e2800fca Dimitris Aragiorgis
  @rtype: tuple
226 e2800fca Dimitris Aragiorgis

227 e2800fca Dimitris Aragiorgis
  """
228 e2800fca Dimitris Aragiorgis
  kvm_cmd, serialized_nics, hvparams, serialized_disks = \
229 e2800fca Dimitris Aragiorgis
    _UpgradeSerializedRuntime(serialized_runtime)
230 58502c9e Dimitris Aragiorgis
  kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
231 4a44d8aa Dimitris Aragiorgis
  kvm_disks = [(objects.Disk.FromDict(sdisk), link)
232 4a44d8aa Dimitris Aragiorgis
               for sdisk, link in serialized_disks]
233 58502c9e Dimitris Aragiorgis
234 4a44d8aa Dimitris Aragiorgis
  return (kvm_cmd, kvm_nics, hvparams, kvm_disks)
235 58502c9e Dimitris Aragiorgis
236 199b2053 Apollon Oikonomopoulos
237 ea2bcb82 Michael Hanselmann
def _GetTunFeatures(fd, _ioctl=fcntl.ioctl):
238 ea2bcb82 Michael Hanselmann
  """Retrieves supported TUN features from file descriptor.
239 ea2bcb82 Michael Hanselmann

240 ea2bcb82 Michael Hanselmann
  @see: L{_ProbeTapVnetHdr}
241 ea2bcb82 Michael Hanselmann

242 ea2bcb82 Michael Hanselmann
  """
243 ea2bcb82 Michael Hanselmann
  req = struct.pack("I", 0)
244 ea2bcb82 Michael Hanselmann
  try:
245 ea2bcb82 Michael Hanselmann
    buf = _ioctl(fd, TUNGETFEATURES, req)
246 ea2bcb82 Michael Hanselmann
  except EnvironmentError, err:
247 cfc24646 Iustin Pop
    logging.warning("ioctl(TUNGETFEATURES) failed: %s", err)
248 ea2bcb82 Michael Hanselmann
    return None
249 ea2bcb82 Michael Hanselmann
  else:
250 ea2bcb82 Michael Hanselmann
    (flags, ) = struct.unpack("I", buf)
251 ea2bcb82 Michael Hanselmann
    return flags
252 ea2bcb82 Michael Hanselmann
253 ea2bcb82 Michael Hanselmann
254 ea2bcb82 Michael Hanselmann
def _ProbeTapVnetHdr(fd, _features_fn=_GetTunFeatures):
255 199b2053 Apollon Oikonomopoulos
  """Check whether to enable the IFF_VNET_HDR flag.
256 199b2053 Apollon Oikonomopoulos

257 199b2053 Apollon Oikonomopoulos
  To do this, _all_ of the following conditions must be met:
258 199b2053 Apollon Oikonomopoulos
   1. TUNGETFEATURES ioctl() *must* be implemented
259 199b2053 Apollon Oikonomopoulos
   2. TUNGETFEATURES ioctl() result *must* contain the IFF_VNET_HDR flag
260 199b2053 Apollon Oikonomopoulos
   3. TUNGETIFF ioctl() *must* be implemented; reading the kernel code in
261 199b2053 Apollon Oikonomopoulos
      drivers/net/tun.c there is no way to test this until after the tap device
262 199b2053 Apollon Oikonomopoulos
      has been created using TUNSETIFF, and there is no way to change the
263 199b2053 Apollon Oikonomopoulos
      IFF_VNET_HDR flag after creating the interface, catch-22! However both
264 199b2053 Apollon Oikonomopoulos
      TUNGETIFF and TUNGETFEATURES were introduced in kernel version 2.6.27,
265 199b2053 Apollon Oikonomopoulos
      thus we can expect TUNGETIFF to be present if TUNGETFEATURES is.
266 199b2053 Apollon Oikonomopoulos

267 199b2053 Apollon Oikonomopoulos
   @type fd: int
268 199b2053 Apollon Oikonomopoulos
   @param fd: the file descriptor of /dev/net/tun
269 199b2053 Apollon Oikonomopoulos

270 199b2053 Apollon Oikonomopoulos
  """
271 ea2bcb82 Michael Hanselmann
  flags = _features_fn(fd)
272 199b2053 Apollon Oikonomopoulos
273 ea2bcb82 Michael Hanselmann
  if flags is None:
274 ea2bcb82 Michael Hanselmann
    # Not supported
275 199b2053 Apollon Oikonomopoulos
    return False
276 199b2053 Apollon Oikonomopoulos
277 ea2bcb82 Michael Hanselmann
  result = bool(flags & IFF_VNET_HDR)
278 ea2bcb82 Michael Hanselmann
279 ea2bcb82 Michael Hanselmann
  if not result:
280 ea2bcb82 Michael Hanselmann
    logging.warning("Kernel does not support IFF_VNET_HDR, not enabling")
281 ea2bcb82 Michael Hanselmann
282 ea2bcb82 Michael Hanselmann
  return result
283 ea2bcb82 Michael Hanselmann
284 199b2053 Apollon Oikonomopoulos
285 199b2053 Apollon Oikonomopoulos
def _OpenTap(vnet_hdr=True):
286 199b2053 Apollon Oikonomopoulos
  """Open a new tap device and return its file descriptor.
287 199b2053 Apollon Oikonomopoulos

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

291 199b2053 Apollon Oikonomopoulos
  @type vnet_hdr: boolean
292 199b2053 Apollon Oikonomopoulos
  @param vnet_hdr: Enable the VNET Header
293 199b2053 Apollon Oikonomopoulos
  @return: (ifname, tapfd)
294 199b2053 Apollon Oikonomopoulos
  @rtype: tuple
295 199b2053 Apollon Oikonomopoulos

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

324 91c10532 Andrea Spadaccini
  """
325 91c10532 Andrea Spadaccini
  def __init__(self, data):
326 91c10532 Andrea Spadaccini
    """Creates a new QMP message based on the passed data.
327 91c10532 Andrea Spadaccini

328 91c10532 Andrea Spadaccini
    """
329 91c10532 Andrea Spadaccini
    if not isinstance(data, dict):
330 91c10532 Andrea Spadaccini
      raise TypeError("QmpMessage must be initialized with a dict")
331 91c10532 Andrea Spadaccini
332 91c10532 Andrea Spadaccini
    self.data = data
333 91c10532 Andrea Spadaccini
334 91c10532 Andrea Spadaccini
  def __getitem__(self, field_name):
335 91c10532 Andrea Spadaccini
    """Get the value of the required field if present, or None.
336 91c10532 Andrea Spadaccini

337 91c10532 Andrea Spadaccini
    Overrides the [] operator to provide access to the message data,
338 91c10532 Andrea Spadaccini
    returning None if the required item is not in the message
339 91c10532 Andrea Spadaccini
    @return: the value of the field_name field, or None if field_name
340 91c10532 Andrea Spadaccini
             is not contained in the message
341 91c10532 Andrea Spadaccini

342 91c10532 Andrea Spadaccini
    """
343 9b87c2cf Michael Hanselmann
    return self.data.get(field_name, None)
344 91c10532 Andrea Spadaccini
345 91c10532 Andrea Spadaccini
  def __setitem__(self, field_name, field_value):
346 91c10532 Andrea Spadaccini
    """Set the value of the required field_name to field_value.
347 91c10532 Andrea Spadaccini

348 91c10532 Andrea Spadaccini
    """
349 91c10532 Andrea Spadaccini
    self.data[field_name] = field_value
350 91c10532 Andrea Spadaccini
351 91c10532 Andrea Spadaccini
  @staticmethod
352 91c10532 Andrea Spadaccini
  def BuildFromJsonString(json_string):
353 91c10532 Andrea Spadaccini
    """Build a QmpMessage from a JSON encoded string.
354 91c10532 Andrea Spadaccini

355 91c10532 Andrea Spadaccini
    @type json_string: str
356 91c10532 Andrea Spadaccini
    @param json_string: JSON string representing the message
357 91c10532 Andrea Spadaccini
    @rtype: L{QmpMessage}
358 91c10532 Andrea Spadaccini
    @return: a L{QmpMessage} built from json_string
359 91c10532 Andrea Spadaccini

360 91c10532 Andrea Spadaccini
    """
361 91c10532 Andrea Spadaccini
    # Parse the string
362 91c10532 Andrea Spadaccini
    data = serializer.LoadJson(json_string)
363 91c10532 Andrea Spadaccini
    return QmpMessage(data)
364 91c10532 Andrea Spadaccini
365 91c10532 Andrea Spadaccini
  def __str__(self):
366 a182a3ed Michael Hanselmann
    # The protocol expects the JSON object to be sent as a single line.
367 a182a3ed Michael Hanselmann
    return serializer.DumpJson(self.data)
368 91c10532 Andrea Spadaccini
369 91c10532 Andrea Spadaccini
  def __eq__(self, other):
370 91c10532 Andrea Spadaccini
    # When comparing two QmpMessages, we are interested in comparing
371 91c10532 Andrea Spadaccini
    # their internal representation of the message data
372 91c10532 Andrea Spadaccini
    return self.data == other.data
373 91c10532 Andrea Spadaccini
374 91c10532 Andrea Spadaccini
375 172a75dc Dimitris Aragiorgis
class MonitorSocket(object):
376 91c10532 Andrea Spadaccini
  _SOCKET_TIMEOUT = 5
377 91c10532 Andrea Spadaccini
378 91c10532 Andrea Spadaccini
  def __init__(self, monitor_filename):
379 172a75dc Dimitris Aragiorgis
    """Instantiates the MonitorSocket object.
380 91c10532 Andrea Spadaccini

381 91c10532 Andrea Spadaccini
    @type monitor_filename: string
382 91c10532 Andrea Spadaccini
    @param monitor_filename: the filename of the UNIX raw socket on which the
383 172a75dc Dimitris Aragiorgis
                             monitor (QMP or simple one) is listening
384 91c10532 Andrea Spadaccini

385 91c10532 Andrea Spadaccini
    """
386 91c10532 Andrea Spadaccini
    self.monitor_filename = monitor_filename
387 91c10532 Andrea Spadaccini
    self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
388 91c10532 Andrea Spadaccini
    # We want to fail if the server doesn't send a complete message
389 91c10532 Andrea Spadaccini
    # in a reasonable amount of time
390 91c10532 Andrea Spadaccini
    self.sock.settimeout(self._SOCKET_TIMEOUT)
391 91c10532 Andrea Spadaccini
    self._connected = False
392 91c10532 Andrea Spadaccini
393 fc84cd5d Guido Trotter
  def _check_socket(self):
394 fc84cd5d Guido Trotter
    sock_stat = None
395 fc84cd5d Guido Trotter
    try:
396 fc84cd5d Guido Trotter
      sock_stat = os.stat(self.monitor_filename)
397 fc84cd5d Guido Trotter
    except EnvironmentError, err:
398 fc84cd5d Guido Trotter
      if err.errno == errno.ENOENT:
399 172a75dc Dimitris Aragiorgis
        raise errors.HypervisorError("No monitor socket found")
400 fc84cd5d Guido Trotter
      else:
401 172a75dc Dimitris Aragiorgis
        raise errors.HypervisorError("Error checking monitor socket: %s",
402 fc84cd5d Guido Trotter
                                     utils.ErrnoOrStr(err))
403 fc84cd5d Guido Trotter
    if not stat.S_ISSOCK(sock_stat.st_mode):
404 172a75dc Dimitris Aragiorgis
      raise errors.HypervisorError("Monitor socket is not a socket")
405 fc84cd5d Guido Trotter
406 91c10532 Andrea Spadaccini
  def _check_connection(self):
407 91c10532 Andrea Spadaccini
    """Make sure that the connection is established.
408 91c10532 Andrea Spadaccini

409 91c10532 Andrea Spadaccini
    """
410 91c10532 Andrea Spadaccini
    if not self._connected:
411 172a75dc Dimitris Aragiorgis
      raise errors.ProgrammerError("To use a MonitorSocket you need to first"
412 91c10532 Andrea Spadaccini
                                   " invoke connect() on it")
413 91c10532 Andrea Spadaccini
414 91c10532 Andrea Spadaccini
  def connect(self):
415 172a75dc Dimitris Aragiorgis
    """Connects to the monitor.
416 91c10532 Andrea Spadaccini

417 172a75dc Dimitris Aragiorgis
    Connects to the UNIX socket
418 91c10532 Andrea Spadaccini

419 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
420 91c10532 Andrea Spadaccini

421 91c10532 Andrea Spadaccini
    """
422 fc84cd5d Guido Trotter
    if self._connected:
423 fc84cd5d Guido Trotter
      raise errors.ProgrammerError("Cannot connect twice")
424 fc84cd5d Guido Trotter
425 fc84cd5d Guido Trotter
    self._check_socket()
426 fc84cd5d Guido Trotter
427 fc84cd5d Guido Trotter
    # Check file existance/stuff
428 fc84cd5d Guido Trotter
    try:
429 fc84cd5d Guido Trotter
      self.sock.connect(self.monitor_filename)
430 fc84cd5d Guido Trotter
    except EnvironmentError:
431 fc84cd5d Guido Trotter
      raise errors.HypervisorError("Can't connect to qmp socket")
432 91c10532 Andrea Spadaccini
    self._connected = True
433 91c10532 Andrea Spadaccini
434 172a75dc Dimitris Aragiorgis
  def close(self):
435 172a75dc Dimitris Aragiorgis
    """Closes the socket
436 172a75dc Dimitris Aragiorgis

437 172a75dc Dimitris Aragiorgis
    It cannot be used after this call.
438 172a75dc Dimitris Aragiorgis

439 172a75dc Dimitris Aragiorgis
    """
440 172a75dc Dimitris Aragiorgis
    self.sock.close()
441 172a75dc Dimitris Aragiorgis
442 172a75dc Dimitris Aragiorgis
443 172a75dc Dimitris Aragiorgis
class QmpConnection(MonitorSocket):
444 172a75dc Dimitris Aragiorgis
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
445 172a75dc Dimitris Aragiorgis

446 172a75dc Dimitris Aragiorgis
  """
447 172a75dc Dimitris Aragiorgis
  _FIRST_MESSAGE_KEY = "QMP"
448 172a75dc Dimitris Aragiorgis
  _EVENT_KEY = "event"
449 172a75dc Dimitris Aragiorgis
  _ERROR_KEY = "error"
450 172a75dc Dimitris Aragiorgis
  _RETURN_KEY = RETURN_KEY = "return"
451 172a75dc Dimitris Aragiorgis
  _ACTUAL_KEY = ACTUAL_KEY = "actual"
452 172a75dc Dimitris Aragiorgis
  _ERROR_CLASS_KEY = "class"
453 172a75dc Dimitris Aragiorgis
  _ERROR_DATA_KEY = "data"
454 172a75dc Dimitris Aragiorgis
  _ERROR_DESC_KEY = "desc"
455 172a75dc Dimitris Aragiorgis
  _EXECUTE_KEY = "execute"
456 172a75dc Dimitris Aragiorgis
  _ARGUMENTS_KEY = "arguments"
457 172a75dc Dimitris Aragiorgis
  _CAPABILITIES_COMMAND = "qmp_capabilities"
458 172a75dc Dimitris Aragiorgis
  _MESSAGE_END_TOKEN = "\r\n"
459 172a75dc Dimitris Aragiorgis
460 172a75dc Dimitris Aragiorgis
  def __init__(self, monitor_filename):
461 172a75dc Dimitris Aragiorgis
    super(QmpConnection, self).__init__(monitor_filename)
462 172a75dc Dimitris Aragiorgis
    self._buf = ""
463 172a75dc Dimitris Aragiorgis
464 172a75dc Dimitris Aragiorgis
  def connect(self):
465 172a75dc Dimitris Aragiorgis
    """Connects to the QMP monitor.
466 172a75dc Dimitris Aragiorgis

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

470 172a75dc Dimitris Aragiorgis
    @raise errors.HypervisorError: when there are communication errors
471 172a75dc Dimitris Aragiorgis
    @raise errors.ProgrammerError: when there are data serialization errors
472 172a75dc Dimitris Aragiorgis

473 172a75dc Dimitris Aragiorgis
    """
474 172a75dc Dimitris Aragiorgis
    super(QmpConnection, self).connect()
475 91c10532 Andrea Spadaccini
    # Check if we receive a correct greeting message from the server
476 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 2.2)
477 91c10532 Andrea Spadaccini
    greeting = self._Recv()
478 91c10532 Andrea Spadaccini
    if not greeting[self._FIRST_MESSAGE_KEY]:
479 91c10532 Andrea Spadaccini
      self._connected = False
480 afa9bb2e Michael Hanselmann
      raise errors.HypervisorError("kvm: QMP communication error (wrong"
481 91c10532 Andrea Spadaccini
                                   " server greeting")
482 91c10532 Andrea Spadaccini
483 91c10532 Andrea Spadaccini
    # Let's put the monitor in command mode using the qmp_capabilities
484 91c10532 Andrea Spadaccini
    # command, or else no command will be executable.
485 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 4)
486 91c10532 Andrea Spadaccini
    self.Execute(self._CAPABILITIES_COMMAND)
487 91c10532 Andrea Spadaccini
488 91c10532 Andrea Spadaccini
  def _ParseMessage(self, buf):
489 91c10532 Andrea Spadaccini
    """Extract and parse a QMP message from the given buffer.
490 91c10532 Andrea Spadaccini

491 91c10532 Andrea Spadaccini
    Seeks for a QMP message in the given buf. If found, it parses it and
492 91c10532 Andrea Spadaccini
    returns it together with the rest of the characters in the buf.
493 91c10532 Andrea Spadaccini
    If no message is found, returns None and the whole buffer.
494 91c10532 Andrea Spadaccini

495 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
496 91c10532 Andrea Spadaccini

497 91c10532 Andrea Spadaccini
    """
498 91c10532 Andrea Spadaccini
    message = None
499 91c10532 Andrea Spadaccini
    # Check if we got the message end token (CRLF, as per the QEMU Protocol
500 91c10532 Andrea Spadaccini
    # Specification 0.1 - Section 2.1.1)
501 91c10532 Andrea Spadaccini
    pos = buf.find(self._MESSAGE_END_TOKEN)
502 91c10532 Andrea Spadaccini
    if pos >= 0:
503 91c10532 Andrea Spadaccini
      try:
504 91c10532 Andrea Spadaccini
        message = QmpMessage.BuildFromJsonString(buf[:pos + 1])
505 91c10532 Andrea Spadaccini
      except Exception, err:
506 91c10532 Andrea Spadaccini
        raise errors.ProgrammerError("QMP data serialization error: %s" % err)
507 91c10532 Andrea Spadaccini
      buf = buf[pos + 1:]
508 91c10532 Andrea Spadaccini
509 91c10532 Andrea Spadaccini
    return (message, buf)
510 91c10532 Andrea Spadaccini
511 91c10532 Andrea Spadaccini
  def _Recv(self):
512 91c10532 Andrea Spadaccini
    """Receives a message from QMP and decodes the received JSON object.
513 91c10532 Andrea Spadaccini

514 91c10532 Andrea Spadaccini
    @rtype: QmpMessage
515 91c10532 Andrea Spadaccini
    @return: the received message
516 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
517 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
518 91c10532 Andrea Spadaccini

519 91c10532 Andrea Spadaccini
    """
520 91c10532 Andrea Spadaccini
    self._check_connection()
521 91c10532 Andrea Spadaccini
522 91c10532 Andrea Spadaccini
    # Check if there is already a message in the buffer
523 91c10532 Andrea Spadaccini
    (message, self._buf) = self._ParseMessage(self._buf)
524 91c10532 Andrea Spadaccini
    if message:
525 91c10532 Andrea Spadaccini
      return message
526 91c10532 Andrea Spadaccini
527 91c10532 Andrea Spadaccini
    recv_buffer = StringIO.StringIO(self._buf)
528 91c10532 Andrea Spadaccini
    recv_buffer.seek(len(self._buf))
529 91c10532 Andrea Spadaccini
    try:
530 91c10532 Andrea Spadaccini
      while True:
531 91c10532 Andrea Spadaccini
        data = self.sock.recv(4096)
532 91c10532 Andrea Spadaccini
        if not data:
533 91c10532 Andrea Spadaccini
          break
534 91c10532 Andrea Spadaccini
        recv_buffer.write(data)
535 91c10532 Andrea Spadaccini
536 91c10532 Andrea Spadaccini
        (message, self._buf) = self._ParseMessage(recv_buffer.getvalue())
537 91c10532 Andrea Spadaccini
        if message:
538 91c10532 Andrea Spadaccini
          return message
539 91c10532 Andrea Spadaccini
540 91c10532 Andrea Spadaccini
    except socket.timeout, err:
541 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while receiving a QMP message: "
542 91c10532 Andrea Spadaccini
                                   "%s" % (err))
543 91c10532 Andrea Spadaccini
    except socket.error, err:
544 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to receive data from KVM using the"
545 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
546 91c10532 Andrea Spadaccini
547 91c10532 Andrea Spadaccini
  def _Send(self, message):
548 91c10532 Andrea Spadaccini
    """Encodes and sends a message to KVM using QMP.
549 91c10532 Andrea Spadaccini

550 91c10532 Andrea Spadaccini
    @type message: QmpMessage
551 91c10532 Andrea Spadaccini
    @param message: message to send to KVM
552 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
553 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
554 91c10532 Andrea Spadaccini

555 91c10532 Andrea Spadaccini
    """
556 91c10532 Andrea Spadaccini
    self._check_connection()
557 91c10532 Andrea Spadaccini
    try:
558 91c10532 Andrea Spadaccini
      message_str = str(message)
559 91c10532 Andrea Spadaccini
    except Exception, err:
560 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("QMP data deserialization error: %s" % err)
561 91c10532 Andrea Spadaccini
562 91c10532 Andrea Spadaccini
    try:
563 91c10532 Andrea Spadaccini
      self.sock.sendall(message_str)
564 91c10532 Andrea Spadaccini
    except socket.timeout, err:
565 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while sending a QMP message: "
566 91c10532 Andrea Spadaccini
                                   "%s (%s)" % (err.string, err.errno))
567 91c10532 Andrea Spadaccini
    except socket.error, err:
568 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to send data from KVM using the"
569 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
570 91c10532 Andrea Spadaccini
571 91c10532 Andrea Spadaccini
  def Execute(self, command, arguments=None):
572 91c10532 Andrea Spadaccini
    """Executes a QMP command and returns the response of the server.
573 91c10532 Andrea Spadaccini

574 91c10532 Andrea Spadaccini
    @type command: str
575 91c10532 Andrea Spadaccini
    @param command: the command to execute
576 91c10532 Andrea Spadaccini
    @type arguments: dict
577 91c10532 Andrea Spadaccini
    @param arguments: dictionary of arguments to be passed to the command
578 91c10532 Andrea Spadaccini
    @rtype: dict
579 91c10532 Andrea Spadaccini
    @return: dictionary representing the received JSON object
580 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
581 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
582 91c10532 Andrea Spadaccini

583 91c10532 Andrea Spadaccini
    """
584 91c10532 Andrea Spadaccini
    self._check_connection()
585 91c10532 Andrea Spadaccini
    message = QmpMessage({self._EXECUTE_KEY: command})
586 91c10532 Andrea Spadaccini
    if arguments:
587 91c10532 Andrea Spadaccini
      message[self._ARGUMENTS_KEY] = arguments
588 91c10532 Andrea Spadaccini
    self._Send(message)
589 91c10532 Andrea Spadaccini
590 91c10532 Andrea Spadaccini
    # Events can occur between the sending of the command and the reception
591 91c10532 Andrea Spadaccini
    # of the response, so we need to filter out messages with the event key.
592 91c10532 Andrea Spadaccini
    while True:
593 91c10532 Andrea Spadaccini
      response = self._Recv()
594 91c10532 Andrea Spadaccini
      err = response[self._ERROR_KEY]
595 91c10532 Andrea Spadaccini
      if err:
596 91c10532 Andrea Spadaccini
        raise errors.HypervisorError("kvm: error executing the %s"
597 91c10532 Andrea Spadaccini
                                     " command: %s (%s, %s):" %
598 91c10532 Andrea Spadaccini
                                     (command,
599 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DESC_KEY],
600 91c10532 Andrea Spadaccini
                                      err[self._ERROR_CLASS_KEY],
601 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DATA_KEY]))
602 91c10532 Andrea Spadaccini
603 91c10532 Andrea Spadaccini
      elif not response[self._EVENT_KEY]:
604 91c10532 Andrea Spadaccini
        return response
605 91c10532 Andrea Spadaccini
606 91c10532 Andrea Spadaccini
607 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
608 65107a2f Michael Hanselmann
  """KVM hypervisor interface
609 65107a2f Michael Hanselmann

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

794 98ec75d6 Iustin Pop
    """
795 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
796 98ec75d6 Iustin Pop
797 263b8de6 Guido Trotter
  @classmethod
798 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
799 7548396c Guido Trotter
    """Returns the instance uidfile.
800 7548396c Guido Trotter

801 7548396c Guido Trotter
    """
802 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
803 7548396c Guido Trotter
804 7548396c Guido Trotter
  @classmethod
805 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
806 263b8de6 Guido Trotter
    """Check pid file for instance information.
807 263b8de6 Guido Trotter

808 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
809 263b8de6 Guido Trotter
    information from its command line.
810 263b8de6 Guido Trotter

811 263b8de6 Guido Trotter
    @type pid: string or int
812 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
813 263b8de6 Guido Trotter
    @rtype: tuple
814 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
815 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
816 263b8de6 Guido Trotter

817 263b8de6 Guido Trotter
    """
818 263b8de6 Guido Trotter
    alive = utils.IsProcessAlive(pid)
819 263b8de6 Guido Trotter
    if not alive:
820 263b8de6 Guido Trotter
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
821 263b8de6 Guido Trotter
822 263b8de6 Guido Trotter
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
823 263b8de6 Guido Trotter
    try:
824 263b8de6 Guido Trotter
      cmdline = utils.ReadFile(cmdline_file)
825 263b8de6 Guido Trotter
    except EnvironmentError, err:
826 263b8de6 Guido Trotter
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
827 263b8de6 Guido Trotter
                                   (pid, err))
828 263b8de6 Guido Trotter
829 263b8de6 Guido Trotter
    instance = None
830 263b8de6 Guido Trotter
    memory = 0
831 263b8de6 Guido Trotter
    vcpus = 0
832 263b8de6 Guido Trotter
833 d0c8c01d Iustin Pop
    arg_list = cmdline.split("\x00")
834 263b8de6 Guido Trotter
    while arg_list:
835 e687ec01 Michael Hanselmann
      arg = arg_list.pop(0)
836 263b8de6 Guido Trotter
      if arg == "-name":
837 263b8de6 Guido Trotter
        instance = arg_list.pop(0)
838 263b8de6 Guido Trotter
      elif arg == "-m":
839 263b8de6 Guido Trotter
        memory = int(arg_list.pop(0))
840 263b8de6 Guido Trotter
      elif arg == "-smp":
841 4888a609 Guido Trotter
        vcpus = int(arg_list.pop(0).split(",")[0])
842 263b8de6 Guido Trotter
843 263b8de6 Guido Trotter
    if instance is None:
844 263b8de6 Guido Trotter
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
845 263b8de6 Guido Trotter
                                   " instance" % pid)
846 263b8de6 Guido Trotter
847 263b8de6 Guido Trotter
    return (instance, memory, vcpus)
848 263b8de6 Guido Trotter
849 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
850 263b8de6 Guido Trotter
    """Returns the instance pidfile, pid, and liveness.
851 263b8de6 Guido Trotter

852 263b8de6 Guido Trotter
    @type instance_name: string
853 263b8de6 Guido Trotter
    @param instance_name: instance name
854 263b8de6 Guido Trotter
    @rtype: tuple
855 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
856 1f8b3a27 Guido Trotter

857 1f8b3a27 Guido Trotter
    """
858 98ec75d6 Iustin Pop
    pidfile = self._InstancePidFile(instance_name)
859 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
860 263b8de6 Guido Trotter
861 263b8de6 Guido Trotter
    alive = False
862 263b8de6 Guido Trotter
    try:
863 263b8de6 Guido Trotter
      cmd_instance = self._InstancePidInfo(pid)[0]
864 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
865 263b8de6 Guido Trotter
    except errors.HypervisorError:
866 263b8de6 Guido Trotter
      pass
867 1f8b3a27 Guido Trotter
868 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
869 1f8b3a27 Guido Trotter
870 5905901c Iustin Pop
  def _CheckDown(self, instance_name):
871 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
872 5905901c Iustin Pop

873 5905901c Iustin Pop
    """
874 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
875 5905901c Iustin Pop
    if alive:
876 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
877 5905901c Iustin Pop
                                   (instance_name, "already running"))
878 5905901c Iustin Pop
879 0df4d98a Guido Trotter
  @classmethod
880 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
881 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
882 c4fbefc8 Guido Trotter

883 c4fbefc8 Guido Trotter
    """
884 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
885 c4fbefc8 Guido Trotter
886 0df4d98a Guido Trotter
  @classmethod
887 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
888 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
889 c4fbefc8 Guido Trotter

890 c4fbefc8 Guido Trotter
    """
891 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
892 c4fbefc8 Guido Trotter
893 91c10532 Andrea Spadaccini
  @classmethod
894 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
895 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
896 91c10532 Andrea Spadaccini

897 91c10532 Andrea Spadaccini
    """
898 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
899 91c10532 Andrea Spadaccini
900 86d6bc2a Guido Trotter
  @staticmethod
901 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
902 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
903 86d6bc2a Guido Trotter

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

906 86d6bc2a Guido Trotter
    """
907 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
908 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
909 86d6bc2a Guido Trotter
    else:
910 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
911 86d6bc2a Guido Trotter
912 0df4d98a Guido Trotter
  @classmethod
913 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
914 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
915 38e250ba Guido Trotter

916 38e250ba Guido Trotter
    """
917 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
918 38e250ba Guido Trotter
919 7e66c35b Guido Trotter
  @classmethod
920 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
921 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
922 547a63b7 Balazs Lecz

923 547a63b7 Balazs Lecz
    """
924 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
925 547a63b7 Balazs Lecz
926 547a63b7 Balazs Lecz
  @classmethod
927 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
928 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
929 5d9bfd87 Apollon Oikonomopoulos
    given instance.
930 5d9bfd87 Apollon Oikonomopoulos

931 5d9bfd87 Apollon Oikonomopoulos
    """
932 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
933 5d9bfd87 Apollon Oikonomopoulos
934 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
935 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
936 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
937 5d9bfd87 Apollon Oikonomopoulos

938 5d9bfd87 Apollon Oikonomopoulos
    """
939 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
940 5d9bfd87 Apollon Oikonomopoulos
941 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
942 4f580fef Sรฉbastien Bocahu
  def _InstanceKeymapFile(cls, instance_name):
943 4f580fef Sรฉbastien Bocahu
    """Returns the name of the file containing the keymap for a given instance
944 4f580fef Sรฉbastien Bocahu

945 4f580fef Sรฉbastien Bocahu
    """
946 4f580fef Sรฉbastien Bocahu
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
947 4f580fef Sรฉbastien Bocahu
948 4f580fef Sรฉbastien Bocahu
  @classmethod
949 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
950 7548396c Guido Trotter
    """Try to read a uid file
951 7548396c Guido Trotter

952 7548396c Guido Trotter
    """
953 7548396c Guido Trotter
    if os.path.exists(uid_file):
954 7548396c Guido Trotter
      try:
955 682f7601 Guido Trotter
        uid = int(utils.ReadOneLineFile(uid_file))
956 aa0b600b Guido Trotter
        return uid
957 7548396c Guido Trotter
      except EnvironmentError:
958 7548396c Guido Trotter
        logging.warning("Can't read uid file", exc_info=True)
959 7548396c Guido Trotter
      except (TypeError, ValueError):
960 7548396c Guido Trotter
        logging.warning("Can't parse uid file contents", exc_info=True)
961 aa0b600b Guido Trotter
    return None
962 7548396c Guido Trotter
963 7548396c Guido Trotter
  @classmethod
964 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
965 547a63b7 Balazs Lecz
    """Removes an instance's rutime sockets/files/dirs.
966 7e66c35b Guido Trotter

967 7e66c35b Guido Trotter
    """
968 7e66c35b Guido Trotter
    utils.RemoveFile(pidfile)
969 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
970 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceSerial(instance_name))
971 91c10532 Andrea Spadaccini
    utils.RemoveFile(cls._InstanceQmpMonitor(instance_name))
972 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
973 4f580fef Sรฉbastien Bocahu
    utils.RemoveFile(cls._InstanceKeymapFile(instance_name))
974 7548396c Guido Trotter
    uid_file = cls._InstanceUidFile(instance_name)
975 7548396c Guido Trotter
    uid = cls._TryReadUidFile(uid_file)
976 7548396c Guido Trotter
    utils.RemoveFile(uid_file)
977 7548396c Guido Trotter
    if uid is not None:
978 7548396c Guido Trotter
      uidpool.ReleaseUid(uid)
979 7be85163 Guido Trotter
    try:
980 7be85163 Guido Trotter
      shutil.rmtree(cls._InstanceNICDir(instance_name))
981 7be85163 Guido Trotter
    except OSError, err:
982 7be85163 Guido Trotter
      if err.errno != errno.ENOENT:
983 7be85163 Guido Trotter
        raise
984 547a63b7 Balazs Lecz
    try:
985 547a63b7 Balazs Lecz
      chroot_dir = cls._InstanceChrootDir(instance_name)
986 547a63b7 Balazs Lecz
      utils.RemoveDir(chroot_dir)
987 547a63b7 Balazs Lecz
    except OSError, err:
988 547a63b7 Balazs Lecz
      if err.errno == errno.ENOTEMPTY:
989 547a63b7 Balazs Lecz
        # The chroot directory is expected to be empty, but it isn't.
990 547a63b7 Balazs Lecz
        new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
991 547a63b7 Balazs Lecz
                                          prefix="%s-%s-" %
992 547a63b7 Balazs Lecz
                                          (instance_name,
993 547a63b7 Balazs Lecz
                                           utils.TimestampForFilename()))
994 547a63b7 Balazs Lecz
        logging.warning("The chroot directory of instance %s can not be"
995 547a63b7 Balazs Lecz
                        " removed as it is not empty. Moving it to the"
996 547a63b7 Balazs Lecz
                        " quarantine instead. Please investigate the"
997 547a63b7 Balazs Lecz
                        " contents (%s) and clean up manually",
998 547a63b7 Balazs Lecz
                        instance_name, new_chroot_dir)
999 547a63b7 Balazs Lecz
        utils.RenameFile(chroot_dir, new_chroot_dir)
1000 547a63b7 Balazs Lecz
      else:
1001 547a63b7 Balazs Lecz
        raise
1002 7e66c35b Guido Trotter
1003 748e4b5a Michael Hanselmann
  @staticmethod
1004 5d9bfd87 Apollon Oikonomopoulos
  def _ConfigureNIC(instance, seq, nic, tap):
1005 5d9bfd87 Apollon Oikonomopoulos
    """Run the network configuration script for a specified NIC
1006 eb58f9b1 Guido Trotter

1007 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
1008 eb58f9b1 Guido Trotter
    @type instance: instance object
1009 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
1010 eb58f9b1 Guido Trotter
    @type seq: int
1011 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
1012 eb58f9b1 Guido Trotter
    @type nic: nic object
1013 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
1014 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
1015 eb58f9b1 Guido Trotter

1016 eb58f9b1 Guido Trotter
    """
1017 5d9bfd87 Apollon Oikonomopoulos
    env = {
1018 5d9bfd87 Apollon Oikonomopoulos
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
1019 5d9bfd87 Apollon Oikonomopoulos
      "INSTANCE": instance.name,
1020 5d9bfd87 Apollon Oikonomopoulos
      "MAC": nic.mac,
1021 5d9bfd87 Apollon Oikonomopoulos
      "MODE": nic.nicparams[constants.NIC_MODE],
1022 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE": tap,
1023 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE_INDEX": str(seq),
1024 6ba0093c Dimitris Aragiorgis
      "INTERFACE_UUID": nic.uuid,
1025 7d4ae909 Dimitris Aragiorgis
      "TAGS": " ".join(instance.GetTags()),
1026 5d9bfd87 Apollon Oikonomopoulos
    }
1027 5d9bfd87 Apollon Oikonomopoulos
1028 5d9bfd87 Apollon Oikonomopoulos
    if nic.ip:
1029 5d9bfd87 Apollon Oikonomopoulos
      env["IP"] = nic.ip
1030 5d9bfd87 Apollon Oikonomopoulos
1031 6ba0093c Dimitris Aragiorgis
    if nic.name:
1032 6ba0093c Dimitris Aragiorgis
      env["INTERFACE_NAME"] = nic.name
1033 6ba0093c Dimitris Aragiorgis
1034 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_LINK]:
1035 5d9bfd87 Apollon Oikonomopoulos
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
1036 5d9bfd87 Apollon Oikonomopoulos
1037 a5ad5e58 Apollon Oikonomopoulos
    if nic.network:
1038 cbe4a0a5 Dimitris Aragiorgis
      n = objects.Network.FromDict(nic.netinfo)
1039 7e8f03e3 Dimitris Aragiorgis
      env.update(n.HooksDict())
1040 a5ad5e58 Apollon Oikonomopoulos
1041 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1042 5d9bfd87 Apollon Oikonomopoulos
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
1043 5d9bfd87 Apollon Oikonomopoulos
1044 9d9bded1 Michael Hanselmann
    result = utils.RunCmd([pathutils.KVM_IFUP, tap], env=env)
1045 5d9bfd87 Apollon Oikonomopoulos
    if result.failed:
1046 afa9bb2e Michael Hanselmann
      raise errors.HypervisorError("Failed to configure interface %s: %s;"
1047 afa9bb2e Michael Hanselmann
                                   " network configuration script output: %s" %
1048 5d9bfd87 Apollon Oikonomopoulos
                                   (tap, result.fail_reason, result.output))
1049 eb58f9b1 Guido Trotter
1050 b693125f Tsachy Shacham
  @staticmethod
1051 b693125f Tsachy Shacham
  def _VerifyAffinityPackage():
1052 b693125f Tsachy Shacham
    if affinity is None:
1053 b693125f Tsachy Shacham
      raise errors.HypervisorError("affinity Python package not"
1054 5ae4945a Iustin Pop
                                   " found; cannot use CPU pinning under KVM")
1055 b693125f Tsachy Shacham
1056 b693125f Tsachy Shacham
  @staticmethod
1057 b693125f Tsachy Shacham
  def _BuildAffinityCpuMask(cpu_list):
1058 b693125f Tsachy Shacham
    """Create a CPU mask suitable for sched_setaffinity from a list of
1059 b693125f Tsachy Shacham
    CPUs.
1060 b693125f Tsachy Shacham

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

1064 b693125f Tsachy Shacham
    @type cpu_list: list of int
1065 b693125f Tsachy Shacham
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
1066 b693125f Tsachy Shacham
    @rtype: int
1067 b693125f Tsachy Shacham
    @return: a bit mask of CPU affinities
1068 b693125f Tsachy Shacham

1069 b693125f Tsachy Shacham
    """
1070 b693125f Tsachy Shacham
    if cpu_list == constants.CPU_PINNING_OFF:
1071 b693125f Tsachy Shacham
      return constants.CPU_PINNING_ALL_KVM
1072 b693125f Tsachy Shacham
    else:
1073 b693125f Tsachy Shacham
      return sum(2 ** cpu for cpu in cpu_list)
1074 b693125f Tsachy Shacham
1075 b693125f Tsachy Shacham
  @classmethod
1076 b693125f Tsachy Shacham
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
1077 b693125f Tsachy Shacham
    """Change CPU affinity for running VM according to given CPU mask.
1078 b693125f Tsachy Shacham

1079 b693125f Tsachy Shacham
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
1080 b693125f Tsachy Shacham
    @type cpu_mask: string
1081 b693125f Tsachy Shacham
    @param process_id: process ID of KVM process. Used to pin entire VM
1082 b693125f Tsachy Shacham
                       to physical CPUs.
1083 b693125f Tsachy Shacham
    @type process_id: int
1084 b693125f Tsachy Shacham
    @param thread_dict: map of virtual CPUs to KVM thread IDs
1085 b693125f Tsachy Shacham
    @type thread_dict: dict int:int
1086 b693125f Tsachy Shacham

1087 b693125f Tsachy Shacham
    """
1088 b693125f Tsachy Shacham
    # Convert the string CPU mask to a list of list of int's
1089 b693125f Tsachy Shacham
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
1090 b693125f Tsachy Shacham
1091 b693125f Tsachy Shacham
    if len(cpu_list) == 1:
1092 b693125f Tsachy Shacham
      all_cpu_mapping = cpu_list[0]
1093 b693125f Tsachy Shacham
      if all_cpu_mapping == constants.CPU_PINNING_OFF:
1094 b693125f Tsachy Shacham
        # If CPU pinning has 1 entry that's "all", then do nothing
1095 b693125f Tsachy Shacham
        pass
1096 b693125f Tsachy Shacham
      else:
1097 b693125f Tsachy Shacham
        # If CPU pinning has one non-all entry, map the entire VM to
1098 b693125f Tsachy Shacham
        # one set of physical CPUs
1099 b693125f Tsachy Shacham
        cls._VerifyAffinityPackage()
1100 5ae4945a Iustin Pop
        affinity.set_process_affinity_mask(
1101 5ae4945a Iustin Pop
          process_id, cls._BuildAffinityCpuMask(all_cpu_mapping))
1102 b693125f Tsachy Shacham
    else:
1103 b693125f Tsachy Shacham
      # The number of vCPUs mapped should match the number of vCPUs
1104 b693125f Tsachy Shacham
      # reported by KVM. This was already verified earlier, so
1105 b693125f Tsachy Shacham
      # here only as a sanity check.
1106 b693125f Tsachy Shacham
      assert len(thread_dict) == len(cpu_list)
1107 b693125f Tsachy Shacham
      cls._VerifyAffinityPackage()
1108 b693125f Tsachy Shacham
1109 b693125f Tsachy Shacham
      # For each vCPU, map it to the proper list of physical CPUs
1110 b693125f Tsachy Shacham
      for vcpu, i in zip(cpu_list, range(len(cpu_list))):
1111 b693125f Tsachy Shacham
        affinity.set_process_affinity_mask(thread_dict[i],
1112 5ae4945a Iustin Pop
                                           cls._BuildAffinityCpuMask(vcpu))
1113 b693125f Tsachy Shacham
1114 b693125f Tsachy Shacham
  def _GetVcpuThreadIds(self, instance_name):
1115 b693125f Tsachy Shacham
    """Get a mapping of vCPU no. to thread IDs for the instance
1116 b693125f Tsachy Shacham

1117 b693125f Tsachy Shacham
    @type instance_name: string
1118 b693125f Tsachy Shacham
    @param instance_name: instance in question
1119 b693125f Tsachy Shacham
    @rtype: dictionary of int:int
1120 b693125f Tsachy Shacham
    @return: a dictionary mapping vCPU numbers to thread IDs
1121 b693125f Tsachy Shacham

1122 b693125f Tsachy Shacham
    """
1123 b693125f Tsachy Shacham
    result = {}
1124 b693125f Tsachy Shacham
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
1125 b693125f Tsachy Shacham
    for line in output.stdout.splitlines():
1126 b693125f Tsachy Shacham
      match = self._CPU_INFO_RE.search(line)
1127 b693125f Tsachy Shacham
      if not match:
1128 b693125f Tsachy Shacham
        continue
1129 b693125f Tsachy Shacham
      grp = map(int, match.groups())
1130 b693125f Tsachy Shacham
      result[grp[0]] = grp[1]
1131 b693125f Tsachy Shacham
1132 b693125f Tsachy Shacham
    return result
1133 b693125f Tsachy Shacham
1134 1d8a7812 Andrea Spadaccini
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
1135 1d8a7812 Andrea Spadaccini
    """Complete CPU pinning.
1136 b693125f Tsachy Shacham

1137 b693125f Tsachy Shacham
    @type instance_name: string
1138 b693125f Tsachy Shacham
    @param instance_name: name of instance
1139 b693125f Tsachy Shacham
    @type cpu_mask: string
1140 b693125f Tsachy Shacham
    @param cpu_mask: CPU pinning mask as entered by user
1141 b693125f Tsachy Shacham

1142 b693125f Tsachy Shacham
    """
1143 1d8a7812 Andrea Spadaccini
    # Get KVM process ID, to be used if need to pin entire VM
1144 1d8a7812 Andrea Spadaccini
    _, pid, _ = self._InstancePidAlive(instance_name)
1145 1d8a7812 Andrea Spadaccini
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
1146 1d8a7812 Andrea Spadaccini
    thread_dict = self._GetVcpuThreadIds(instance_name)
1147 1d8a7812 Andrea Spadaccini
    # Run CPU pinning, based on configured mask
1148 1d8a7812 Andrea Spadaccini
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
1149 b693125f Tsachy Shacham
1150 eb58f9b1 Guido Trotter
  def ListInstances(self):
1151 eb58f9b1 Guido Trotter
    """Get the list of running instances.
1152 eb58f9b1 Guido Trotter

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

1156 eb58f9b1 Guido Trotter
    """
1157 eb58f9b1 Guido Trotter
    result = []
1158 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1159 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
1160 eb58f9b1 Guido Trotter
        result.append(name)
1161 eb58f9b1 Guido Trotter
    return result
1162 eb58f9b1 Guido Trotter
1163 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
1164 eb58f9b1 Guido Trotter
    """Get instance properties.
1165 eb58f9b1 Guido Trotter

1166 4fbb3c60 Guido Trotter
    @type instance_name: string
1167 c41eea6e Iustin Pop
    @param instance_name: the instance name
1168 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
1169 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
1170 eb58f9b1 Guido Trotter

1171 eb58f9b1 Guido Trotter
    """
1172 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
1173 1f8b3a27 Guido Trotter
    if not alive:
1174 eb58f9b1 Guido Trotter
      return None
1175 eb58f9b1 Guido Trotter
1176 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
1177 fc84cd5d Guido Trotter
    istat = "---b-"
1178 eb58f9b1 Guido Trotter
    times = "0"
1179 eb58f9b1 Guido Trotter
1180 89da2ff3 Guido Trotter
    try:
1181 89da2ff3 Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
1182 89da2ff3 Guido Trotter
      qmp.connect()
1183 89da2ff3 Guido Trotter
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
1184 89da2ff3 Guido Trotter
      # Will fail if ballooning is not enabled, but we can then just resort to
1185 89da2ff3 Guido Trotter
      # the value above.
1186 89da2ff3 Guido Trotter
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
1187 89da2ff3 Guido Trotter
      memory = mem_bytes / 1048576
1188 89da2ff3 Guido Trotter
    except errors.HypervisorError:
1189 89da2ff3 Guido Trotter
      pass
1190 89da2ff3 Guido Trotter
1191 fc84cd5d Guido Trotter
    return (instance_name, pid, memory, vcpus, istat, times)
1192 eb58f9b1 Guido Trotter
1193 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
1194 eb58f9b1 Guido Trotter
    """Get properties of all instances.
1195 eb58f9b1 Guido Trotter

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

1198 eb58f9b1 Guido Trotter
    """
1199 eb58f9b1 Guido Trotter
    data = []
1200 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1201 263b8de6 Guido Trotter
      try:
1202 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
1203 263b8de6 Guido Trotter
      except errors.HypervisorError:
1204 3bc145d8 Bernardo Dal Seno
        # Ignore exceptions due to instances being shut down
1205 263b8de6 Guido Trotter
        continue
1206 263b8de6 Guido Trotter
      if info:
1207 263b8de6 Guido Trotter
        data.append(info)
1208 eb58f9b1 Guido Trotter
    return data
1209 eb58f9b1 Guido Trotter
1210 4a44d8aa Dimitris Aragiorgis
  def _GenerateKVMBlockDevicesOptions(self, instance, kvm_disks,
1211 e419e42f Dimitris Aragiorgis
                                      kvmhelp, devlist):
1212 e419e42f Dimitris Aragiorgis
    """Generate KVM options regarding instance's block devices.
1213 e419e42f Dimitris Aragiorgis

1214 e419e42f Dimitris Aragiorgis
    @type instance: L{objects.Instance}
1215 e419e42f Dimitris Aragiorgis
    @param instance: the instance object
1216 4a44d8aa Dimitris Aragiorgis
    @type kvm_disks: list of tuples
1217 4a44d8aa Dimitris Aragiorgis
    @param kvm_disks: list of tuples [(disk, link_name)..]
1218 e419e42f Dimitris Aragiorgis
    @type kvmhelp: string
1219 e419e42f Dimitris Aragiorgis
    @param kvmhelp: output of kvm --help
1220 e419e42f Dimitris Aragiorgis
    @type devlist: string
1221 e419e42f Dimitris Aragiorgis
    @param devlist: output of kvm -device ?
1222 e419e42f Dimitris Aragiorgis
    @rtype: list
1223 e419e42f Dimitris Aragiorgis
    @return: list of command line options eventually used by kvm executable
1224 ece1057c Dimitris Aragiorgis

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

1298 b73f1c59 Guido Trotter
    @type kvmhelp: string
1299 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1300 839642c2 Iustin Pop
    @attention: this function must not have any side-effects; for
1301 839642c2 Iustin Pop
        example, it must not write to the filesystem, or read values
1302 839642c2 Iustin Pop
        from the current system the are expected to differ between
1303 839642c2 Iustin Pop
        nodes, since it is only run once at instance startup;
1304 839642c2 Iustin Pop
        actions/kvm arguments that can vary between systems should be
1305 839642c2 Iustin Pop
        done in L{_ExecuteKVMRuntime}
1306 839642c2 Iustin Pop

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

1648 38e250ba Guido Trotter
    """
1649 38e250ba Guido Trotter
    try:
1650 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1651 38e250ba Guido Trotter
                      data=data)
1652 90c024f6 Guido Trotter
    except EnvironmentError, err:
1653 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1654 38e250ba Guido Trotter
1655 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
1656 38e250ba Guido Trotter
    """Read an instance's KVM runtime
1657 38e250ba Guido Trotter

1658 38e250ba Guido Trotter
    """
1659 38e250ba Guido Trotter
    try:
1660 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1661 90c024f6 Guido Trotter
    except EnvironmentError, err:
1662 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1663 38e250ba Guido Trotter
    return file_content
1664 38e250ba Guido Trotter
1665 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1666 38e250ba Guido Trotter
    """Save an instance's KVM runtime
1667 38e250ba Guido Trotter

1668 38e250ba Guido Trotter
    """
1669 4a44d8aa Dimitris Aragiorgis
    kvm_cmd, kvm_nics, hvparams, kvm_disks = kvm_runtime
1670 58502c9e Dimitris Aragiorgis
1671 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1672 4a44d8aa Dimitris Aragiorgis
    serialized_disks = [(blk.ToDict(), link)
1673 4a44d8aa Dimitris Aragiorgis
                            for blk, link in kvm_disks]
1674 58502c9e Dimitris Aragiorgis
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams,
1675 4a44d8aa Dimitris Aragiorgis
                                      serialized_disks))
1676 58502c9e Dimitris Aragiorgis
1677 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
1678 38e250ba Guido Trotter
1679 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1680 38e250ba Guido Trotter
    """Load an instance's KVM runtime
1681 38e250ba Guido Trotter

1682 38e250ba Guido Trotter
    """
1683 30e42c4e Guido Trotter
    if not serialized_runtime:
1684 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1685 58502c9e Dimitris Aragiorgis
1686 58502c9e Dimitris Aragiorgis
    return _AnalyzeSerializedRuntime(serialized_runtime)
1687 38e250ba Guido Trotter
1688 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1689 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
1690 76431533 Guido Trotter

1691 76431533 Guido Trotter
    @type name: string
1692 76431533 Guido Trotter
    @param name: instance name
1693 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1694 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1695 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1696 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1697 76431533 Guido Trotter

1698 76431533 Guido Trotter
    """
1699 5d9bfd87 Apollon Oikonomopoulos
    try:
1700 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1701 5d9bfd87 Apollon Oikonomopoulos
    finally:
1702 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
1703 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
1704 5d9bfd87 Apollon Oikonomopoulos
1705 76431533 Guido Trotter
    if result.failed:
1706 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1707 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
1708 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
1709 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
1710 76431533 Guido Trotter
1711 4a44d8aa Dimitris Aragiorgis
  # too many local variables
1712 58502c9e Dimitris Aragiorgis
  # pylint: disable=R0914
1713 b73f1c59 Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1714 839642c2 Iustin Pop
    """Execute a KVM cmd, after completing it with some last minute data.
1715 ee5f20b0 Guido Trotter

1716 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1717 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1718 b73f1c59 Guido Trotter
    @type kvmhelp: string
1719 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1720 30e42c4e Guido Trotter

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

1939 ee5f20b0 Guido Trotter
    """
1940 5905901c Iustin Pop
    self._CheckDown(instance.name)
1941 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1942 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1943 7238edb5 Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1944 b73f1c59 Guido Trotter
                                           startup_paused, kvmhelp)
1945 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1946 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1947 ee5f20b0 Guido Trotter
1948 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
1949 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
1950 6567aff3 Guido Trotter

1951 6567aff3 Guido Trotter
    """
1952 eace6157 Michael Hanselmann
    # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
1953 eace6157 Michael Hanselmann
    # version. The monitor protocol is designed for human consumption, whereas
1954 eace6157 Michael Hanselmann
    # QMP is made for programmatic usage. In the worst case QMP can also
1955 eace6157 Michael Hanselmann
    # execute monitor commands. As it is, all calls to socat take at least
1956 eace6157 Michael Hanselmann
    # 500ms and likely more: socat can't detect the end of the reply and waits
1957 eace6157 Michael Hanselmann
    # for 500ms of no data received before exiting (500 ms is the default for
1958 eace6157 Michael Hanselmann
    # the "-t" parameter).
1959 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1960 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
1961 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
1962 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1963 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
1964 6567aff3 Guido Trotter
    if result.failed:
1965 afa9bb2e Michael Hanselmann
      msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
1966 afa9bb2e Michael Hanselmann
             " output: %s" %
1967 afa9bb2e Michael Hanselmann
             (command, instance_name, result.fail_reason, result.output))
1968 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
1969 6567aff3 Guido Trotter
1970 6567aff3 Guido Trotter
    return result
1971 6567aff3 Guido Trotter
1972 8b7be6f2 Dimitris Aragiorgis
  def _GetFreePCISlot(self, instance, dev):
1973 8b7be6f2 Dimitris Aragiorgis
    """Get the first available pci slot of a runnung instance.
1974 8b7be6f2 Dimitris Aragiorgis

1975 8b7be6f2 Dimitris Aragiorgis
    """
1976 8b7be6f2 Dimitris Aragiorgis
    slots = bitarray(32)
1977 8b7be6f2 Dimitris Aragiorgis
    slots.setall(False) # pylint: disable=E1101
1978 8b7be6f2 Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance.name, self._INFO_PCI_CMD)
1979 8b7be6f2 Dimitris Aragiorgis
    for line in output.stdout.splitlines():
1980 8b7be6f2 Dimitris Aragiorgis
      match = self._INFO_PCI_RE.search(line)
1981 8b7be6f2 Dimitris Aragiorgis
      if match:
1982 8b7be6f2 Dimitris Aragiorgis
        slot = int(match.group(1))
1983 8b7be6f2 Dimitris Aragiorgis
        slots[slot] = True
1984 8b7be6f2 Dimitris Aragiorgis
1985 8b7be6f2 Dimitris Aragiorgis
    [free] = slots.search(_AVAILABLE_PCI_SLOT, 1) # pylint: disable=E1101
1986 8b7be6f2 Dimitris Aragiorgis
    if not free:
1987 8b7be6f2 Dimitris Aragiorgis
      raise errors.HypervisorError("All PCI slots occupied")
1988 8b7be6f2 Dimitris Aragiorgis
1989 8b7be6f2 Dimitris Aragiorgis
    dev.pci = int(free)
1990 8b7be6f2 Dimitris Aragiorgis
1991 9f395c32 Dimitris Aragiorgis
  def VerifyHotplugSupport(self, instance, action, dev_type):
1992 9f395c32 Dimitris Aragiorgis
    """Verifies that hotplug is supported.
1993 d7583563 Dimitris Aragiorgis

1994 d7583563 Dimitris Aragiorgis
    Hotplug is *not* supported in case of:
1995 d7583563 Dimitris Aragiorgis
     - security models and chroot (disk hotplug)
1996 d7583563 Dimitris Aragiorgis
     - fdsend module is missing (nic hot-add)
1997 d7583563 Dimitris Aragiorgis

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

2000 d7583563 Dimitris Aragiorgis
    """
2001 d7583563 Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2002 d7583563 Dimitris Aragiorgis
      hvp = instance.hvparams
2003 d7583563 Dimitris Aragiorgis
      security_model = hvp[constants.HV_SECURITY_MODEL]
2004 d7583563 Dimitris Aragiorgis
      use_chroot = hvp[constants.HV_KVM_USE_CHROOT]
2005 d7583563 Dimitris Aragiorgis
      if use_chroot:
2006 d7583563 Dimitris Aragiorgis
        raise errors.HotplugError("Disk hotplug is not supported"
2007 d7583563 Dimitris Aragiorgis
                                  " in case of chroot.")
2008 d7583563 Dimitris Aragiorgis
      if security_model != constants.HT_SM_NONE:
2009 d7583563 Dimitris Aragiorgis
        raise errors.HotplugError("Disk Hotplug is not supported in case"
2010 d7583563 Dimitris Aragiorgis
                                  " security models are used.")
2011 d7583563 Dimitris Aragiorgis
2012 d7583563 Dimitris Aragiorgis
    if (dev_type == constants.HOTPLUG_TARGET_NIC and
2013 d7583563 Dimitris Aragiorgis
        action == constants.HOTPLUG_ACTION_ADD and not fdsend):
2014 d7583563 Dimitris Aragiorgis
      raise errors.HotplugError("Cannot hot-add NIC."
2015 d7583563 Dimitris Aragiorgis
                                " fdsend python module is missing.")
2016 d7583563 Dimitris Aragiorgis
2017 caf74756 Dimitris Aragiorgis
  def HotplugSupported(self, instance):
2018 caf74756 Dimitris Aragiorgis
    """Checks if hotplug is generally supported.
2019 caf74756 Dimitris Aragiorgis

2020 caf74756 Dimitris Aragiorgis
    Hotplug is *not* supported in case of:
2021 caf74756 Dimitris Aragiorgis
     - qemu versions < 1.0
2022 caf74756 Dimitris Aragiorgis
     - for stopped instances
2023 caf74756 Dimitris Aragiorgis

2024 caf74756 Dimitris Aragiorgis
    @raise errors.HypervisorError: in one of the previous cases
2025 caf74756 Dimitris Aragiorgis

2026 caf74756 Dimitris Aragiorgis
    """
2027 e7a77eb8 Dimitris Aragiorgis
    try:
2028 e7a77eb8 Dimitris Aragiorgis
      output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD)
2029 e7a77eb8 Dimitris Aragiorgis
    except errors.HypervisorError:
2030 e7a77eb8 Dimitris Aragiorgis
      raise errors.HotplugError("Instance is probably down")
2031 e7a77eb8 Dimitris Aragiorgis
2032 caf74756 Dimitris Aragiorgis
    # TODO: search for netdev_add, drive_add, device_add.....
2033 caf74756 Dimitris Aragiorgis
    match = self._INFO_VERSION_RE.search(output.stdout)
2034 caf74756 Dimitris Aragiorgis
    if not match:
2035 e7a77eb8 Dimitris Aragiorgis
      raise errors.HotplugError("Cannot parse qemu version via monitor")
2036 e7a77eb8 Dimitris Aragiorgis
2037 caf74756 Dimitris Aragiorgis
    v_major, v_min, _, _ = match.groups()
2038 caf74756 Dimitris Aragiorgis
    if (int(v_major), int(v_min)) < (1, 0):
2039 caf74756 Dimitris Aragiorgis
      raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0")
2040 caf74756 Dimitris Aragiorgis
2041 d7583563 Dimitris Aragiorgis
  def _CallHotplugCommand(self, name, cmd):
2042 d7583563 Dimitris Aragiorgis
    output = self._CallMonitorCommand(name, cmd)
2043 d7583563 Dimitris Aragiorgis
    # TODO: parse output and check if succeeded
2044 d7583563 Dimitris Aragiorgis
    for line in output.stdout.splitlines():
2045 d7583563 Dimitris Aragiorgis
      logging.info("%s", line)
2046 d7583563 Dimitris Aragiorgis
2047 af2f716d Dimitris Aragiorgis
  def HotAddDevice(self, instance, dev_type, device, extra, seq):
2048 af2f716d Dimitris Aragiorgis
    """ Helper method to hot-add a new device
2049 af2f716d Dimitris Aragiorgis

2050 af2f716d Dimitris Aragiorgis
    It gets free pci slot generates the device name and invokes the
2051 af2f716d Dimitris Aragiorgis
    device specific method.
2052 af2f716d Dimitris Aragiorgis

2053 af2f716d Dimitris Aragiorgis
    """
2054 af2f716d Dimitris Aragiorgis
    # in case of hot-mod this is given
2055 af2f716d Dimitris Aragiorgis
    if device.pci is None:
2056 af2f716d Dimitris Aragiorgis
      self._GetFreePCISlot(instance, device)
2057 af2f716d Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, device)
2058 af2f716d Dimitris Aragiorgis
    runtime = self._LoadKVMRuntime(instance)
2059 af2f716d Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2060 af2f716d Dimitris Aragiorgis
      command = "drive_add dummy file=%s,if=none,id=%s,format=raw\n" % \
2061 af2f716d Dimitris Aragiorgis
                 (extra, kvm_devid)
2062 af2f716d Dimitris Aragiorgis
      command += ("device_add virtio-blk-pci,bus=pci.0,addr=%s,drive=%s,id=%s" %
2063 af2f716d Dimitris Aragiorgis
                  (hex(device.pci), kvm_devid, kvm_devid))
2064 af2f716d Dimitris Aragiorgis
    elif dev_type == constants.HOTPLUG_TARGET_NIC:
2065 af2f716d Dimitris Aragiorgis
      (tap, fd) = _OpenTap()
2066 af2f716d Dimitris Aragiorgis
      self._ConfigureNIC(instance, seq, device, tap)
2067 af2f716d Dimitris Aragiorgis
      self._PassTapFd(instance, fd, device)
2068 af2f716d Dimitris Aragiorgis
      command = "netdev_add tap,id=%s,fd=%s\n" % (kvm_devid, kvm_devid)
2069 af2f716d Dimitris Aragiorgis
      args = "virtio-net-pci,bus=pci.0,addr=%s,mac=%s,netdev=%s,id=%s" % \
2070 af2f716d Dimitris Aragiorgis
               (hex(device.pci), device.mac, kvm_devid, kvm_devid)
2071 af2f716d Dimitris Aragiorgis
      command += "device_add %s" % args
2072 af2f716d Dimitris Aragiorgis
      utils.WriteFile(self._InstanceNICFile(instance.name, seq), data=tap)
2073 af2f716d Dimitris Aragiorgis
2074 af2f716d Dimitris Aragiorgis
    self._CallHotplugCommand(instance.name, command)
2075 af2f716d Dimitris Aragiorgis
    # update relevant entries in runtime file
2076 af2f716d Dimitris Aragiorgis
    index = _DEVICE_RUNTIME_INDEX[dev_type]
2077 af2f716d Dimitris Aragiorgis
    entry = _RUNTIME_ENTRY[dev_type](device, extra)
2078 af2f716d Dimitris Aragiorgis
    runtime[index].append(entry)
2079 af2f716d Dimitris Aragiorgis
    self._SaveKVMRuntime(instance, runtime)
2080 af2f716d Dimitris Aragiorgis
2081 af2f716d Dimitris Aragiorgis
  def HotDelDevice(self, instance, dev_type, device, _, seq):
2082 af2f716d Dimitris Aragiorgis
    """ Helper method for hot-del device
2083 af2f716d Dimitris Aragiorgis

2084 af2f716d Dimitris Aragiorgis
    It gets device info from runtime file, generates the device name and
2085 af2f716d Dimitris Aragiorgis
    invokes the device specific method.
2086 af2f716d Dimitris Aragiorgis

2087 af2f716d Dimitris Aragiorgis
    """
2088 af2f716d Dimitris Aragiorgis
    runtime = self._LoadKVMRuntime(instance)
2089 af2f716d Dimitris Aragiorgis
    entry = _GetExistingDeviceInfo(dev_type, device, runtime)
2090 af2f716d Dimitris Aragiorgis
    kvm_device = _RUNTIME_DEVICE[dev_type](entry)
2091 af2f716d Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, kvm_device)
2092 af2f716d Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2093 1c6c4d6d Dimitris Aragiorgis
      command = "device_del %s\n" % kvm_devid
2094 1c6c4d6d Dimitris Aragiorgis
      command += "drive_del %s" % kvm_devid
2095 af2f716d Dimitris Aragiorgis
    elif dev_type == constants.HOTPLUG_TARGET_NIC:
2096 af2f716d Dimitris Aragiorgis
      command = "device_del %s\n" % kvm_devid
2097 af2f716d Dimitris Aragiorgis
      command += "netdev_del %s" % kvm_devid
2098 af2f716d Dimitris Aragiorgis
      utils.RemoveFile(self._InstanceNICFile(instance.name, seq))
2099 af2f716d Dimitris Aragiorgis
    self._CallHotplugCommand(instance.name, command)
2100 af2f716d Dimitris Aragiorgis
    index = _DEVICE_RUNTIME_INDEX[dev_type]
2101 af2f716d Dimitris Aragiorgis
    runtime[index].remove(entry)
2102 af2f716d Dimitris Aragiorgis
    self._SaveKVMRuntime(instance, runtime)
2103 af2f716d Dimitris Aragiorgis
2104 af2f716d Dimitris Aragiorgis
    return kvm_device.pci
2105 af2f716d Dimitris Aragiorgis
2106 af2f716d Dimitris Aragiorgis
  def HotModDevice(self, instance, dev_type, device, _, seq):
2107 af2f716d Dimitris Aragiorgis
    """ Helper method for hot-mod device
2108 af2f716d Dimitris Aragiorgis

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

2112 af2f716d Dimitris Aragiorgis
    """
2113 af2f716d Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_NIC:
2114 af2f716d Dimitris Aragiorgis
      # putting it back in the same pci slot
2115 af2f716d Dimitris Aragiorgis
      device.pci = self.HotDelDevice(instance, dev_type, device, _, seq)
2116 af2f716d Dimitris Aragiorgis
      # TODO: remove sleep when socat gets removed
2117 af2f716d Dimitris Aragiorgis
      time.sleep(2)
2118 af2f716d Dimitris Aragiorgis
      self.HotAddDevice(instance, dev_type, device, _, seq)
2119 af2f716d Dimitris Aragiorgis
2120 af2f716d Dimitris Aragiorgis
  def _PassTapFd(self, instance, fd, nic):
2121 af2f716d Dimitris Aragiorgis
    """Pass file descriptor to kvm process via monitor socket using SCM_RIGHTS
2122 af2f716d Dimitris Aragiorgis

2123 af2f716d Dimitris Aragiorgis
    """
2124 af2f716d Dimitris Aragiorgis
    # TODO: factor out code related to unix sockets.
2125 af2f716d Dimitris Aragiorgis
    #       squash common parts between monitor and qmp
2126 af2f716d Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_NIC, nic)
2127 af2f716d Dimitris Aragiorgis
    command = "getfd %s\n" % kvm_devid
2128 af2f716d Dimitris Aragiorgis
    fds = [fd]
2129 af2f716d Dimitris Aragiorgis
    logging.info("%s", fds)
2130 af2f716d Dimitris Aragiorgis
    try:
2131 af2f716d Dimitris Aragiorgis
      monsock = MonitorSocket(self._InstanceMonitor(instance.name))
2132 af2f716d Dimitris Aragiorgis
      monsock.connect()
2133 af2f716d Dimitris Aragiorgis
      fdsend.sendfds(monsock.sock, command, fds=fds)
2134 af2f716d Dimitris Aragiorgis
    finally:
2135 af2f716d Dimitris Aragiorgis
      monsock.close()
2136 af2f716d Dimitris Aragiorgis
2137 b52d85c1 Guido Trotter
  @classmethod
2138 585c8187 Guido Trotter
  def _ParseKVMVersion(cls, text):
2139 585c8187 Guido Trotter
    """Parse the KVM version from the --help output.
2140 585c8187 Guido Trotter

2141 585c8187 Guido Trotter
    @type text: string
2142 585c8187 Guido Trotter
    @param text: output of kvm --help
2143 585c8187 Guido Trotter
    @return: (version, v_maj, v_min, v_rev)
2144 5c3d5dfd Iustin Pop
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
2145 585c8187 Guido Trotter

2146 585c8187 Guido Trotter
    """
2147 585c8187 Guido Trotter
    match = cls._VERSION_RE.search(text.splitlines()[0])
2148 585c8187 Guido Trotter
    if not match:
2149 585c8187 Guido Trotter
      raise errors.HypervisorError("Unable to get KVM version")
2150 585c8187 Guido Trotter
2151 585c8187 Guido Trotter
    v_all = match.group(0)
2152 585c8187 Guido Trotter
    v_maj = int(match.group(1))
2153 585c8187 Guido Trotter
    v_min = int(match.group(2))
2154 585c8187 Guido Trotter
    if match.group(4):
2155 585c8187 Guido Trotter
      v_rev = int(match.group(4))
2156 585c8187 Guido Trotter
    else:
2157 585c8187 Guido Trotter
      v_rev = 0
2158 585c8187 Guido Trotter
    return (v_all, v_maj, v_min, v_rev)
2159 585c8187 Guido Trotter
2160 585c8187 Guido Trotter
  @classmethod
2161 6e043e60 Guido Trotter
  def _GetKVMOutput(cls, kvm_path, option):
2162 6e043e60 Guido Trotter
    """Return the output of a kvm invocation
2163 e3b89628 Guido Trotter

2164 bc0fed4b Guido Trotter
    @type kvm_path: string
2165 bc0fed4b Guido Trotter
    @param kvm_path: path to the kvm executable
2166 bc0fed4b Guido Trotter
    @type option: a key of _KVMOPTS_CMDS
2167 bc0fed4b Guido Trotter
    @param option: kvm option to fetch the output from
2168 6e043e60 Guido Trotter
    @return: output a supported kvm invocation
2169 e3b89628 Guido Trotter
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
2170 e3b89628 Guido Trotter

2171 e3b89628 Guido Trotter
    """
2172 6e043e60 Guido Trotter
    assert option in cls._KVMOPTS_CMDS, "Invalid output option"
2173 6e043e60 Guido Trotter
2174 bc0fed4b Guido Trotter
    optlist, can_fail = cls._KVMOPTS_CMDS[option]
2175 bc0fed4b Guido Trotter
2176 bc0fed4b Guido Trotter
    result = utils.RunCmd([kvm_path] + optlist)
2177 bc0fed4b Guido Trotter
    if result.failed and not can_fail:
2178 af89fa76 Helga Velroyen
      raise errors.HypervisorError("Unable to get KVM %s output" %
2179 3ddc7650 Jose A. Lopes
                                    " ".join(optlist))
2180 e3b89628 Guido Trotter
    return result.output
2181 e3b89628 Guido Trotter
2182 e3b89628 Guido Trotter
  @classmethod
2183 3b59ec02 Guido Trotter
  def _GetKVMVersion(cls, kvm_path):
2184 d7e4a2b1 Andrea Spadaccini
    """Return the installed KVM version.
2185 b52d85c1 Guido Trotter

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

2189 b52d85c1 Guido Trotter
    """
2190 6e043e60 Guido Trotter
    return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
2191 82e3bf85 Dimitris Aragiorgis
2192 82e3bf85 Dimitris Aragiorgis
  @classmethod
2193 82e3bf85 Dimitris Aragiorgis
  def _GetDefaultMachineVersion(cls, kvm_path):
2194 82e3bf85 Dimitris Aragiorgis
    """Return the default hardware revision (e.g. pc-1.1)
2195 82e3bf85 Dimitris Aragiorgis

2196 82e3bf85 Dimitris Aragiorgis
    """
2197 6e043e60 Guido Trotter
    output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2198 82e3bf85 Dimitris Aragiorgis
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
2199 82e3bf85 Dimitris Aragiorgis
    if match:
2200 82e3bf85 Dimitris Aragiorgis
      return match.group(1)
2201 82e3bf85 Dimitris Aragiorgis
    else:
2202 82e3bf85 Dimitris Aragiorgis
      return "pc"
2203 82e3bf85 Dimitris Aragiorgis
2204 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
2205 eb58f9b1 Guido Trotter
    """Stop an instance.
2206 eb58f9b1 Guido Trotter

2207 eb58f9b1 Guido Trotter
    """
2208 bbcf7ad0 Iustin Pop
    if name is not None and not force:
2209 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
2210 bbcf7ad0 Iustin Pop
    if name is None:
2211 bbcf7ad0 Iustin Pop
      name = instance.name
2212 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
2213 bbcf7ad0 Iustin Pop
    else:
2214 bbcf7ad0 Iustin Pop
      acpi = False
2215 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
2216 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
2217 bbcf7ad0 Iustin Pop
      if force or not acpi:
2218 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
2219 eb58f9b1 Guido Trotter
      else:
2220 d0c8c01d Iustin Pop
        self._CallMonitorCommand(name, "system_powerdown")
2221 eb58f9b1 Guido Trotter
2222 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
2223 8904b35c Guido Trotter
    """Cleanup after a stopped instance
2224 8904b35c Guido Trotter

2225 8904b35c Guido Trotter
    """
2226 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
2227 8904b35c Guido Trotter
    if pid > 0 and alive:
2228 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
2229 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
2230 eb58f9b1 Guido Trotter
2231 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
2232 eb58f9b1 Guido Trotter
    """Reboot an instance.
2233 eb58f9b1 Guido Trotter

2234 eb58f9b1 Guido Trotter
    """
2235 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
2236 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
2237 eb58f9b1 Guido Trotter
    # to shutdown and restart.
2238 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
2239 1f8b3a27 Guido Trotter
    if not alive:
2240 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
2241 78411c60 Iustin Pop
                                   " not running" % instance.name)
2242 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
2243 f02881e0 Guido Trotter
    # ...first load it...
2244 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
2245 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
2246 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
2247 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
2248 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
2249 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
2250 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2251 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2252 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
2253 eb58f9b1 Guido Trotter
2254 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
2255 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
2256 30e42c4e Guido Trotter

2257 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2258 30e42c4e Guido Trotter
    @param instance: instance to be migrated
2259 30e42c4e Guido Trotter
    @rtype: string
2260 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
2261 30e42c4e Guido Trotter

2262 30e42c4e Guido Trotter
    """
2263 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
2264 30e42c4e Guido Trotter
2265 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
2266 30e42c4e Guido Trotter
    """Prepare to accept an instance.
2267 30e42c4e Guido Trotter

2268 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2269 30e42c4e Guido Trotter
    @param instance: instance to be accepted
2270 30e42c4e Guido Trotter
    @type info: string
2271 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
2272 30e42c4e Guido Trotter
    @type target: string
2273 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
2274 30e42c4e Guido Trotter

2275 30e42c4e Guido Trotter
    """
2276 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2277 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
2278 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2279 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2280 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
2281 b73f1c59 Guido Trotter
                            incoming=incoming_address)
2282 30e42c4e Guido Trotter
2283 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
2284 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
2285 30e42c4e Guido Trotter

2286 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
2287 30e42c4e Guido Trotter

2288 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2289 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
2290 30e42c4e Guido Trotter

2291 30e42c4e Guido Trotter
    """
2292 30e42c4e Guido Trotter
    if success:
2293 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2294 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
2295 5d9bfd87 Apollon Oikonomopoulos
2296 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
2297 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
2298 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
2299 cc8a8ed7 Apollon Oikonomopoulos
          continue
2300 5d9bfd87 Apollon Oikonomopoulos
        try:
2301 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
2302 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
2303 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
2304 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
2305 5d9bfd87 Apollon Oikonomopoulos
          continue
2306 5d9bfd87 Apollon Oikonomopoulos
        try:
2307 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
2308 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
2309 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
2310 5d9bfd87 Apollon Oikonomopoulos
2311 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
2312 30e42c4e Guido Trotter
    else:
2313 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
2314 30e42c4e Guido Trotter
2315 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
2316 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
2317 30e42c4e Guido Trotter

2318 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
2319 30e42c4e Guido Trotter
    currently running.
2320 30e42c4e Guido Trotter

2321 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
2322 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
2323 30e42c4e Guido Trotter
    @type target: string
2324 30e42c4e Guido Trotter
    @param target: ip address of the target node
2325 30e42c4e Guido Trotter
    @type live: boolean
2326 30e42c4e Guido Trotter
    @param live: perform a live migration
2327 30e42c4e Guido Trotter

2328 30e42c4e Guido Trotter
    """
2329 58d38b02 Iustin Pop
    instance_name = instance.name
2330 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
2331 6a1434d7 Andrea Spadaccini
    _, _, alive = self._InstancePidAlive(instance_name)
2332 30e42c4e Guido Trotter
    if not alive:
2333 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
2334 30e42c4e Guido Trotter
2335 30e42c4e Guido Trotter
    if not live:
2336 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
2337 30e42c4e Guido Trotter
2338 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
2339 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
2340 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2341 e43d4f9f Apollon Oikonomopoulos
2342 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
2343 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
2344 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2345 e43d4f9f Apollon Oikonomopoulos
2346 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
2347 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
2348 30e42c4e Guido Trotter
2349 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
2350 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
2351 6a1434d7 Andrea Spadaccini

2352 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2353 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
2354 6a1434d7 Andrea Spadaccini
    @type success: bool
2355 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
2356 6a1434d7 Andrea Spadaccini
    @type live: bool
2357 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
2358 6a1434d7 Andrea Spadaccini

2359 6a1434d7 Andrea Spadaccini
    """
2360 6a1434d7 Andrea Spadaccini
    if success:
2361 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
2362 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
2363 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
2364 6a1434d7 Andrea Spadaccini
    elif live:
2365 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
2366 6a1434d7 Andrea Spadaccini
2367 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
2368 6a1434d7 Andrea Spadaccini
    """Get the migration status
2369 6a1434d7 Andrea Spadaccini

2370 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2371 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
2372 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
2373 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
2374 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
2375 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
2376 6a1434d7 Andrea Spadaccini

2377 6a1434d7 Andrea Spadaccini
    """
2378 d0c8c01d Iustin Pop
    info_command = "info migrate"
2379 6a1434d7 Andrea Spadaccini
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
2380 6a1434d7 Andrea Spadaccini
      result = self._CallMonitorCommand(instance.name, info_command)
2381 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
2382 30e42c4e Guido Trotter
      if not match:
2383 c4e388a5 Guido Trotter
        if not result.stdout:
2384 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
2385 c4e388a5 Guido Trotter
        else:
2386 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
2387 c4e388a5 Guido Trotter
                          result.stdout)
2388 30e42c4e Guido Trotter
      else:
2389 30e42c4e Guido Trotter
        status = match.group(1)
2390 6a1434d7 Andrea Spadaccini
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
2391 6a1434d7 Andrea Spadaccini
          migration_status = objects.MigrationStatus(status=status)
2392 61643226 Andrea Spadaccini
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
2393 61643226 Andrea Spadaccini
          if match:
2394 61643226 Andrea Spadaccini
            migration_status.transferred_ram = match.group("transferred")
2395 61643226 Andrea Spadaccini
            migration_status.total_ram = match.group("total")
2396 61643226 Andrea Spadaccini
2397 6a1434d7 Andrea Spadaccini
          return migration_status
2398 30e42c4e Guido Trotter
2399 6a1434d7 Andrea Spadaccini
        logging.warning("KVM: unknown migration status '%s'", status)
2400 6a1434d7 Andrea Spadaccini
2401 6a1434d7 Andrea Spadaccini
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
2402 6a1434d7 Andrea Spadaccini
2403 62457f51 Iustin Pop
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
2404 30e42c4e Guido Trotter
2405 3d836750 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
2406 3d836750 Guido Trotter
    """Balloon an instance memory to a certain value.
2407 3d836750 Guido Trotter

2408 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
2409 3d836750 Guido Trotter
    @param instance: instance to be accepted
2410 3d836750 Guido Trotter
    @type mem: int
2411 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
2412 3d836750 Guido Trotter

2413 3d836750 Guido Trotter
    """
2414 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2415 3d836750 Guido Trotter
2416 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
2417 eb58f9b1 Guido Trotter
    """Return information about the node.
2418 eb58f9b1 Guido Trotter

2419 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
2420 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
2421 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
2422 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
2423 34fbc862 Andrea Spadaccini
          - hv_version: the hypervisor version in the form (major, minor,
2424 34fbc862 Andrea Spadaccini
                        revision)
2425 eb58f9b1 Guido Trotter

2426 eb58f9b1 Guido Trotter
    """
2427 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
2428 4b9638dc Guido Trotter
    # FIXME: this is the global kvm version, but the actual version can be
2429 4b9638dc Guido Trotter
    # customized as an hv parameter. we should use the nodegroup's default kvm
2430 4b9638dc Guido Trotter
    # path parameter here.
2431 3b59ec02 Guido Trotter
    _, v_major, v_min, v_rev = self._GetKVMVersion(constants.KVM_PATH)
2432 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2433 34fbc862 Andrea Spadaccini
    return result
2434 eb58f9b1 Guido Trotter
2435 637ce7f9 Guido Trotter
  @classmethod
2436 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
2437 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
2438 eb58f9b1 Guido Trotter

2439 eb58f9b1 Guido Trotter
    """
2440 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2441 9d9bded1 Michael Hanselmann
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2442 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2443 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2444 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
2445 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2446 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2447 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
2448 55cc0a44 Michael Hanselmann
                                     host=instance.primary_node,
2449 052783ff Michael Hanselmann
                                     user=constants.SSH_CONSOLE_USER,
2450 55cc0a44 Michael Hanselmann
                                     command=cmd)
2451 3be34f57 Guido Trotter
2452 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2453 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2454 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
2455 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2456 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
2457 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
2458 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
2459 55cc0a44 Michael Hanselmann
                                     display=display)
2460 55cc0a44 Michael Hanselmann
2461 4d2cdb5a Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2462 4d2cdb5a Andrea Spadaccini
    if spice_bind:
2463 4d2cdb5a Andrea Spadaccini
      return objects.InstanceConsole(instance=instance.name,
2464 4d2cdb5a Andrea Spadaccini
                                     kind=constants.CONS_SPICE,
2465 4d2cdb5a Andrea Spadaccini
                                     host=spice_bind,
2466 4d2cdb5a Andrea Spadaccini
                                     port=instance.network_port)
2467 4d2cdb5a Andrea Spadaccini
2468 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
2469 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
2470 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
2471 55cc0a44 Michael Hanselmann
                                            instance.name))
2472 eb58f9b1 Guido Trotter
2473 eb58f9b1 Guido Trotter
  def Verify(self):
2474 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
2475 eb58f9b1 Guido Trotter

2476 cd04dfd2 Michael Hanselmann
    Check that the required binaries exist.
2477 cd04dfd2 Michael Hanselmann

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

2480 eb58f9b1 Guido Trotter
    """
2481 1f4b9d39 Iustin Pop
    msgs = []
2482 1f4b9d39 Iustin Pop
    # FIXME: this is the global kvm binary, but the actual path can be
2483 1f4b9d39 Iustin Pop
    # customized as an hv parameter; we should use the nodegroup's
2484 1f4b9d39 Iustin Pop
    # default kvm path parameter here.
2485 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
2486 1f4b9d39 Iustin Pop
      msgs.append("The KVM binary ('%s') does not exist" % constants.KVM_PATH)
2487 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2488 1f4b9d39 Iustin Pop
      msgs.append("The socat binary ('%s') does not exist" %
2489 1f4b9d39 Iustin Pop
                  constants.SOCAT_PATH)
2490 1f4b9d39 Iustin Pop
2491 1f4b9d39 Iustin Pop
    return self._FormatVerifyResults(msgs)
2492 14aa53cb Guido Trotter
2493 6b5605e8 Iustin Pop
  @classmethod
2494 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2495 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2496 6b5605e8 Iustin Pop

2497 6b5605e8 Iustin Pop
    @type hvparams:  dict
2498 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2499 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2500 6b5605e8 Iustin Pop

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

2570 d19d94db Guido Trotter
    @type hvparams:  dict
2571 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2572 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2573 d19d94db Guido Trotter

2574 d19d94db Guido Trotter
    """
2575 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2576 d19d94db Guido Trotter
2577 82e3bf85 Dimitris Aragiorgis
    kvm_path = hvparams[constants.HV_KVM_PATH]
2578 82e3bf85 Dimitris Aragiorgis
2579 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2580 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2581 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2582 d19d94db Guido Trotter
      try:
2583 1feb39ec Guido Trotter
        pwd.getpwnam(username)
2584 d19d94db Guido Trotter
      except KeyError:
2585 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
2586 d19d94db Guido Trotter
                                     % username)
2587 d19d94db Guido Trotter
2588 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2589 b1cb62bd Andrea Spadaccini
    if spice_bind:
2590 b1cb62bd Andrea Spadaccini
      # only one of VNC and SPICE can be used currently.
2591 b1cb62bd Andrea Spadaccini
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2592 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("Both SPICE and VNC are configured, but"
2593 b1cb62bd Andrea Spadaccini
                                     " only one of them can be used at a"
2594 afa9bb2e Michael Hanselmann
                                     " given time")
2595 b1cb62bd Andrea Spadaccini
2596 3b59ec02 Guido Trotter
      # check that KVM supports SPICE
2597 6e043e60 Guido Trotter
      kvmhelp = cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP)
2598 0ad7f5d8 Guido Trotter
      if not cls._SPICE_RE.search(kvmhelp):
2599 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE is configured, but it is not"
2600 afa9bb2e Michael Hanselmann
                                     " supported according to 'kvm --help'")
2601 b1cb62bd Andrea Spadaccini
2602 b1cb62bd Andrea Spadaccini
      # if spice_bind is not an IP address, it must be a valid interface
2603 afa9bb2e Michael Hanselmann
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind) or
2604 afa9bb2e Michael Hanselmann
                       netutils.IP6Address.IsValid(spice_bind))
2605 b1cb62bd Andrea Spadaccini
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2606 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE: The %s parameter must be either"
2607 b1cb62bd Andrea Spadaccini
                                     " a valid IP address or interface name" %
2608 b1cb62bd Andrea Spadaccini
                                     constants.HV_KVM_SPICE_BIND)
2609 b1cb62bd Andrea Spadaccini
2610 82e3bf85 Dimitris Aragiorgis
    machine_version = hvparams[constants.HV_KVM_MACHINE_VERSION]
2611 82e3bf85 Dimitris Aragiorgis
    if machine_version:
2612 6e043e60 Guido Trotter
      output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2613 82e3bf85 Dimitris Aragiorgis
      if not cls._CHECK_MACHINE_VERSION_RE(machine_version).search(output):
2614 82e3bf85 Dimitris Aragiorgis
        raise errors.HypervisorError("Unsupported machine version: %s" %
2615 82e3bf85 Dimitris Aragiorgis
                                     machine_version)
2616 82e3bf85 Dimitris Aragiorgis
2617 f5118ade Iustin Pop
  @classmethod
2618 f5118ade Iustin Pop
  def PowercycleNode(cls):
2619 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
2620 f5118ade Iustin Pop

2621 f5118ade Iustin Pop
    """
2622 f5118ade Iustin Pop
    cls.LinuxPowercycle()