Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ dbbf9700

History | View | Annotate | Download (96.6 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 f44c88c7 Dimitris Aragiorgis
def _GenerateDeviceKVMId(dev_type, dev, idx=None):
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 f44c88c7 Dimitris Aragiorgis
  # proper device id - available in latest Ganeti versions
134 f44c88c7 Dimitris Aragiorgis
  if dev.pci and dev.uuid:
135 f44c88c7 Dimitris Aragiorgis
    return "%s-%s-pci-%d" % (dev_type.lower(), dev.uuid.split("-")[0], dev.pci)
136 8b7be6f2 Dimitris Aragiorgis
137 f44c88c7 Dimitris Aragiorgis
  # dummy device id - returned only to _GenerateKVMBlockDevicesOptions
138 f44c88c7 Dimitris Aragiorgis
  # This enables -device option for paravirtual disk_type
139 f44c88c7 Dimitris Aragiorgis
  if idx is not None:
140 f44c88c7 Dimitris Aragiorgis
    return "%s-%d" % (dev_type.lower(), idx)
141 f44c88c7 Dimitris Aragiorgis
142 f44c88c7 Dimitris Aragiorgis
  raise errors.HotplugError("Hotplug is not supported for devices"
143 f44c88c7 Dimitris Aragiorgis
                            " without UUID or PCI info")
144 8b7be6f2 Dimitris Aragiorgis
145 8b7be6f2 Dimitris Aragiorgis
146 8b7be6f2 Dimitris Aragiorgis
def _UpdatePCISlots(dev, pci_reservations):
147 8b7be6f2 Dimitris Aragiorgis
  """Update pci configuration for a stopped instance
148 8b7be6f2 Dimitris Aragiorgis

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

153 8b7be6f2 Dimitris Aragiorgis
  @type dev: L{objects.Disk} or L{objects.NIC}
154 8b7be6f2 Dimitris Aragiorgis
  @param dev: the device object for which we update its pci slot
155 8b7be6f2 Dimitris Aragiorgis
  @type pci_reservations: bitarray
156 8b7be6f2 Dimitris Aragiorgis
  @param pci_reservations: existing pci reservations for an instance
157 8b7be6f2 Dimitris Aragiorgis
  @raise errors.HotplugError: in case an instance has all its slot occupied
158 8b7be6f2 Dimitris Aragiorgis

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

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

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

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

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

204 58502c9e Dimitris Aragiorgis
  @type serialized_runtime: string
205 58502c9e Dimitris Aragiorgis
  @param serialized_runtime: raw text data read from actual runtime file
206 e2800fca Dimitris Aragiorgis
  @return: (cmd, nic dicts, hvparams, bdev dicts)
207 e2800fca Dimitris Aragiorgis
  @rtype: tuple
208 58502c9e Dimitris Aragiorgis

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

228 e2800fca Dimitris Aragiorgis
  @type serialized_runtime: string
229 e2800fca Dimitris Aragiorgis
  @param serialized_runtime: raw text data read from actual runtime file
230 e2800fca Dimitris Aragiorgis
  @return: (cmd, nics, hvparams, bdevs)
231 e2800fca Dimitris Aragiorgis
  @rtype: tuple
232 e2800fca Dimitris Aragiorgis

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

246 ea2bcb82 Michael Hanselmann
  @see: L{_ProbeTapVnetHdr}
247 ea2bcb82 Michael Hanselmann

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

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

273 199b2053 Apollon Oikonomopoulos
   @type fd: int
274 199b2053 Apollon Oikonomopoulos
   @param fd: the file descriptor of /dev/net/tun
275 199b2053 Apollon Oikonomopoulos

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

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

297 199b2053 Apollon Oikonomopoulos
  @type vnet_hdr: boolean
298 199b2053 Apollon Oikonomopoulos
  @param vnet_hdr: Enable the VNET Header
299 199b2053 Apollon Oikonomopoulos
  @return: (ifname, tapfd)
300 199b2053 Apollon Oikonomopoulos
  @rtype: tuple
301 199b2053 Apollon Oikonomopoulos

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

330 91c10532 Andrea Spadaccini
  """
331 91c10532 Andrea Spadaccini
  def __init__(self, data):
332 91c10532 Andrea Spadaccini
    """Creates a new QMP message based on the passed data.
333 91c10532 Andrea Spadaccini

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

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

348 91c10532 Andrea Spadaccini
    """
349 9b87c2cf Michael Hanselmann
    return self.data.get(field_name, None)
350 91c10532 Andrea Spadaccini
351 91c10532 Andrea Spadaccini
  def __setitem__(self, field_name, field_value):
352 91c10532 Andrea Spadaccini
    """Set the value of the required field_name to field_value.
353 91c10532 Andrea Spadaccini

354 91c10532 Andrea Spadaccini
    """
355 91c10532 Andrea Spadaccini
    self.data[field_name] = field_value
356 91c10532 Andrea Spadaccini
357 91c10532 Andrea Spadaccini
  @staticmethod
358 91c10532 Andrea Spadaccini
  def BuildFromJsonString(json_string):
359 91c10532 Andrea Spadaccini
    """Build a QmpMessage from a JSON encoded string.
360 91c10532 Andrea Spadaccini

361 91c10532 Andrea Spadaccini
    @type json_string: str
362 91c10532 Andrea Spadaccini
    @param json_string: JSON string representing the message
363 91c10532 Andrea Spadaccini
    @rtype: L{QmpMessage}
364 91c10532 Andrea Spadaccini
    @return: a L{QmpMessage} built from json_string
365 91c10532 Andrea Spadaccini

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

387 91c10532 Andrea Spadaccini
    @type monitor_filename: string
388 91c10532 Andrea Spadaccini
    @param monitor_filename: the filename of the UNIX raw socket on which the
389 172a75dc Dimitris Aragiorgis
                             monitor (QMP or simple one) is listening
390 91c10532 Andrea Spadaccini

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

415 91c10532 Andrea Spadaccini
    """
416 91c10532 Andrea Spadaccini
    if not self._connected:
417 172a75dc Dimitris Aragiorgis
      raise errors.ProgrammerError("To use a MonitorSocket you need to first"
418 91c10532 Andrea Spadaccini
                                   " invoke connect() on it")
419 91c10532 Andrea Spadaccini
420 91c10532 Andrea Spadaccini
  def connect(self):
421 172a75dc Dimitris Aragiorgis
    """Connects to the monitor.
422 91c10532 Andrea Spadaccini

423 172a75dc Dimitris Aragiorgis
    Connects to the UNIX socket
424 91c10532 Andrea Spadaccini

425 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
426 91c10532 Andrea Spadaccini

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

443 172a75dc Dimitris Aragiorgis
    It cannot be used after this call.
444 172a75dc Dimitris Aragiorgis

445 172a75dc Dimitris Aragiorgis
    """
446 172a75dc Dimitris Aragiorgis
    self.sock.close()
447 172a75dc Dimitris Aragiorgis
448 172a75dc Dimitris Aragiorgis
449 172a75dc Dimitris Aragiorgis
class QmpConnection(MonitorSocket):
450 172a75dc Dimitris Aragiorgis
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
451 172a75dc Dimitris Aragiorgis

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

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

475 172a75dc Dimitris Aragiorgis
    @raise errors.HypervisorError: when there are communication errors
476 172a75dc Dimitris Aragiorgis
    @raise errors.ProgrammerError: when there are data serialization errors
477 172a75dc Dimitris Aragiorgis

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

496 91c10532 Andrea Spadaccini
    Seeks for a QMP message in the given buf. If found, it parses it and
497 91c10532 Andrea Spadaccini
    returns it together with the rest of the characters in the buf.
498 91c10532 Andrea Spadaccini
    If no message is found, returns None and the whole buffer.
499 91c10532 Andrea Spadaccini

500 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
501 91c10532 Andrea Spadaccini

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

519 91c10532 Andrea Spadaccini
    @rtype: QmpMessage
520 91c10532 Andrea Spadaccini
    @return: the received message
521 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
522 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
523 91c10532 Andrea Spadaccini

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

557 91c10532 Andrea Spadaccini
    @type message: QmpMessage
558 91c10532 Andrea Spadaccini
    @param message: message to send to KVM
559 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
560 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
561 91c10532 Andrea Spadaccini

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

581 91c10532 Andrea Spadaccini
    @type command: str
582 91c10532 Andrea Spadaccini
    @param command: the command to execute
583 91c10532 Andrea Spadaccini
    @type arguments: dict
584 91c10532 Andrea Spadaccini
    @param arguments: dictionary of arguments to be passed to the command
585 91c10532 Andrea Spadaccini
    @rtype: dict
586 91c10532 Andrea Spadaccini
    @return: dictionary representing the received JSON object
587 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
588 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
589 91c10532 Andrea Spadaccini

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

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

800 98ec75d6 Iustin Pop
    """
801 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
802 98ec75d6 Iustin Pop
803 263b8de6 Guido Trotter
  @classmethod
804 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
805 7548396c Guido Trotter
    """Returns the instance uidfile.
806 7548396c Guido Trotter

807 7548396c Guido Trotter
    """
808 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
809 7548396c Guido Trotter
810 7548396c Guido Trotter
  @classmethod
811 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
812 263b8de6 Guido Trotter
    """Check pid file for instance information.
813 263b8de6 Guido Trotter

814 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
815 263b8de6 Guido Trotter
    information from its command line.
816 263b8de6 Guido Trotter

817 263b8de6 Guido Trotter
    @type pid: string or int
818 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
819 263b8de6 Guido Trotter
    @rtype: tuple
820 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
821 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
822 263b8de6 Guido Trotter

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

858 263b8de6 Guido Trotter
    @type instance_name: string
859 263b8de6 Guido Trotter
    @param instance_name: instance name
860 263b8de6 Guido Trotter
    @rtype: tuple
861 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
862 1f8b3a27 Guido Trotter

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

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

889 c4fbefc8 Guido Trotter
    """
890 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
891 c4fbefc8 Guido Trotter
892 0df4d98a Guido Trotter
  @classmethod
893 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
894 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
895 c4fbefc8 Guido Trotter

896 c4fbefc8 Guido Trotter
    """
897 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
898 c4fbefc8 Guido Trotter
899 91c10532 Andrea Spadaccini
  @classmethod
900 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
901 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
902 91c10532 Andrea Spadaccini

903 91c10532 Andrea Spadaccini
    """
904 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
905 91c10532 Andrea Spadaccini
906 86d6bc2a Guido Trotter
  @staticmethod
907 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
908 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
909 86d6bc2a Guido Trotter

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

912 86d6bc2a Guido Trotter
    """
913 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
914 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
915 86d6bc2a Guido Trotter
    else:
916 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
917 86d6bc2a Guido Trotter
918 0df4d98a Guido Trotter
  @classmethod
919 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
920 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
921 38e250ba Guido Trotter

922 38e250ba Guido Trotter
    """
923 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
924 38e250ba Guido Trotter
925 7e66c35b Guido Trotter
  @classmethod
926 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
927 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
928 547a63b7 Balazs Lecz

929 547a63b7 Balazs Lecz
    """
930 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
931 547a63b7 Balazs Lecz
932 547a63b7 Balazs Lecz
  @classmethod
933 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
934 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
935 5d9bfd87 Apollon Oikonomopoulos
    given instance.
936 5d9bfd87 Apollon Oikonomopoulos

937 5d9bfd87 Apollon Oikonomopoulos
    """
938 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
939 5d9bfd87 Apollon Oikonomopoulos
940 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
941 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
942 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
943 5d9bfd87 Apollon Oikonomopoulos

944 5d9bfd87 Apollon Oikonomopoulos
    """
945 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
946 5d9bfd87 Apollon Oikonomopoulos
947 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
948 4f580fef Sรฉbastien Bocahu
  def _InstanceKeymapFile(cls, instance_name):
949 4f580fef Sรฉbastien Bocahu
    """Returns the name of the file containing the keymap for a given instance
950 4f580fef Sรฉbastien Bocahu

951 4f580fef Sรฉbastien Bocahu
    """
952 4f580fef Sรฉbastien Bocahu
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
953 4f580fef Sรฉbastien Bocahu
954 4f580fef Sรฉbastien Bocahu
  @classmethod
955 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
956 7548396c Guido Trotter
    """Try to read a uid file
957 7548396c Guido Trotter

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

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

1013 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
1014 eb58f9b1 Guido Trotter
    @type instance: instance object
1015 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
1016 eb58f9b1 Guido Trotter
    @type seq: int
1017 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
1018 eb58f9b1 Guido Trotter
    @type nic: nic object
1019 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
1020 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
1021 eb58f9b1 Guido Trotter

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

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

1070 b693125f Tsachy Shacham
    @type cpu_list: list of int
1071 b693125f Tsachy Shacham
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
1072 b693125f Tsachy Shacham
    @rtype: int
1073 b693125f Tsachy Shacham
    @return: a bit mask of CPU affinities
1074 b693125f Tsachy Shacham

1075 b693125f Tsachy Shacham
    """
1076 b693125f Tsachy Shacham
    if cpu_list == constants.CPU_PINNING_OFF:
1077 b693125f Tsachy Shacham
      return constants.CPU_PINNING_ALL_KVM
1078 b693125f Tsachy Shacham
    else:
1079 b693125f Tsachy Shacham
      return sum(2 ** cpu for cpu in cpu_list)
1080 b693125f Tsachy Shacham
1081 b693125f Tsachy Shacham
  @classmethod
1082 b693125f Tsachy Shacham
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
1083 b693125f Tsachy Shacham
    """Change CPU affinity for running VM according to given CPU mask.
1084 b693125f Tsachy Shacham

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

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

1123 b693125f Tsachy Shacham
    @type instance_name: string
1124 b693125f Tsachy Shacham
    @param instance_name: instance in question
1125 b693125f Tsachy Shacham
    @rtype: dictionary of int:int
1126 b693125f Tsachy Shacham
    @return: a dictionary mapping vCPU numbers to thread IDs
1127 b693125f Tsachy Shacham

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

1143 b693125f Tsachy Shacham
    @type instance_name: string
1144 b693125f Tsachy Shacham
    @param instance_name: name of instance
1145 b693125f Tsachy Shacham
    @type cpu_mask: string
1146 b693125f Tsachy Shacham
    @param cpu_mask: CPU pinning mask as entered by user
1147 b693125f Tsachy Shacham

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

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

1162 eb58f9b1 Guido Trotter
    """
1163 eb58f9b1 Guido Trotter
    result = []
1164 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1165 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
1166 eb58f9b1 Guido Trotter
        result.append(name)
1167 eb58f9b1 Guido Trotter
    return result
1168 eb58f9b1 Guido Trotter
1169 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
1170 eb58f9b1 Guido Trotter
    """Get instance properties.
1171 eb58f9b1 Guido Trotter

1172 4fbb3c60 Guido Trotter
    @type instance_name: string
1173 c41eea6e Iustin Pop
    @param instance_name: the instance name
1174 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
1175 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
1176 eb58f9b1 Guido Trotter

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

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

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

1222 e419e42f Dimitris Aragiorgis
    @type instance: L{objects.Instance}
1223 e419e42f Dimitris Aragiorgis
    @param instance: the instance object
1224 4a44d8aa Dimitris Aragiorgis
    @type kvm_disks: list of tuples
1225 4a44d8aa Dimitris Aragiorgis
    @param kvm_disks: list of tuples [(disk, link_name)..]
1226 e419e42f Dimitris Aragiorgis
    @type kvmhelp: string
1227 e419e42f Dimitris Aragiorgis
    @param kvmhelp: output of kvm --help
1228 e419e42f Dimitris Aragiorgis
    @type devlist: string
1229 e419e42f Dimitris Aragiorgis
    @param devlist: output of kvm -device ?
1230 e419e42f Dimitris Aragiorgis
    @rtype: list
1231 e419e42f Dimitris Aragiorgis
    @return: list of command line options eventually used by kvm executable
1232 ece1057c Dimitris Aragiorgis

1233 e419e42f Dimitris Aragiorgis
    """
1234 ece1057c Dimitris Aragiorgis
    hvp = instance.hvparams
1235 e419e42f Dimitris Aragiorgis
    kernel_path = hvp[constants.HV_KERNEL_PATH]
1236 e419e42f Dimitris Aragiorgis
    if kernel_path:
1237 e419e42f Dimitris Aragiorgis
      boot_disk = False
1238 e419e42f Dimitris Aragiorgis
    else:
1239 e419e42f Dimitris Aragiorgis
      boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
1240 ece1057c Dimitris Aragiorgis
1241 ece1057c Dimitris Aragiorgis
    # whether this is an older KVM version that uses the boot=on flag
1242 ece1057c Dimitris Aragiorgis
    # on devices
1243 ece1057c Dimitris Aragiorgis
    needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1244 ece1057c Dimitris Aragiorgis
1245 ece1057c Dimitris Aragiorgis
    dev_opts = []
1246 994ccaf2 Dimitris Aragiorgis
    device_driver = None
1247 ece1057c Dimitris Aragiorgis
    disk_type = hvp[constants.HV_DISK_TYPE]
1248 ece1057c Dimitris Aragiorgis
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
1249 ece1057c Dimitris Aragiorgis
      if_val = ",if=%s" % self._VIRTIO
1250 994ccaf2 Dimitris Aragiorgis
      try:
1251 994ccaf2 Dimitris Aragiorgis
        if self._VIRTIO_BLK_RE.search(devlist):
1252 0288e7bf Dimitris Aragiorgis
          if_val = ",if=none"
1253 994ccaf2 Dimitris Aragiorgis
          # will be passed in -device option as driver
1254 994ccaf2 Dimitris Aragiorgis
          device_driver = self._VIRTIO_BLK_PCI
1255 994ccaf2 Dimitris Aragiorgis
      except errors.HypervisorError, _:
1256 994ccaf2 Dimitris Aragiorgis
        pass
1257 ece1057c Dimitris Aragiorgis
    else:
1258 ece1057c Dimitris Aragiorgis
      if_val = ",if=%s" % disk_type
1259 ece1057c Dimitris Aragiorgis
    # Cache mode
1260 ece1057c Dimitris Aragiorgis
    disk_cache = hvp[constants.HV_DISK_CACHE]
1261 ece1057c Dimitris Aragiorgis
    if instance.disk_template in constants.DTS_EXT_MIRROR:
1262 ece1057c Dimitris Aragiorgis
      if disk_cache != "none":
1263 ece1057c Dimitris Aragiorgis
        # TODO: make this a hard error, instead of a silent overwrite
1264 ece1057c Dimitris Aragiorgis
        logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
1265 ece1057c Dimitris Aragiorgis
                        " to prevent shared storage corruption on migration",
1266 ece1057c Dimitris Aragiorgis
                        disk_cache)
1267 ece1057c Dimitris Aragiorgis
      cache_val = ",cache=none"
1268 ece1057c Dimitris Aragiorgis
    elif disk_cache != constants.HT_CACHE_DEFAULT:
1269 ece1057c Dimitris Aragiorgis
      cache_val = ",cache=%s" % disk_cache
1270 ece1057c Dimitris Aragiorgis
    else:
1271 ece1057c Dimitris Aragiorgis
      cache_val = ""
1272 f44c88c7 Dimitris Aragiorgis
    for idx, (cfdev, link_name) in enumerate(kvm_disks):
1273 ece1057c Dimitris Aragiorgis
      if cfdev.mode != constants.DISK_RDWR:
1274 ece1057c Dimitris Aragiorgis
        raise errors.HypervisorError("Instance has read-only disks which"
1275 ece1057c Dimitris Aragiorgis
                                     " are not supported by KVM")
1276 ece1057c Dimitris Aragiorgis
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
1277 ece1057c Dimitris Aragiorgis
      boot_val = ""
1278 ece1057c Dimitris Aragiorgis
      if boot_disk:
1279 ece1057c Dimitris Aragiorgis
        dev_opts.extend(["-boot", "c"])
1280 ece1057c Dimitris Aragiorgis
        boot_disk = False
1281 ece1057c Dimitris Aragiorgis
        if needs_boot_flag and disk_type != constants.HT_DISK_IDE:
1282 ece1057c Dimitris Aragiorgis
          boot_val = ",boot=on"
1283 566853c4 Dimitris Aragiorgis
1284 566853c4 Dimitris Aragiorgis
      # For ext we allow overriding disk_cache hypervisor params per disk
1285 566853c4 Dimitris Aragiorgis
      disk_cache = cfdev.params.get("cache", None)
1286 566853c4 Dimitris Aragiorgis
      if disk_cache:
1287 566853c4 Dimitris Aragiorgis
        cache_val = ",cache=%s" % disk_cache
1288 ece1057c Dimitris Aragiorgis
      drive_val = "file=%s,format=raw%s%s%s" % \
1289 f44c88c7 Dimitris Aragiorgis
                  (link_name, if_val, boot_val, cache_val)
1290 ece1057c Dimitris Aragiorgis
1291 994ccaf2 Dimitris Aragiorgis
      if device_driver:
1292 4a44d8aa Dimitris Aragiorgis
        # kvm_disks are the 4th entry of runtime file that did not exist in
1293 0288e7bf Dimitris Aragiorgis
        # the past. That means that cfdev should always have pci slot and
1294 0288e7bf Dimitris Aragiorgis
        # _GenerateDeviceKVMId() will not raise a exception.
1295 f44c88c7 Dimitris Aragiorgis
        kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_DISK,
1296 f44c88c7 Dimitris Aragiorgis
                                         cfdev, idx)
1297 0288e7bf Dimitris Aragiorgis
        drive_val += (",id=%s" % kvm_devid)
1298 f44c88c7 Dimitris Aragiorgis
        if cfdev.pci:
1299 f44c88c7 Dimitris Aragiorgis
          drive_val += (",bus=0,unit=%d" % cfdev.pci)
1300 0288e7bf Dimitris Aragiorgis
        dev_val = ("%s,drive=%s,id=%s" %
1301 0288e7bf Dimitris Aragiorgis
                   (device_driver, kvm_devid, kvm_devid))
1302 f44c88c7 Dimitris Aragiorgis
        if cfdev.pci:
1303 f44c88c7 Dimitris Aragiorgis
          dev_val += ",bus=pci.0,addr=%s" % hex(cfdev.pci)
1304 0288e7bf Dimitris Aragiorgis
        dev_opts.extend(["-device", dev_val])
1305 0288e7bf Dimitris Aragiorgis
1306 9209d947 Dimitris Aragiorgis
      # TODO: export disk geometry in IDISK_PARAMS
1307 9209d947 Dimitris Aragiorgis
      heads = cfdev.params.get('heads', None)
1308 9209d947 Dimitris Aragiorgis
      secs = cfdev.params.get('secs', None)
1309 9209d947 Dimitris Aragiorgis
      if heads and secs:
1310 9209d947 Dimitris Aragiorgis
        nr_sectors = cfdev.size * 1024 * 1024 / 512
1311 9209d947 Dimitris Aragiorgis
        cyls = nr_sectors / (int(heads) * int(secs))
1312 9209d947 Dimitris Aragiorgis
        if cyls > 16383:
1313 9209d947 Dimitris Aragiorgis
          cyls = 16383
1314 9209d947 Dimitris Aragiorgis
        elif cyls < 2:
1315 9209d947 Dimitris Aragiorgis
          cyls = 2
1316 9209d947 Dimitris Aragiorgis
        if cyls and heads and secs:
1317 9209d947 Dimitris Aragiorgis
          drive_val += (",cyls=%d,heads=%d,secs=%d" %
1318 9209d947 Dimitris Aragiorgis
                        (cyls, int(heads), int(secs)))
1319 9209d947 Dimitris Aragiorgis
1320 ece1057c Dimitris Aragiorgis
      dev_opts.extend(["-drive", drive_val])
1321 ece1057c Dimitris Aragiorgis
1322 ece1057c Dimitris Aragiorgis
    return dev_opts
1323 ece1057c Dimitris Aragiorgis
1324 b73f1c59 Guido Trotter
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused,
1325 b73f1c59 Guido Trotter
                          kvmhelp):
1326 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
1327 eb58f9b1 Guido Trotter

1328 b73f1c59 Guido Trotter
    @type kvmhelp: string
1329 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1330 839642c2 Iustin Pop
    @attention: this function must not have any side-effects; for
1331 839642c2 Iustin Pop
        example, it must not write to the filesystem, or read values
1332 839642c2 Iustin Pop
        from the current system the are expected to differ between
1333 839642c2 Iustin Pop
        nodes, since it is only run once at instance startup;
1334 839642c2 Iustin Pop
        actions/kvm arguments that can vary between systems should be
1335 839642c2 Iustin Pop
        done in L{_ExecuteKVMRuntime}
1336 839642c2 Iustin Pop

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

1678 38e250ba Guido Trotter
    """
1679 38e250ba Guido Trotter
    try:
1680 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1681 38e250ba Guido Trotter
                      data=data)
1682 90c024f6 Guido Trotter
    except EnvironmentError, err:
1683 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1684 38e250ba Guido Trotter
1685 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
1686 38e250ba Guido Trotter
    """Read an instance's KVM runtime
1687 38e250ba Guido Trotter

1688 38e250ba Guido Trotter
    """
1689 38e250ba Guido Trotter
    try:
1690 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1691 90c024f6 Guido Trotter
    except EnvironmentError, err:
1692 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1693 38e250ba Guido Trotter
    return file_content
1694 38e250ba Guido Trotter
1695 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1696 38e250ba Guido Trotter
    """Save an instance's KVM runtime
1697 38e250ba Guido Trotter

1698 38e250ba Guido Trotter
    """
1699 4a44d8aa Dimitris Aragiorgis
    kvm_cmd, kvm_nics, hvparams, kvm_disks = kvm_runtime
1700 58502c9e Dimitris Aragiorgis
1701 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1702 4a44d8aa Dimitris Aragiorgis
    serialized_disks = [(blk.ToDict(), link)
1703 4a44d8aa Dimitris Aragiorgis
                            for blk, link in kvm_disks]
1704 58502c9e Dimitris Aragiorgis
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams,
1705 4a44d8aa Dimitris Aragiorgis
                                      serialized_disks))
1706 58502c9e Dimitris Aragiorgis
1707 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
1708 38e250ba Guido Trotter
1709 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1710 38e250ba Guido Trotter
    """Load an instance's KVM runtime
1711 38e250ba Guido Trotter

1712 38e250ba Guido Trotter
    """
1713 30e42c4e Guido Trotter
    if not serialized_runtime:
1714 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1715 58502c9e Dimitris Aragiorgis
1716 58502c9e Dimitris Aragiorgis
    return _AnalyzeSerializedRuntime(serialized_runtime)
1717 38e250ba Guido Trotter
1718 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1719 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
1720 76431533 Guido Trotter

1721 76431533 Guido Trotter
    @type name: string
1722 76431533 Guido Trotter
    @param name: instance name
1723 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1724 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1725 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1726 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1727 76431533 Guido Trotter

1728 76431533 Guido Trotter
    """
1729 5d9bfd87 Apollon Oikonomopoulos
    try:
1730 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1731 5d9bfd87 Apollon Oikonomopoulos
    finally:
1732 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
1733 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
1734 5d9bfd87 Apollon Oikonomopoulos
1735 76431533 Guido Trotter
    if result.failed:
1736 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1737 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
1738 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
1739 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
1740 76431533 Guido Trotter
1741 4a44d8aa Dimitris Aragiorgis
  # too many local variables
1742 58502c9e Dimitris Aragiorgis
  # pylint: disable=R0914
1743 b73f1c59 Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1744 839642c2 Iustin Pop
    """Execute a KVM cmd, after completing it with some last minute data.
1745 ee5f20b0 Guido Trotter

1746 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1747 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1748 b73f1c59 Guido Trotter
    @type kvmhelp: string
1749 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1750 30e42c4e Guido Trotter

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

1971 ee5f20b0 Guido Trotter
    """
1972 5905901c Iustin Pop
    self._CheckDown(instance.name)
1973 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1974 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1975 7238edb5 Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1976 b73f1c59 Guido Trotter
                                           startup_paused, kvmhelp)
1977 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1978 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1979 ee5f20b0 Guido Trotter
1980 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
1981 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
1982 6567aff3 Guido Trotter

1983 6567aff3 Guido Trotter
    """
1984 eace6157 Michael Hanselmann
    # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
1985 eace6157 Michael Hanselmann
    # version. The monitor protocol is designed for human consumption, whereas
1986 eace6157 Michael Hanselmann
    # QMP is made for programmatic usage. In the worst case QMP can also
1987 eace6157 Michael Hanselmann
    # execute monitor commands. As it is, all calls to socat take at least
1988 eace6157 Michael Hanselmann
    # 500ms and likely more: socat can't detect the end of the reply and waits
1989 eace6157 Michael Hanselmann
    # for 500ms of no data received before exiting (500 ms is the default for
1990 eace6157 Michael Hanselmann
    # the "-t" parameter).
1991 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1992 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
1993 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
1994 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1995 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
1996 6567aff3 Guido Trotter
    if result.failed:
1997 afa9bb2e Michael Hanselmann
      msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
1998 afa9bb2e Michael Hanselmann
             " output: %s" %
1999 afa9bb2e Michael Hanselmann
             (command, instance_name, result.fail_reason, result.output))
2000 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
2001 6567aff3 Guido Trotter
2002 6567aff3 Guido Trotter
    return result
2003 6567aff3 Guido Trotter
2004 8b7be6f2 Dimitris Aragiorgis
  def _GetFreePCISlot(self, instance, dev):
2005 8b7be6f2 Dimitris Aragiorgis
    """Get the first available pci slot of a runnung instance.
2006 8b7be6f2 Dimitris Aragiorgis

2007 8b7be6f2 Dimitris Aragiorgis
    """
2008 8b7be6f2 Dimitris Aragiorgis
    slots = bitarray(32)
2009 8b7be6f2 Dimitris Aragiorgis
    slots.setall(False) # pylint: disable=E1101
2010 8b7be6f2 Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance.name, self._INFO_PCI_CMD)
2011 8b7be6f2 Dimitris Aragiorgis
    for line in output.stdout.splitlines():
2012 8b7be6f2 Dimitris Aragiorgis
      match = self._INFO_PCI_RE.search(line)
2013 8b7be6f2 Dimitris Aragiorgis
      if match:
2014 8b7be6f2 Dimitris Aragiorgis
        slot = int(match.group(1))
2015 8b7be6f2 Dimitris Aragiorgis
        slots[slot] = True
2016 8b7be6f2 Dimitris Aragiorgis
2017 8b7be6f2 Dimitris Aragiorgis
    [free] = slots.search(_AVAILABLE_PCI_SLOT, 1) # pylint: disable=E1101
2018 8b7be6f2 Dimitris Aragiorgis
    if not free:
2019 8b7be6f2 Dimitris Aragiorgis
      raise errors.HypervisorError("All PCI slots occupied")
2020 8b7be6f2 Dimitris Aragiorgis
2021 8b7be6f2 Dimitris Aragiorgis
    dev.pci = int(free)
2022 8b7be6f2 Dimitris Aragiorgis
2023 9f395c32 Dimitris Aragiorgis
  def VerifyHotplugSupport(self, instance, action, dev_type):
2024 9f395c32 Dimitris Aragiorgis
    """Verifies that hotplug is supported.
2025 d7583563 Dimitris Aragiorgis

2026 d7583563 Dimitris Aragiorgis
    Hotplug is *not* supported in case of:
2027 d7583563 Dimitris Aragiorgis
     - security models and chroot (disk hotplug)
2028 d7583563 Dimitris Aragiorgis
     - fdsend module is missing (nic hot-add)
2029 d7583563 Dimitris Aragiorgis

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

2032 d7583563 Dimitris Aragiorgis
    """
2033 d7583563 Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2034 d7583563 Dimitris Aragiorgis
      hvp = instance.hvparams
2035 d7583563 Dimitris Aragiorgis
      security_model = hvp[constants.HV_SECURITY_MODEL]
2036 d7583563 Dimitris Aragiorgis
      use_chroot = hvp[constants.HV_KVM_USE_CHROOT]
2037 d7583563 Dimitris Aragiorgis
      if use_chroot:
2038 d7583563 Dimitris Aragiorgis
        raise errors.HotplugError("Disk hotplug is not supported"
2039 d7583563 Dimitris Aragiorgis
                                  " in case of chroot.")
2040 d7583563 Dimitris Aragiorgis
      if security_model != constants.HT_SM_NONE:
2041 d7583563 Dimitris Aragiorgis
        raise errors.HotplugError("Disk Hotplug is not supported in case"
2042 d7583563 Dimitris Aragiorgis
                                  " security models are used.")
2043 d7583563 Dimitris Aragiorgis
2044 d7583563 Dimitris Aragiorgis
    if (dev_type == constants.HOTPLUG_TARGET_NIC and
2045 d7583563 Dimitris Aragiorgis
        action == constants.HOTPLUG_ACTION_ADD and not fdsend):
2046 d7583563 Dimitris Aragiorgis
      raise errors.HotplugError("Cannot hot-add NIC."
2047 d7583563 Dimitris Aragiorgis
                                " fdsend python module is missing.")
2048 d7583563 Dimitris Aragiorgis
2049 caf74756 Dimitris Aragiorgis
  def HotplugSupported(self, instance):
2050 caf74756 Dimitris Aragiorgis
    """Checks if hotplug is generally supported.
2051 caf74756 Dimitris Aragiorgis

2052 caf74756 Dimitris Aragiorgis
    Hotplug is *not* supported in case of:
2053 caf74756 Dimitris Aragiorgis
     - qemu versions < 1.0
2054 caf74756 Dimitris Aragiorgis
     - for stopped instances
2055 caf74756 Dimitris Aragiorgis

2056 caf74756 Dimitris Aragiorgis
    @raise errors.HypervisorError: in one of the previous cases
2057 caf74756 Dimitris Aragiorgis

2058 caf74756 Dimitris Aragiorgis
    """
2059 e7a77eb8 Dimitris Aragiorgis
    try:
2060 e7a77eb8 Dimitris Aragiorgis
      output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD)
2061 e7a77eb8 Dimitris Aragiorgis
    except errors.HypervisorError:
2062 e7a77eb8 Dimitris Aragiorgis
      raise errors.HotplugError("Instance is probably down")
2063 e7a77eb8 Dimitris Aragiorgis
2064 caf74756 Dimitris Aragiorgis
    # TODO: search for netdev_add, drive_add, device_add.....
2065 caf74756 Dimitris Aragiorgis
    match = self._INFO_VERSION_RE.search(output.stdout)
2066 caf74756 Dimitris Aragiorgis
    if not match:
2067 e7a77eb8 Dimitris Aragiorgis
      raise errors.HotplugError("Cannot parse qemu version via monitor")
2068 e7a77eb8 Dimitris Aragiorgis
2069 caf74756 Dimitris Aragiorgis
    v_major, v_min, _, _ = match.groups()
2070 caf74756 Dimitris Aragiorgis
    if (int(v_major), int(v_min)) < (1, 0):
2071 caf74756 Dimitris Aragiorgis
      raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0")
2072 caf74756 Dimitris Aragiorgis
2073 d7583563 Dimitris Aragiorgis
  def _CallHotplugCommand(self, name, cmd):
2074 d7583563 Dimitris Aragiorgis
    output = self._CallMonitorCommand(name, cmd)
2075 d7583563 Dimitris Aragiorgis
    # TODO: parse output and check if succeeded
2076 d7583563 Dimitris Aragiorgis
    for line in output.stdout.splitlines():
2077 d7583563 Dimitris Aragiorgis
      logging.info("%s", line)
2078 d7583563 Dimitris Aragiorgis
2079 af2f716d Dimitris Aragiorgis
  def HotAddDevice(self, instance, dev_type, device, extra, seq):
2080 af2f716d Dimitris Aragiorgis
    """ Helper method to hot-add a new device
2081 af2f716d Dimitris Aragiorgis

2082 af2f716d Dimitris Aragiorgis
    It gets free pci slot generates the device name and invokes the
2083 af2f716d Dimitris Aragiorgis
    device specific method.
2084 af2f716d Dimitris Aragiorgis

2085 af2f716d Dimitris Aragiorgis
    """
2086 af2f716d Dimitris Aragiorgis
    # in case of hot-mod this is given
2087 af2f716d Dimitris Aragiorgis
    if device.pci is None:
2088 af2f716d Dimitris Aragiorgis
      self._GetFreePCISlot(instance, device)
2089 af2f716d Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, device)
2090 af2f716d Dimitris Aragiorgis
    runtime = self._LoadKVMRuntime(instance)
2091 af2f716d Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2092 af2f716d Dimitris Aragiorgis
      command = "drive_add dummy file=%s,if=none,id=%s,format=raw\n" % \
2093 af2f716d Dimitris Aragiorgis
                 (extra, kvm_devid)
2094 af2f716d Dimitris Aragiorgis
      command += ("device_add virtio-blk-pci,bus=pci.0,addr=%s,drive=%s,id=%s" %
2095 af2f716d Dimitris Aragiorgis
                  (hex(device.pci), kvm_devid, kvm_devid))
2096 af2f716d Dimitris Aragiorgis
    elif dev_type == constants.HOTPLUG_TARGET_NIC:
2097 af2f716d Dimitris Aragiorgis
      (tap, fd) = _OpenTap()
2098 af2f716d Dimitris Aragiorgis
      self._ConfigureNIC(instance, seq, device, tap)
2099 af2f716d Dimitris Aragiorgis
      self._PassTapFd(instance, fd, device)
2100 af2f716d Dimitris Aragiorgis
      command = "netdev_add tap,id=%s,fd=%s\n" % (kvm_devid, kvm_devid)
2101 af2f716d Dimitris Aragiorgis
      args = "virtio-net-pci,bus=pci.0,addr=%s,mac=%s,netdev=%s,id=%s" % \
2102 af2f716d Dimitris Aragiorgis
               (hex(device.pci), device.mac, kvm_devid, kvm_devid)
2103 af2f716d Dimitris Aragiorgis
      command += "device_add %s" % args
2104 af2f716d Dimitris Aragiorgis
      utils.WriteFile(self._InstanceNICFile(instance.name, seq), data=tap)
2105 af2f716d Dimitris Aragiorgis
2106 af2f716d Dimitris Aragiorgis
    self._CallHotplugCommand(instance.name, command)
2107 af2f716d Dimitris Aragiorgis
    # update relevant entries in runtime file
2108 af2f716d Dimitris Aragiorgis
    index = _DEVICE_RUNTIME_INDEX[dev_type]
2109 af2f716d Dimitris Aragiorgis
    entry = _RUNTIME_ENTRY[dev_type](device, extra)
2110 af2f716d Dimitris Aragiorgis
    runtime[index].append(entry)
2111 af2f716d Dimitris Aragiorgis
    self._SaveKVMRuntime(instance, runtime)
2112 af2f716d Dimitris Aragiorgis
2113 af2f716d Dimitris Aragiorgis
  def HotDelDevice(self, instance, dev_type, device, _, seq):
2114 af2f716d Dimitris Aragiorgis
    """ Helper method for hot-del device
2115 af2f716d Dimitris Aragiorgis

2116 af2f716d Dimitris Aragiorgis
    It gets device info from runtime file, generates the device name and
2117 af2f716d Dimitris Aragiorgis
    invokes the device specific method.
2118 af2f716d Dimitris Aragiorgis

2119 af2f716d Dimitris Aragiorgis
    """
2120 af2f716d Dimitris Aragiorgis
    runtime = self._LoadKVMRuntime(instance)
2121 af2f716d Dimitris Aragiorgis
    entry = _GetExistingDeviceInfo(dev_type, device, runtime)
2122 af2f716d Dimitris Aragiorgis
    kvm_device = _RUNTIME_DEVICE[dev_type](entry)
2123 af2f716d Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, kvm_device)
2124 af2f716d Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2125 1c6c4d6d Dimitris Aragiorgis
      command = "device_del %s\n" % kvm_devid
2126 1c6c4d6d Dimitris Aragiorgis
      command += "drive_del %s" % kvm_devid
2127 af2f716d Dimitris Aragiorgis
    elif dev_type == constants.HOTPLUG_TARGET_NIC:
2128 af2f716d Dimitris Aragiorgis
      command = "device_del %s\n" % kvm_devid
2129 af2f716d Dimitris Aragiorgis
      command += "netdev_del %s" % kvm_devid
2130 af2f716d Dimitris Aragiorgis
      utils.RemoveFile(self._InstanceNICFile(instance.name, seq))
2131 af2f716d Dimitris Aragiorgis
    self._CallHotplugCommand(instance.name, command)
2132 af2f716d Dimitris Aragiorgis
    index = _DEVICE_RUNTIME_INDEX[dev_type]
2133 af2f716d Dimitris Aragiorgis
    runtime[index].remove(entry)
2134 af2f716d Dimitris Aragiorgis
    self._SaveKVMRuntime(instance, runtime)
2135 af2f716d Dimitris Aragiorgis
2136 af2f716d Dimitris Aragiorgis
    return kvm_device.pci
2137 af2f716d Dimitris Aragiorgis
2138 af2f716d Dimitris Aragiorgis
  def HotModDevice(self, instance, dev_type, device, _, seq):
2139 af2f716d Dimitris Aragiorgis
    """ Helper method for hot-mod device
2140 af2f716d Dimitris Aragiorgis

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

2144 af2f716d Dimitris Aragiorgis
    """
2145 af2f716d Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_NIC:
2146 af2f716d Dimitris Aragiorgis
      # putting it back in the same pci slot
2147 af2f716d Dimitris Aragiorgis
      device.pci = self.HotDelDevice(instance, dev_type, device, _, seq)
2148 af2f716d Dimitris Aragiorgis
      # TODO: remove sleep when socat gets removed
2149 af2f716d Dimitris Aragiorgis
      time.sleep(2)
2150 af2f716d Dimitris Aragiorgis
      self.HotAddDevice(instance, dev_type, device, _, seq)
2151 af2f716d Dimitris Aragiorgis
2152 af2f716d Dimitris Aragiorgis
  def _PassTapFd(self, instance, fd, nic):
2153 af2f716d Dimitris Aragiorgis
    """Pass file descriptor to kvm process via monitor socket using SCM_RIGHTS
2154 af2f716d Dimitris Aragiorgis

2155 af2f716d Dimitris Aragiorgis
    """
2156 af2f716d Dimitris Aragiorgis
    # TODO: factor out code related to unix sockets.
2157 af2f716d Dimitris Aragiorgis
    #       squash common parts between monitor and qmp
2158 af2f716d Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_NIC, nic)
2159 af2f716d Dimitris Aragiorgis
    command = "getfd %s\n" % kvm_devid
2160 af2f716d Dimitris Aragiorgis
    fds = [fd]
2161 af2f716d Dimitris Aragiorgis
    logging.info("%s", fds)
2162 af2f716d Dimitris Aragiorgis
    try:
2163 af2f716d Dimitris Aragiorgis
      monsock = MonitorSocket(self._InstanceMonitor(instance.name))
2164 af2f716d Dimitris Aragiorgis
      monsock.connect()
2165 af2f716d Dimitris Aragiorgis
      fdsend.sendfds(monsock.sock, command, fds=fds)
2166 af2f716d Dimitris Aragiorgis
    finally:
2167 af2f716d Dimitris Aragiorgis
      monsock.close()
2168 af2f716d Dimitris Aragiorgis
2169 b52d85c1 Guido Trotter
  @classmethod
2170 585c8187 Guido Trotter
  def _ParseKVMVersion(cls, text):
2171 585c8187 Guido Trotter
    """Parse the KVM version from the --help output.
2172 585c8187 Guido Trotter

2173 585c8187 Guido Trotter
    @type text: string
2174 585c8187 Guido Trotter
    @param text: output of kvm --help
2175 585c8187 Guido Trotter
    @return: (version, v_maj, v_min, v_rev)
2176 5c3d5dfd Iustin Pop
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
2177 585c8187 Guido Trotter

2178 585c8187 Guido Trotter
    """
2179 585c8187 Guido Trotter
    match = cls._VERSION_RE.search(text.splitlines()[0])
2180 585c8187 Guido Trotter
    if not match:
2181 585c8187 Guido Trotter
      raise errors.HypervisorError("Unable to get KVM version")
2182 585c8187 Guido Trotter
2183 585c8187 Guido Trotter
    v_all = match.group(0)
2184 585c8187 Guido Trotter
    v_maj = int(match.group(1))
2185 585c8187 Guido Trotter
    v_min = int(match.group(2))
2186 585c8187 Guido Trotter
    if match.group(4):
2187 585c8187 Guido Trotter
      v_rev = int(match.group(4))
2188 585c8187 Guido Trotter
    else:
2189 585c8187 Guido Trotter
      v_rev = 0
2190 585c8187 Guido Trotter
    return (v_all, v_maj, v_min, v_rev)
2191 585c8187 Guido Trotter
2192 585c8187 Guido Trotter
  @classmethod
2193 6e043e60 Guido Trotter
  def _GetKVMOutput(cls, kvm_path, option):
2194 6e043e60 Guido Trotter
    """Return the output of a kvm invocation
2195 e3b89628 Guido Trotter

2196 bc0fed4b Guido Trotter
    @type kvm_path: string
2197 bc0fed4b Guido Trotter
    @param kvm_path: path to the kvm executable
2198 bc0fed4b Guido Trotter
    @type option: a key of _KVMOPTS_CMDS
2199 bc0fed4b Guido Trotter
    @param option: kvm option to fetch the output from
2200 6e043e60 Guido Trotter
    @return: output a supported kvm invocation
2201 e3b89628 Guido Trotter
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
2202 e3b89628 Guido Trotter

2203 e3b89628 Guido Trotter
    """
2204 6e043e60 Guido Trotter
    assert option in cls._KVMOPTS_CMDS, "Invalid output option"
2205 6e043e60 Guido Trotter
2206 bc0fed4b Guido Trotter
    optlist, can_fail = cls._KVMOPTS_CMDS[option]
2207 bc0fed4b Guido Trotter
2208 bc0fed4b Guido Trotter
    result = utils.RunCmd([kvm_path] + optlist)
2209 bc0fed4b Guido Trotter
    if result.failed and not can_fail:
2210 af89fa76 Helga Velroyen
      raise errors.HypervisorError("Unable to get KVM %s output" %
2211 3ddc7650 Jose A. Lopes
                                    " ".join(optlist))
2212 e3b89628 Guido Trotter
    return result.output
2213 e3b89628 Guido Trotter
2214 e3b89628 Guido Trotter
  @classmethod
2215 3b59ec02 Guido Trotter
  def _GetKVMVersion(cls, kvm_path):
2216 d7e4a2b1 Andrea Spadaccini
    """Return the installed KVM version.
2217 b52d85c1 Guido Trotter

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

2221 b52d85c1 Guido Trotter
    """
2222 6e043e60 Guido Trotter
    return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
2223 82e3bf85 Dimitris Aragiorgis
2224 82e3bf85 Dimitris Aragiorgis
  @classmethod
2225 82e3bf85 Dimitris Aragiorgis
  def _GetDefaultMachineVersion(cls, kvm_path):
2226 82e3bf85 Dimitris Aragiorgis
    """Return the default hardware revision (e.g. pc-1.1)
2227 82e3bf85 Dimitris Aragiorgis

2228 82e3bf85 Dimitris Aragiorgis
    """
2229 6e043e60 Guido Trotter
    output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2230 82e3bf85 Dimitris Aragiorgis
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
2231 82e3bf85 Dimitris Aragiorgis
    if match:
2232 82e3bf85 Dimitris Aragiorgis
      return match.group(1)
2233 82e3bf85 Dimitris Aragiorgis
    else:
2234 82e3bf85 Dimitris Aragiorgis
      return "pc"
2235 82e3bf85 Dimitris Aragiorgis
2236 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
2237 eb58f9b1 Guido Trotter
    """Stop an instance.
2238 eb58f9b1 Guido Trotter

2239 eb58f9b1 Guido Trotter
    """
2240 bbcf7ad0 Iustin Pop
    if name is not None and not force:
2241 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
2242 bbcf7ad0 Iustin Pop
    if name is None:
2243 bbcf7ad0 Iustin Pop
      name = instance.name
2244 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
2245 bbcf7ad0 Iustin Pop
    else:
2246 bbcf7ad0 Iustin Pop
      acpi = False
2247 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
2248 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
2249 bbcf7ad0 Iustin Pop
      if force or not acpi:
2250 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
2251 eb58f9b1 Guido Trotter
      else:
2252 d0c8c01d Iustin Pop
        self._CallMonitorCommand(name, "system_powerdown")
2253 eb58f9b1 Guido Trotter
2254 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
2255 8904b35c Guido Trotter
    """Cleanup after a stopped instance
2256 8904b35c Guido Trotter

2257 8904b35c Guido Trotter
    """
2258 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
2259 8904b35c Guido Trotter
    if pid > 0 and alive:
2260 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
2261 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
2262 eb58f9b1 Guido Trotter
2263 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
2264 eb58f9b1 Guido Trotter
    """Reboot an instance.
2265 eb58f9b1 Guido Trotter

2266 eb58f9b1 Guido Trotter
    """
2267 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
2268 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
2269 eb58f9b1 Guido Trotter
    # to shutdown and restart.
2270 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
2271 1f8b3a27 Guido Trotter
    if not alive:
2272 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
2273 78411c60 Iustin Pop
                                   " not running" % instance.name)
2274 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
2275 f02881e0 Guido Trotter
    # ...first load it...
2276 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
2277 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
2278 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
2279 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
2280 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
2281 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
2282 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2283 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2284 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
2285 eb58f9b1 Guido Trotter
2286 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
2287 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
2288 30e42c4e Guido Trotter

2289 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2290 30e42c4e Guido Trotter
    @param instance: instance to be migrated
2291 30e42c4e Guido Trotter
    @rtype: string
2292 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
2293 30e42c4e Guido Trotter

2294 30e42c4e Guido Trotter
    """
2295 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
2296 30e42c4e Guido Trotter
2297 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
2298 30e42c4e Guido Trotter
    """Prepare to accept an instance.
2299 30e42c4e Guido Trotter

2300 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2301 30e42c4e Guido Trotter
    @param instance: instance to be accepted
2302 30e42c4e Guido Trotter
    @type info: string
2303 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
2304 30e42c4e Guido Trotter
    @type target: string
2305 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
2306 30e42c4e Guido Trotter

2307 30e42c4e Guido Trotter
    """
2308 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2309 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
2310 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2311 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2312 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
2313 b73f1c59 Guido Trotter
                            incoming=incoming_address)
2314 30e42c4e Guido Trotter
2315 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
2316 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
2317 30e42c4e Guido Trotter

2318 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
2319 30e42c4e Guido Trotter

2320 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2321 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
2322 30e42c4e Guido Trotter

2323 30e42c4e Guido Trotter
    """
2324 30e42c4e Guido Trotter
    if success:
2325 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2326 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
2327 5d9bfd87 Apollon Oikonomopoulos
2328 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
2329 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
2330 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
2331 cc8a8ed7 Apollon Oikonomopoulos
          continue
2332 5d9bfd87 Apollon Oikonomopoulos
        try:
2333 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
2334 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
2335 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
2336 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
2337 5d9bfd87 Apollon Oikonomopoulos
          continue
2338 5d9bfd87 Apollon Oikonomopoulos
        try:
2339 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
2340 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
2341 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
2342 5d9bfd87 Apollon Oikonomopoulos
2343 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
2344 30e42c4e Guido Trotter
    else:
2345 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
2346 30e42c4e Guido Trotter
2347 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
2348 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
2349 30e42c4e Guido Trotter

2350 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
2351 30e42c4e Guido Trotter
    currently running.
2352 30e42c4e Guido Trotter

2353 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
2354 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
2355 30e42c4e Guido Trotter
    @type target: string
2356 30e42c4e Guido Trotter
    @param target: ip address of the target node
2357 30e42c4e Guido Trotter
    @type live: boolean
2358 30e42c4e Guido Trotter
    @param live: perform a live migration
2359 30e42c4e Guido Trotter

2360 30e42c4e Guido Trotter
    """
2361 58d38b02 Iustin Pop
    instance_name = instance.name
2362 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
2363 6a1434d7 Andrea Spadaccini
    _, _, alive = self._InstancePidAlive(instance_name)
2364 30e42c4e Guido Trotter
    if not alive:
2365 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
2366 30e42c4e Guido Trotter
2367 30e42c4e Guido Trotter
    if not live:
2368 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
2369 30e42c4e Guido Trotter
2370 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
2371 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
2372 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2373 e43d4f9f Apollon Oikonomopoulos
2374 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
2375 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
2376 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2377 e43d4f9f Apollon Oikonomopoulos
2378 f14863bc Dimitris Aragiorgis
    # These commands are supported in latest qemu versions.
2379 f14863bc Dimitris Aragiorgis
    # Since _CallMonitorCommand does not catch monitor errors
2380 f14863bc Dimitris Aragiorgis
    # this does not raise an exception in case command is not supported
2381 f14863bc Dimitris Aragiorgis
    # TODO: either parse output of command or see if the command supported
2382 f14863bc Dimitris Aragiorgis
    # via info help (see hotplug)
2383 f14863bc Dimitris Aragiorgis
    migrate_command = ("migrate_set_capability xbzrle on")
2384 f14863bc Dimitris Aragiorgis
    self._CallMonitorCommand(instance_name, migrate_command)
2385 f14863bc Dimitris Aragiorgis
2386 f14863bc Dimitris Aragiorgis
    migrate_command = ("migrate_set_capability auto-converge on")
2387 f14863bc Dimitris Aragiorgis
    self._CallMonitorCommand(instance_name, migrate_command)
2388 f14863bc Dimitris Aragiorgis
2389 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
2390 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
2391 30e42c4e Guido Trotter
2392 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
2393 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
2394 6a1434d7 Andrea Spadaccini

2395 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2396 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
2397 6a1434d7 Andrea Spadaccini
    @type success: bool
2398 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
2399 6a1434d7 Andrea Spadaccini
    @type live: bool
2400 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
2401 6a1434d7 Andrea Spadaccini

2402 6a1434d7 Andrea Spadaccini
    """
2403 6a1434d7 Andrea Spadaccini
    if success:
2404 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
2405 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
2406 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
2407 6a1434d7 Andrea Spadaccini
    elif live:
2408 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
2409 6a1434d7 Andrea Spadaccini
2410 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
2411 6a1434d7 Andrea Spadaccini
    """Get the migration status
2412 6a1434d7 Andrea Spadaccini

2413 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2414 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
2415 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
2416 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
2417 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
2418 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
2419 6a1434d7 Andrea Spadaccini

2420 6a1434d7 Andrea Spadaccini
    """
2421 d0c8c01d Iustin Pop
    info_command = "info migrate"
2422 6a1434d7 Andrea Spadaccini
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
2423 6a1434d7 Andrea Spadaccini
      result = self._CallMonitorCommand(instance.name, info_command)
2424 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
2425 30e42c4e Guido Trotter
      if not match:
2426 c4e388a5 Guido Trotter
        if not result.stdout:
2427 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
2428 c4e388a5 Guido Trotter
        else:
2429 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
2430 c4e388a5 Guido Trotter
                          result.stdout)
2431 30e42c4e Guido Trotter
      else:
2432 30e42c4e Guido Trotter
        status = match.group(1)
2433 6a1434d7 Andrea Spadaccini
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
2434 6a1434d7 Andrea Spadaccini
          migration_status = objects.MigrationStatus(status=status)
2435 61643226 Andrea Spadaccini
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
2436 61643226 Andrea Spadaccini
          if match:
2437 61643226 Andrea Spadaccini
            migration_status.transferred_ram = match.group("transferred")
2438 61643226 Andrea Spadaccini
            migration_status.total_ram = match.group("total")
2439 61643226 Andrea Spadaccini
2440 6a1434d7 Andrea Spadaccini
          return migration_status
2441 30e42c4e Guido Trotter
2442 6a1434d7 Andrea Spadaccini
        logging.warning("KVM: unknown migration status '%s'", status)
2443 6a1434d7 Andrea Spadaccini
2444 6a1434d7 Andrea Spadaccini
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
2445 6a1434d7 Andrea Spadaccini
2446 62457f51 Iustin Pop
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
2447 30e42c4e Guido Trotter
2448 3d836750 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
2449 3d836750 Guido Trotter
    """Balloon an instance memory to a certain value.
2450 3d836750 Guido Trotter

2451 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
2452 3d836750 Guido Trotter
    @param instance: instance to be accepted
2453 3d836750 Guido Trotter
    @type mem: int
2454 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
2455 3d836750 Guido Trotter

2456 3d836750 Guido Trotter
    """
2457 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2458 3d836750 Guido Trotter
2459 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
2460 eb58f9b1 Guido Trotter
    """Return information about the node.
2461 eb58f9b1 Guido Trotter

2462 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
2463 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
2464 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
2465 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
2466 34fbc862 Andrea Spadaccini
          - hv_version: the hypervisor version in the form (major, minor,
2467 34fbc862 Andrea Spadaccini
                        revision)
2468 eb58f9b1 Guido Trotter

2469 eb58f9b1 Guido Trotter
    """
2470 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
2471 4b9638dc Guido Trotter
    # FIXME: this is the global kvm version, but the actual version can be
2472 4b9638dc Guido Trotter
    # customized as an hv parameter. we should use the nodegroup's default kvm
2473 4b9638dc Guido Trotter
    # path parameter here.
2474 3b59ec02 Guido Trotter
    _, v_major, v_min, v_rev = self._GetKVMVersion(constants.KVM_PATH)
2475 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2476 34fbc862 Andrea Spadaccini
    return result
2477 eb58f9b1 Guido Trotter
2478 637ce7f9 Guido Trotter
  @classmethod
2479 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
2480 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
2481 eb58f9b1 Guido Trotter

2482 eb58f9b1 Guido Trotter
    """
2483 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2484 9d9bded1 Michael Hanselmann
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2485 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2486 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2487 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
2488 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2489 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2490 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
2491 55cc0a44 Michael Hanselmann
                                     host=instance.primary_node,
2492 052783ff Michael Hanselmann
                                     user=constants.SSH_CONSOLE_USER,
2493 55cc0a44 Michael Hanselmann
                                     command=cmd)
2494 3be34f57 Guido Trotter
2495 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2496 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2497 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
2498 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2499 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
2500 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
2501 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
2502 55cc0a44 Michael Hanselmann
                                     display=display)
2503 55cc0a44 Michael Hanselmann
2504 4d2cdb5a Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2505 4d2cdb5a Andrea Spadaccini
    if spice_bind:
2506 4d2cdb5a Andrea Spadaccini
      return objects.InstanceConsole(instance=instance.name,
2507 4d2cdb5a Andrea Spadaccini
                                     kind=constants.CONS_SPICE,
2508 4d2cdb5a Andrea Spadaccini
                                     host=spice_bind,
2509 4d2cdb5a Andrea Spadaccini
                                     port=instance.network_port)
2510 4d2cdb5a Andrea Spadaccini
2511 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
2512 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
2513 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
2514 55cc0a44 Michael Hanselmann
                                            instance.name))
2515 eb58f9b1 Guido Trotter
2516 eb58f9b1 Guido Trotter
  def Verify(self):
2517 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
2518 eb58f9b1 Guido Trotter

2519 cd04dfd2 Michael Hanselmann
    Check that the required binaries exist.
2520 cd04dfd2 Michael Hanselmann

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

2523 eb58f9b1 Guido Trotter
    """
2524 1f4b9d39 Iustin Pop
    msgs = []
2525 1f4b9d39 Iustin Pop
    # FIXME: this is the global kvm binary, but the actual path can be
2526 1f4b9d39 Iustin Pop
    # customized as an hv parameter; we should use the nodegroup's
2527 1f4b9d39 Iustin Pop
    # default kvm path parameter here.
2528 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
2529 1f4b9d39 Iustin Pop
      msgs.append("The KVM binary ('%s') does not exist" % constants.KVM_PATH)
2530 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2531 1f4b9d39 Iustin Pop
      msgs.append("The socat binary ('%s') does not exist" %
2532 1f4b9d39 Iustin Pop
                  constants.SOCAT_PATH)
2533 1f4b9d39 Iustin Pop
2534 1f4b9d39 Iustin Pop
    return self._FormatVerifyResults(msgs)
2535 14aa53cb Guido Trotter
2536 6b5605e8 Iustin Pop
  @classmethod
2537 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2538 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2539 6b5605e8 Iustin Pop

2540 6b5605e8 Iustin Pop
    @type hvparams:  dict
2541 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2542 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2543 6b5605e8 Iustin Pop

2544 6b5605e8 Iustin Pop
    """
2545 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2546 6b5605e8 Iustin Pop
2547 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
2548 df5ab9f0 Guido Trotter
    if kernel_path:
2549 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
2550 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
2551 205ab586 Iustin Pop
                                     " if a kernel is defined")
2552 6b5605e8 Iustin Pop
2553 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
2554 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
2555 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
2556 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
2557 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
2558 66d5dbef Guido Trotter
2559 14fd6c81 Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2560 14fd6c81 Guido Trotter
      serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2561 14fd6c81 Guido Trotter
      valid_speeds = constants.VALID_SERIAL_SPEEDS
2562 14fd6c81 Guido Trotter
      if not serial_speed or serial_speed not in valid_speeds:
2563 14fd6c81 Guido Trotter
        raise errors.HypervisorError("Invalid serial console speed, must be"
2564 14fd6c81 Guido Trotter
                                     " one of: %s" %
2565 14fd6c81 Guido Trotter
                                     utils.CommaJoin(valid_speeds))
2566 14fd6c81 Guido Trotter
2567 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2568 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
2569 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2570 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2571 835528af Iustin Pop
                                   " ISO path")
2572 f5118ade Iustin Pop
2573 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2574 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2575 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
2576 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
2577 d19d94db Guido Trotter
                                     " must be specified")
2578 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
2579 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
2580 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
2581 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
2582 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
2583 d19d94db Guido Trotter
2584 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2585 b451c4c7 Andrea Spadaccini
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2586 b1cb62bd Andrea Spadaccini
    if spice_bind:
2587 b1cb62bd Andrea Spadaccini
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2588 b1cb62bd Andrea Spadaccini
        # if an IP version is specified, the spice_bind parameter must be an
2589 b1cb62bd Andrea Spadaccini
        # IP of that family
2590 b1cb62bd Andrea Spadaccini
        if (netutils.IP4Address.IsValid(spice_bind) and
2591 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP4_VERSION):
2592 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv4 address (%s), but"
2593 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2594 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2595 b1cb62bd Andrea Spadaccini
2596 b1cb62bd Andrea Spadaccini
        if (netutils.IP6Address.IsValid(spice_bind) and
2597 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP6_VERSION):
2598 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv6 address (%s), but"
2599 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2600 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2601 b451c4c7 Andrea Spadaccini
    else:
2602 0e1b03b9 Andrea Spadaccini
      # All the other SPICE parameters depend on spice_bind being set. Raise an
2603 0e1b03b9 Andrea Spadaccini
      # error if any of them is set without it.
2604 07788a0b Michael Hanselmann
      for param in _SPICE_ADDITIONAL_PARAMS:
2605 0e1b03b9 Andrea Spadaccini
        if hvparams[param]:
2606 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: %s requires %s to be set" %
2607 0e1b03b9 Andrea Spadaccini
                                       (param, constants.HV_KVM_SPICE_BIND))
2608 b1cb62bd Andrea Spadaccini
2609 d19d94db Guido Trotter
  @classmethod
2610 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
2611 d19d94db Guido Trotter
    """Check the given parameters for validity.
2612 d19d94db Guido Trotter

2613 d19d94db Guido Trotter
    @type hvparams:  dict
2614 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2615 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2616 d19d94db Guido Trotter

2617 d19d94db Guido Trotter
    """
2618 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2619 d19d94db Guido Trotter
2620 82e3bf85 Dimitris Aragiorgis
    kvm_path = hvparams[constants.HV_KVM_PATH]
2621 82e3bf85 Dimitris Aragiorgis
2622 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2623 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2624 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2625 d19d94db Guido Trotter
      try:
2626 1feb39ec Guido Trotter
        pwd.getpwnam(username)
2627 d19d94db Guido Trotter
      except KeyError:
2628 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
2629 d19d94db Guido Trotter
                                     % username)
2630 d19d94db Guido Trotter
2631 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2632 b1cb62bd Andrea Spadaccini
    if spice_bind:
2633 b1cb62bd Andrea Spadaccini
      # only one of VNC and SPICE can be used currently.
2634 b1cb62bd Andrea Spadaccini
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2635 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("Both SPICE and VNC are configured, but"
2636 b1cb62bd Andrea Spadaccini
                                     " only one of them can be used at a"
2637 afa9bb2e Michael Hanselmann
                                     " given time")
2638 b1cb62bd Andrea Spadaccini
2639 3b59ec02 Guido Trotter
      # check that KVM supports SPICE
2640 6e043e60 Guido Trotter
      kvmhelp = cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP)
2641 0ad7f5d8 Guido Trotter
      if not cls._SPICE_RE.search(kvmhelp):
2642 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE is configured, but it is not"
2643 afa9bb2e Michael Hanselmann
                                     " supported according to 'kvm --help'")
2644 b1cb62bd Andrea Spadaccini
2645 b1cb62bd Andrea Spadaccini
      # if spice_bind is not an IP address, it must be a valid interface
2646 afa9bb2e Michael Hanselmann
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind) or
2647 afa9bb2e Michael Hanselmann
                       netutils.IP6Address.IsValid(spice_bind))
2648 b1cb62bd Andrea Spadaccini
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2649 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE: The %s parameter must be either"
2650 b1cb62bd Andrea Spadaccini
                                     " a valid IP address or interface name" %
2651 b1cb62bd Andrea Spadaccini
                                     constants.HV_KVM_SPICE_BIND)
2652 b1cb62bd Andrea Spadaccini
2653 82e3bf85 Dimitris Aragiorgis
    machine_version = hvparams[constants.HV_KVM_MACHINE_VERSION]
2654 82e3bf85 Dimitris Aragiorgis
    if machine_version:
2655 6e043e60 Guido Trotter
      output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2656 82e3bf85 Dimitris Aragiorgis
      if not cls._CHECK_MACHINE_VERSION_RE(machine_version).search(output):
2657 82e3bf85 Dimitris Aragiorgis
        raise errors.HypervisorError("Unsupported machine version: %s" %
2658 82e3bf85 Dimitris Aragiorgis
                                     machine_version)
2659 82e3bf85 Dimitris Aragiorgis
2660 f5118ade Iustin Pop
  @classmethod
2661 f5118ade Iustin Pop
  def PowercycleNode(cls):
2662 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
2663 f5118ade Iustin Pop

2664 f5118ade Iustin Pop
    """
2665 f5118ade Iustin Pop
    cls.LinuxPowercycle()