Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 061a6a1d

History | View | Annotate | Download (95.8 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 0745fe0e 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 e506cce0 Dimitris Aragiorgis
try:
46 e506cce0 Dimitris Aragiorgis
  import fdsend   # pylint: disable=F0401
47 e506cce0 Dimitris Aragiorgis
except ImportError:
48 e506cce0 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 0745fe0e Dimitris Aragiorgis
# Constant bitarray that reflects to a free pci slot
88 0745fe0e Dimitris Aragiorgis
# Use it with bitarray.search()
89 0745fe0e Dimitris Aragiorgis
_AVAILABLE_PCI_SLOT = bitarray("0")
90 0745fe0e Dimitris Aragiorgis
91 8bbcbb9e Dimitris Aragiorgis
# below constants show the format of runtime file
92 8bbcbb9e Dimitris Aragiorgis
# the nics are in second possition, while the disks in 4th (last)
93 8bbcbb9e Dimitris Aragiorgis
# moreover disk entries are stored in tupples of L{objects.Disk}, dev_path
94 8bbcbb9e Dimitris Aragiorgis
_KVM_NICS_RUNTIME_INDEX = 1
95 8bbcbb9e Dimitris Aragiorgis
_KVM_DISKS_RUNTIME_INDEX = 3
96 8bbcbb9e Dimitris Aragiorgis
_DEVICE_RUNTIME_INDEX = {
97 8bbcbb9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK: _KVM_DISKS_RUNTIME_INDEX,
98 8bbcbb9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC: _KVM_NICS_RUNTIME_INDEX
99 8bbcbb9e Dimitris Aragiorgis
  }
100 8bbcbb9e Dimitris Aragiorgis
_FIND_RUNTIME_ENTRY = {
101 8bbcbb9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC:
102 8bbcbb9e Dimitris Aragiorgis
    lambda nic, kvm_nics: [n for n in kvm_nics if n.uuid == nic.uuid],
103 8bbcbb9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK:
104 8bbcbb9e Dimitris Aragiorgis
    lambda disk, kvm_disks: [(d, l) for (d, l) in kvm_disks
105 8bbcbb9e Dimitris Aragiorgis
                             if d.uuid == disk.uuid]
106 8bbcbb9e Dimitris Aragiorgis
  }
107 8bbcbb9e Dimitris Aragiorgis
_RUNTIME_DEVICE = {
108 8bbcbb9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC: lambda d: d,
109 8bbcbb9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK: lambda (d, e): d
110 8bbcbb9e Dimitris Aragiorgis
  }
111 8bbcbb9e Dimitris Aragiorgis
_RUNTIME_ENTRY = {
112 8bbcbb9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC: lambda d, e: d,
113 8bbcbb9e Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK: lambda d, e: (d, e)
114 8bbcbb9e Dimitris Aragiorgis
  }
115 8bbcbb9e Dimitris Aragiorgis
116 8bbcbb9e Dimitris Aragiorgis
117 218e4c34 Dimitris Aragiorgis
def _GenerateDeviceKVMId(dev_type, dev, idx=None):
118 0745fe0e Dimitris Aragiorgis
  """Helper function to generate a unique device name used by KVM
119 0745fe0e Dimitris Aragiorgis

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

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

130 0745fe0e Dimitris Aragiorgis
  """
131 0745fe0e Dimitris Aragiorgis
132 218e4c34 Dimitris Aragiorgis
  # proper device id - available in latest Ganeti versions
133 218e4c34 Dimitris Aragiorgis
  if dev.pci and dev.uuid:
134 218e4c34 Dimitris Aragiorgis
    return "%s-%s-pci-%d" % (dev_type.lower(), dev.uuid.split("-")[0], dev.pci)
135 0745fe0e Dimitris Aragiorgis
136 218e4c34 Dimitris Aragiorgis
  # dummy device id - returned only to _GenerateKVMBlockDevicesOptions
137 218e4c34 Dimitris Aragiorgis
  # This enables -device option for paravirtual disk_type
138 218e4c34 Dimitris Aragiorgis
  if idx is not None:
139 218e4c34 Dimitris Aragiorgis
    return "%s-%d" % (dev_type.lower(), idx)
140 218e4c34 Dimitris Aragiorgis
141 218e4c34 Dimitris Aragiorgis
  raise errors.HotplugError("Hotplug is not supported for devices"
142 218e4c34 Dimitris Aragiorgis
                            " without UUID or PCI info")
143 0745fe0e Dimitris Aragiorgis
144 0745fe0e Dimitris Aragiorgis
145 0745fe0e Dimitris Aragiorgis
def _UpdatePCISlots(dev, pci_reservations):
146 0745fe0e Dimitris Aragiorgis
  """Update pci configuration for a stopped instance
147 0745fe0e Dimitris Aragiorgis

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

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

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

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

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

186 8bbcbb9e Dimitris Aragiorgis
  """
187 8bbcbb9e Dimitris Aragiorgis
  index = _DEVICE_RUNTIME_INDEX[dev_type]
188 8bbcbb9e Dimitris Aragiorgis
  found = _FIND_RUNTIME_ENTRY[dev_type](device, runtime[index])
189 8bbcbb9e Dimitris Aragiorgis
  if not found:
190 8bbcbb9e Dimitris Aragiorgis
    raise errors.HotplugError("Cannot find runtime info for %s with UUID %s" %
191 8bbcbb9e Dimitris Aragiorgis
                              (dev_type, device.uuid))
192 8bbcbb9e Dimitris Aragiorgis
193 8bbcbb9e Dimitris Aragiorgis
  return found[0]
194 8bbcbb9e Dimitris Aragiorgis
195 199b2053 Apollon Oikonomopoulos
196 ea2bcb82 Michael Hanselmann
def _GetTunFeatures(fd, _ioctl=fcntl.ioctl):
197 ea2bcb82 Michael Hanselmann
  """Retrieves supported TUN features from file descriptor.
198 ea2bcb82 Michael Hanselmann

199 ea2bcb82 Michael Hanselmann
  @see: L{_ProbeTapVnetHdr}
200 ea2bcb82 Michael Hanselmann

201 ea2bcb82 Michael Hanselmann
  """
202 ea2bcb82 Michael Hanselmann
  req = struct.pack("I", 0)
203 ea2bcb82 Michael Hanselmann
  try:
204 ea2bcb82 Michael Hanselmann
    buf = _ioctl(fd, TUNGETFEATURES, req)
205 ea2bcb82 Michael Hanselmann
  except EnvironmentError, err:
206 cfc24646 Iustin Pop
    logging.warning("ioctl(TUNGETFEATURES) failed: %s", err)
207 ea2bcb82 Michael Hanselmann
    return None
208 ea2bcb82 Michael Hanselmann
  else:
209 ea2bcb82 Michael Hanselmann
    (flags, ) = struct.unpack("I", buf)
210 ea2bcb82 Michael Hanselmann
    return flags
211 ea2bcb82 Michael Hanselmann
212 ea2bcb82 Michael Hanselmann
213 ea2bcb82 Michael Hanselmann
def _ProbeTapVnetHdr(fd, _features_fn=_GetTunFeatures):
214 199b2053 Apollon Oikonomopoulos
  """Check whether to enable the IFF_VNET_HDR flag.
215 199b2053 Apollon Oikonomopoulos

216 199b2053 Apollon Oikonomopoulos
  To do this, _all_ of the following conditions must be met:
217 199b2053 Apollon Oikonomopoulos
   1. TUNGETFEATURES ioctl() *must* be implemented
218 199b2053 Apollon Oikonomopoulos
   2. TUNGETFEATURES ioctl() result *must* contain the IFF_VNET_HDR flag
219 199b2053 Apollon Oikonomopoulos
   3. TUNGETIFF ioctl() *must* be implemented; reading the kernel code in
220 199b2053 Apollon Oikonomopoulos
      drivers/net/tun.c there is no way to test this until after the tap device
221 199b2053 Apollon Oikonomopoulos
      has been created using TUNSETIFF, and there is no way to change the
222 199b2053 Apollon Oikonomopoulos
      IFF_VNET_HDR flag after creating the interface, catch-22! However both
223 199b2053 Apollon Oikonomopoulos
      TUNGETIFF and TUNGETFEATURES were introduced in kernel version 2.6.27,
224 199b2053 Apollon Oikonomopoulos
      thus we can expect TUNGETIFF to be present if TUNGETFEATURES is.
225 199b2053 Apollon Oikonomopoulos

226 199b2053 Apollon Oikonomopoulos
   @type fd: int
227 199b2053 Apollon Oikonomopoulos
   @param fd: the file descriptor of /dev/net/tun
228 199b2053 Apollon Oikonomopoulos

229 199b2053 Apollon Oikonomopoulos
  """
230 ea2bcb82 Michael Hanselmann
  flags = _features_fn(fd)
231 199b2053 Apollon Oikonomopoulos
232 ea2bcb82 Michael Hanselmann
  if flags is None:
233 ea2bcb82 Michael Hanselmann
    # Not supported
234 199b2053 Apollon Oikonomopoulos
    return False
235 199b2053 Apollon Oikonomopoulos
236 ea2bcb82 Michael Hanselmann
  result = bool(flags & IFF_VNET_HDR)
237 ea2bcb82 Michael Hanselmann
238 ea2bcb82 Michael Hanselmann
  if not result:
239 ea2bcb82 Michael Hanselmann
    logging.warning("Kernel does not support IFF_VNET_HDR, not enabling")
240 ea2bcb82 Michael Hanselmann
241 ea2bcb82 Michael Hanselmann
  return result
242 ea2bcb82 Michael Hanselmann
243 199b2053 Apollon Oikonomopoulos
244 199b2053 Apollon Oikonomopoulos
def _OpenTap(vnet_hdr=True):
245 199b2053 Apollon Oikonomopoulos
  """Open a new tap device and return its file descriptor.
246 199b2053 Apollon Oikonomopoulos

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

250 199b2053 Apollon Oikonomopoulos
  @type vnet_hdr: boolean
251 199b2053 Apollon Oikonomopoulos
  @param vnet_hdr: Enable the VNET Header
252 199b2053 Apollon Oikonomopoulos
  @return: (ifname, tapfd)
253 199b2053 Apollon Oikonomopoulos
  @rtype: tuple
254 199b2053 Apollon Oikonomopoulos

255 199b2053 Apollon Oikonomopoulos
  """
256 199b2053 Apollon Oikonomopoulos
  try:
257 199b2053 Apollon Oikonomopoulos
    tapfd = os.open("/dev/net/tun", os.O_RDWR)
258 199b2053 Apollon Oikonomopoulos
  except EnvironmentError:
259 199b2053 Apollon Oikonomopoulos
    raise errors.HypervisorError("Failed to open /dev/net/tun")
260 199b2053 Apollon Oikonomopoulos
261 199b2053 Apollon Oikonomopoulos
  flags = IFF_TAP | IFF_NO_PI
262 199b2053 Apollon Oikonomopoulos
263 199b2053 Apollon Oikonomopoulos
  if vnet_hdr and _ProbeTapVnetHdr(tapfd):
264 199b2053 Apollon Oikonomopoulos
    flags |= IFF_VNET_HDR
265 199b2053 Apollon Oikonomopoulos
266 199b2053 Apollon Oikonomopoulos
  # The struct ifreq ioctl request (see netdevice(7))
267 199b2053 Apollon Oikonomopoulos
  ifr = struct.pack("16sh", "", flags)
268 199b2053 Apollon Oikonomopoulos
269 199b2053 Apollon Oikonomopoulos
  try:
270 199b2053 Apollon Oikonomopoulos
    res = fcntl.ioctl(tapfd, TUNSETIFF, ifr)
271 6f1e1921 Michael Hanselmann
  except EnvironmentError, err:
272 6f1e1921 Michael Hanselmann
    raise errors.HypervisorError("Failed to allocate a new TAP device: %s" %
273 6f1e1921 Michael Hanselmann
                                 err)
274 199b2053 Apollon Oikonomopoulos
275 199b2053 Apollon Oikonomopoulos
  # Get the interface name from the ioctl
276 199b2053 Apollon Oikonomopoulos
  ifname = struct.unpack("16sh", res)[0].strip("\x00")
277 199b2053 Apollon Oikonomopoulos
  return (ifname, tapfd)
278 199b2053 Apollon Oikonomopoulos
279 748e4b5a Michael Hanselmann
280 91c10532 Andrea Spadaccini
class QmpMessage:
281 91c10532 Andrea Spadaccini
  """QEMU Messaging Protocol (QMP) message.
282 91c10532 Andrea Spadaccini

283 91c10532 Andrea Spadaccini
  """
284 91c10532 Andrea Spadaccini
  def __init__(self, data):
285 91c10532 Andrea Spadaccini
    """Creates a new QMP message based on the passed data.
286 91c10532 Andrea Spadaccini

287 91c10532 Andrea Spadaccini
    """
288 91c10532 Andrea Spadaccini
    if not isinstance(data, dict):
289 91c10532 Andrea Spadaccini
      raise TypeError("QmpMessage must be initialized with a dict")
290 91c10532 Andrea Spadaccini
291 91c10532 Andrea Spadaccini
    self.data = data
292 91c10532 Andrea Spadaccini
293 91c10532 Andrea Spadaccini
  def __getitem__(self, field_name):
294 91c10532 Andrea Spadaccini
    """Get the value of the required field if present, or None.
295 91c10532 Andrea Spadaccini

296 91c10532 Andrea Spadaccini
    Overrides the [] operator to provide access to the message data,
297 91c10532 Andrea Spadaccini
    returning None if the required item is not in the message
298 91c10532 Andrea Spadaccini
    @return: the value of the field_name field, or None if field_name
299 91c10532 Andrea Spadaccini
             is not contained in the message
300 91c10532 Andrea Spadaccini

301 91c10532 Andrea Spadaccini
    """
302 9b87c2cf Michael Hanselmann
    return self.data.get(field_name, None)
303 91c10532 Andrea Spadaccini
304 91c10532 Andrea Spadaccini
  def __setitem__(self, field_name, field_value):
305 91c10532 Andrea Spadaccini
    """Set the value of the required field_name to field_value.
306 91c10532 Andrea Spadaccini

307 91c10532 Andrea Spadaccini
    """
308 91c10532 Andrea Spadaccini
    self.data[field_name] = field_value
309 91c10532 Andrea Spadaccini
310 91c10532 Andrea Spadaccini
  @staticmethod
311 91c10532 Andrea Spadaccini
  def BuildFromJsonString(json_string):
312 91c10532 Andrea Spadaccini
    """Build a QmpMessage from a JSON encoded string.
313 91c10532 Andrea Spadaccini

314 91c10532 Andrea Spadaccini
    @type json_string: str
315 91c10532 Andrea Spadaccini
    @param json_string: JSON string representing the message
316 91c10532 Andrea Spadaccini
    @rtype: L{QmpMessage}
317 91c10532 Andrea Spadaccini
    @return: a L{QmpMessage} built from json_string
318 91c10532 Andrea Spadaccini

319 91c10532 Andrea Spadaccini
    """
320 91c10532 Andrea Spadaccini
    # Parse the string
321 91c10532 Andrea Spadaccini
    data = serializer.LoadJson(json_string)
322 91c10532 Andrea Spadaccini
    return QmpMessage(data)
323 91c10532 Andrea Spadaccini
324 91c10532 Andrea Spadaccini
  def __str__(self):
325 a182a3ed Michael Hanselmann
    # The protocol expects the JSON object to be sent as a single line.
326 a182a3ed Michael Hanselmann
    return serializer.DumpJson(self.data)
327 91c10532 Andrea Spadaccini
328 91c10532 Andrea Spadaccini
  def __eq__(self, other):
329 91c10532 Andrea Spadaccini
    # When comparing two QmpMessages, we are interested in comparing
330 91c10532 Andrea Spadaccini
    # their internal representation of the message data
331 91c10532 Andrea Spadaccini
    return self.data == other.data
332 91c10532 Andrea Spadaccini
333 91c10532 Andrea Spadaccini
334 f028b2bf Dimitris Aragiorgis
class MonitorSocket(object):
335 91c10532 Andrea Spadaccini
  _SOCKET_TIMEOUT = 5
336 91c10532 Andrea Spadaccini
337 91c10532 Andrea Spadaccini
  def __init__(self, monitor_filename):
338 f028b2bf Dimitris Aragiorgis
    """Instantiates the MonitorSocket object.
339 91c10532 Andrea Spadaccini

340 91c10532 Andrea Spadaccini
    @type monitor_filename: string
341 91c10532 Andrea Spadaccini
    @param monitor_filename: the filename of the UNIX raw socket on which the
342 f028b2bf Dimitris Aragiorgis
                             monitor (QMP or simple one) is listening
343 91c10532 Andrea Spadaccini

344 91c10532 Andrea Spadaccini
    """
345 91c10532 Andrea Spadaccini
    self.monitor_filename = monitor_filename
346 91c10532 Andrea Spadaccini
    self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
347 91c10532 Andrea Spadaccini
    # We want to fail if the server doesn't send a complete message
348 91c10532 Andrea Spadaccini
    # in a reasonable amount of time
349 91c10532 Andrea Spadaccini
    self.sock.settimeout(self._SOCKET_TIMEOUT)
350 91c10532 Andrea Spadaccini
    self._connected = False
351 91c10532 Andrea Spadaccini
352 fc84cd5d Guido Trotter
  def _check_socket(self):
353 fc84cd5d Guido Trotter
    sock_stat = None
354 fc84cd5d Guido Trotter
    try:
355 fc84cd5d Guido Trotter
      sock_stat = os.stat(self.monitor_filename)
356 fc84cd5d Guido Trotter
    except EnvironmentError, err:
357 fc84cd5d Guido Trotter
      if err.errno == errno.ENOENT:
358 f028b2bf Dimitris Aragiorgis
        raise errors.HypervisorError("No monitor socket found")
359 fc84cd5d Guido Trotter
      else:
360 f028b2bf Dimitris Aragiorgis
        raise errors.HypervisorError("Error checking monitor socket: %s",
361 fc84cd5d Guido Trotter
                                     utils.ErrnoOrStr(err))
362 fc84cd5d Guido Trotter
    if not stat.S_ISSOCK(sock_stat.st_mode):
363 f028b2bf Dimitris Aragiorgis
      raise errors.HypervisorError("Monitor socket is not a socket")
364 fc84cd5d Guido Trotter
365 91c10532 Andrea Spadaccini
  def _check_connection(self):
366 91c10532 Andrea Spadaccini
    """Make sure that the connection is established.
367 91c10532 Andrea Spadaccini

368 91c10532 Andrea Spadaccini
    """
369 91c10532 Andrea Spadaccini
    if not self._connected:
370 f028b2bf Dimitris Aragiorgis
      raise errors.ProgrammerError("To use a MonitorSocket you need to first"
371 91c10532 Andrea Spadaccini
                                   " invoke connect() on it")
372 91c10532 Andrea Spadaccini
373 91c10532 Andrea Spadaccini
  def connect(self):
374 f028b2bf Dimitris Aragiorgis
    """Connects to the monitor.
375 91c10532 Andrea Spadaccini

376 f028b2bf Dimitris Aragiorgis
    Connects to the UNIX socket
377 91c10532 Andrea Spadaccini

378 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
379 91c10532 Andrea Spadaccini

380 91c10532 Andrea Spadaccini
    """
381 fc84cd5d Guido Trotter
    if self._connected:
382 fc84cd5d Guido Trotter
      raise errors.ProgrammerError("Cannot connect twice")
383 fc84cd5d Guido Trotter
384 fc84cd5d Guido Trotter
    self._check_socket()
385 fc84cd5d Guido Trotter
386 fc84cd5d Guido Trotter
    # Check file existance/stuff
387 fc84cd5d Guido Trotter
    try:
388 fc84cd5d Guido Trotter
      self.sock.connect(self.monitor_filename)
389 fc84cd5d Guido Trotter
    except EnvironmentError:
390 fc84cd5d Guido Trotter
      raise errors.HypervisorError("Can't connect to qmp socket")
391 91c10532 Andrea Spadaccini
    self._connected = True
392 91c10532 Andrea Spadaccini
393 f028b2bf Dimitris Aragiorgis
  def close(self):
394 f028b2bf Dimitris Aragiorgis
    """Closes the socket
395 f028b2bf Dimitris Aragiorgis

396 f028b2bf Dimitris Aragiorgis
    It cannot be used after this call.
397 f028b2bf Dimitris Aragiorgis

398 f028b2bf Dimitris Aragiorgis
    """
399 f028b2bf Dimitris Aragiorgis
    self.sock.close()
400 f028b2bf Dimitris Aragiorgis
401 f028b2bf Dimitris Aragiorgis
402 f028b2bf Dimitris Aragiorgis
class QmpConnection(MonitorSocket):
403 f028b2bf Dimitris Aragiorgis
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
404 f028b2bf Dimitris Aragiorgis

405 f028b2bf Dimitris Aragiorgis
  """
406 f028b2bf Dimitris Aragiorgis
  _FIRST_MESSAGE_KEY = "QMP"
407 f028b2bf Dimitris Aragiorgis
  _EVENT_KEY = "event"
408 f028b2bf Dimitris Aragiorgis
  _ERROR_KEY = "error"
409 f028b2bf Dimitris Aragiorgis
  _RETURN_KEY = RETURN_KEY = "return"
410 f028b2bf Dimitris Aragiorgis
  _ACTUAL_KEY = ACTUAL_KEY = "actual"
411 f028b2bf Dimitris Aragiorgis
  _ERROR_CLASS_KEY = "class"
412 f028b2bf Dimitris Aragiorgis
  _ERROR_DATA_KEY = "data"
413 f028b2bf Dimitris Aragiorgis
  _ERROR_DESC_KEY = "desc"
414 f028b2bf Dimitris Aragiorgis
  _EXECUTE_KEY = "execute"
415 f028b2bf Dimitris Aragiorgis
  _ARGUMENTS_KEY = "arguments"
416 f028b2bf Dimitris Aragiorgis
  _CAPABILITIES_COMMAND = "qmp_capabilities"
417 f028b2bf Dimitris Aragiorgis
  _MESSAGE_END_TOKEN = "\r\n"
418 f028b2bf Dimitris Aragiorgis
419 f028b2bf Dimitris Aragiorgis
  def __init__(self, monitor_filename):
420 f028b2bf Dimitris Aragiorgis
    super(QmpConnection, self).__init__(monitor_filename)
421 f028b2bf Dimitris Aragiorgis
    self._buf = ""
422 f028b2bf Dimitris Aragiorgis
423 f028b2bf Dimitris Aragiorgis
  def connect(self):
424 f028b2bf Dimitris Aragiorgis
    """Connects to the QMP monitor.
425 f028b2bf Dimitris Aragiorgis

426 f028b2bf Dimitris Aragiorgis
    Connects to the UNIX socket and makes sure that we can actually send and
427 f028b2bf Dimitris Aragiorgis
    receive data to the kvm instance via QMP.
428 f028b2bf Dimitris Aragiorgis

429 f028b2bf Dimitris Aragiorgis
    @raise errors.HypervisorError: when there are communication errors
430 f028b2bf Dimitris Aragiorgis
    @raise errors.ProgrammerError: when there are data serialization errors
431 f028b2bf Dimitris Aragiorgis

432 f028b2bf Dimitris Aragiorgis
    """
433 f028b2bf Dimitris Aragiorgis
    super(QmpConnection, self).connect()
434 91c10532 Andrea Spadaccini
    # Check if we receive a correct greeting message from the server
435 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 2.2)
436 91c10532 Andrea Spadaccini
    greeting = self._Recv()
437 91c10532 Andrea Spadaccini
    if not greeting[self._FIRST_MESSAGE_KEY]:
438 91c10532 Andrea Spadaccini
      self._connected = False
439 afa9bb2e Michael Hanselmann
      raise errors.HypervisorError("kvm: QMP communication error (wrong"
440 91c10532 Andrea Spadaccini
                                   " server greeting")
441 91c10532 Andrea Spadaccini
442 91c10532 Andrea Spadaccini
    # Let's put the monitor in command mode using the qmp_capabilities
443 91c10532 Andrea Spadaccini
    # command, or else no command will be executable.
444 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 4)
445 91c10532 Andrea Spadaccini
    self.Execute(self._CAPABILITIES_COMMAND)
446 91c10532 Andrea Spadaccini
447 91c10532 Andrea Spadaccini
  def _ParseMessage(self, buf):
448 91c10532 Andrea Spadaccini
    """Extract and parse a QMP message from the given buffer.
449 91c10532 Andrea Spadaccini

450 91c10532 Andrea Spadaccini
    Seeks for a QMP message in the given buf. If found, it parses it and
451 91c10532 Andrea Spadaccini
    returns it together with the rest of the characters in the buf.
452 91c10532 Andrea Spadaccini
    If no message is found, returns None and the whole buffer.
453 91c10532 Andrea Spadaccini

454 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
455 91c10532 Andrea Spadaccini

456 91c10532 Andrea Spadaccini
    """
457 91c10532 Andrea Spadaccini
    message = None
458 91c10532 Andrea Spadaccini
    # Check if we got the message end token (CRLF, as per the QEMU Protocol
459 91c10532 Andrea Spadaccini
    # Specification 0.1 - Section 2.1.1)
460 91c10532 Andrea Spadaccini
    pos = buf.find(self._MESSAGE_END_TOKEN)
461 91c10532 Andrea Spadaccini
    if pos >= 0:
462 91c10532 Andrea Spadaccini
      try:
463 91c10532 Andrea Spadaccini
        message = QmpMessage.BuildFromJsonString(buf[:pos + 1])
464 91c10532 Andrea Spadaccini
      except Exception, err:
465 91c10532 Andrea Spadaccini
        raise errors.ProgrammerError("QMP data serialization error: %s" % err)
466 91c10532 Andrea Spadaccini
      buf = buf[pos + 1:]
467 91c10532 Andrea Spadaccini
468 91c10532 Andrea Spadaccini
    return (message, buf)
469 91c10532 Andrea Spadaccini
470 91c10532 Andrea Spadaccini
  def _Recv(self):
471 91c10532 Andrea Spadaccini
    """Receives a message from QMP and decodes the received JSON object.
472 91c10532 Andrea Spadaccini

473 91c10532 Andrea Spadaccini
    @rtype: QmpMessage
474 91c10532 Andrea Spadaccini
    @return: the received message
475 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
476 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
477 91c10532 Andrea Spadaccini

478 91c10532 Andrea Spadaccini
    """
479 91c10532 Andrea Spadaccini
    self._check_connection()
480 91c10532 Andrea Spadaccini
481 91c10532 Andrea Spadaccini
    # Check if there is already a message in the buffer
482 91c10532 Andrea Spadaccini
    (message, self._buf) = self._ParseMessage(self._buf)
483 91c10532 Andrea Spadaccini
    if message:
484 91c10532 Andrea Spadaccini
      return message
485 91c10532 Andrea Spadaccini
486 91c10532 Andrea Spadaccini
    recv_buffer = StringIO.StringIO(self._buf)
487 91c10532 Andrea Spadaccini
    recv_buffer.seek(len(self._buf))
488 91c10532 Andrea Spadaccini
    try:
489 91c10532 Andrea Spadaccini
      while True:
490 91c10532 Andrea Spadaccini
        data = self.sock.recv(4096)
491 91c10532 Andrea Spadaccini
        if not data:
492 91c10532 Andrea Spadaccini
          break
493 91c10532 Andrea Spadaccini
        recv_buffer.write(data)
494 91c10532 Andrea Spadaccini
495 91c10532 Andrea Spadaccini
        (message, self._buf) = self._ParseMessage(recv_buffer.getvalue())
496 91c10532 Andrea Spadaccini
        if message:
497 91c10532 Andrea Spadaccini
          return message
498 91c10532 Andrea Spadaccini
499 91c10532 Andrea Spadaccini
    except socket.timeout, err:
500 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while receiving a QMP message: "
501 91c10532 Andrea Spadaccini
                                   "%s" % (err))
502 91c10532 Andrea Spadaccini
    except socket.error, err:
503 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to receive data from KVM using the"
504 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
505 91c10532 Andrea Spadaccini
506 91c10532 Andrea Spadaccini
  def _Send(self, message):
507 91c10532 Andrea Spadaccini
    """Encodes and sends a message to KVM using QMP.
508 91c10532 Andrea Spadaccini

509 91c10532 Andrea Spadaccini
    @type message: QmpMessage
510 91c10532 Andrea Spadaccini
    @param message: message to send to KVM
511 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
512 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
513 91c10532 Andrea Spadaccini

514 91c10532 Andrea Spadaccini
    """
515 91c10532 Andrea Spadaccini
    self._check_connection()
516 91c10532 Andrea Spadaccini
    try:
517 91c10532 Andrea Spadaccini
      message_str = str(message)
518 91c10532 Andrea Spadaccini
    except Exception, err:
519 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("QMP data deserialization error: %s" % err)
520 91c10532 Andrea Spadaccini
521 91c10532 Andrea Spadaccini
    try:
522 91c10532 Andrea Spadaccini
      self.sock.sendall(message_str)
523 91c10532 Andrea Spadaccini
    except socket.timeout, err:
524 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while sending a QMP message: "
525 91c10532 Andrea Spadaccini
                                   "%s (%s)" % (err.string, err.errno))
526 91c10532 Andrea Spadaccini
    except socket.error, err:
527 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to send data from KVM using the"
528 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
529 91c10532 Andrea Spadaccini
530 91c10532 Andrea Spadaccini
  def Execute(self, command, arguments=None):
531 91c10532 Andrea Spadaccini
    """Executes a QMP command and returns the response of the server.
532 91c10532 Andrea Spadaccini

533 91c10532 Andrea Spadaccini
    @type command: str
534 91c10532 Andrea Spadaccini
    @param command: the command to execute
535 91c10532 Andrea Spadaccini
    @type arguments: dict
536 91c10532 Andrea Spadaccini
    @param arguments: dictionary of arguments to be passed to the command
537 91c10532 Andrea Spadaccini
    @rtype: dict
538 91c10532 Andrea Spadaccini
    @return: dictionary representing the received JSON object
539 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
540 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
541 91c10532 Andrea Spadaccini

542 91c10532 Andrea Spadaccini
    """
543 91c10532 Andrea Spadaccini
    self._check_connection()
544 91c10532 Andrea Spadaccini
    message = QmpMessage({self._EXECUTE_KEY: command})
545 91c10532 Andrea Spadaccini
    if arguments:
546 91c10532 Andrea Spadaccini
      message[self._ARGUMENTS_KEY] = arguments
547 91c10532 Andrea Spadaccini
    self._Send(message)
548 91c10532 Andrea Spadaccini
549 91c10532 Andrea Spadaccini
    # Events can occur between the sending of the command and the reception
550 91c10532 Andrea Spadaccini
    # of the response, so we need to filter out messages with the event key.
551 91c10532 Andrea Spadaccini
    while True:
552 91c10532 Andrea Spadaccini
      response = self._Recv()
553 91c10532 Andrea Spadaccini
      err = response[self._ERROR_KEY]
554 91c10532 Andrea Spadaccini
      if err:
555 91c10532 Andrea Spadaccini
        raise errors.HypervisorError("kvm: error executing the %s"
556 91c10532 Andrea Spadaccini
                                     " command: %s (%s, %s):" %
557 91c10532 Andrea Spadaccini
                                     (command,
558 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DESC_KEY],
559 91c10532 Andrea Spadaccini
                                      err[self._ERROR_CLASS_KEY],
560 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DATA_KEY]))
561 91c10532 Andrea Spadaccini
562 91c10532 Andrea Spadaccini
      elif not response[self._EVENT_KEY]:
563 91c10532 Andrea Spadaccini
        return response
564 91c10532 Andrea Spadaccini
565 91c10532 Andrea Spadaccini
566 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
567 65107a2f Michael Hanselmann
  """KVM hypervisor interface
568 65107a2f Michael Hanselmann

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

753 98ec75d6 Iustin Pop
    """
754 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
755 98ec75d6 Iustin Pop
756 263b8de6 Guido Trotter
  @classmethod
757 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
758 7548396c Guido Trotter
    """Returns the instance uidfile.
759 7548396c Guido Trotter

760 7548396c Guido Trotter
    """
761 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
762 7548396c Guido Trotter
763 7548396c Guido Trotter
  @classmethod
764 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
765 263b8de6 Guido Trotter
    """Check pid file for instance information.
766 263b8de6 Guido Trotter

767 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
768 263b8de6 Guido Trotter
    information from its command line.
769 263b8de6 Guido Trotter

770 263b8de6 Guido Trotter
    @type pid: string or int
771 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
772 263b8de6 Guido Trotter
    @rtype: tuple
773 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
774 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
775 263b8de6 Guido Trotter

776 263b8de6 Guido Trotter
    """
777 263b8de6 Guido Trotter
    alive = utils.IsProcessAlive(pid)
778 263b8de6 Guido Trotter
    if not alive:
779 263b8de6 Guido Trotter
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
780 263b8de6 Guido Trotter
781 263b8de6 Guido Trotter
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
782 263b8de6 Guido Trotter
    try:
783 263b8de6 Guido Trotter
      cmdline = utils.ReadFile(cmdline_file)
784 263b8de6 Guido Trotter
    except EnvironmentError, err:
785 263b8de6 Guido Trotter
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
786 263b8de6 Guido Trotter
                                   (pid, err))
787 263b8de6 Guido Trotter
788 263b8de6 Guido Trotter
    instance = None
789 263b8de6 Guido Trotter
    memory = 0
790 263b8de6 Guido Trotter
    vcpus = 0
791 263b8de6 Guido Trotter
792 d0c8c01d Iustin Pop
    arg_list = cmdline.split("\x00")
793 263b8de6 Guido Trotter
    while arg_list:
794 e687ec01 Michael Hanselmann
      arg = arg_list.pop(0)
795 263b8de6 Guido Trotter
      if arg == "-name":
796 263b8de6 Guido Trotter
        instance = arg_list.pop(0)
797 263b8de6 Guido Trotter
      elif arg == "-m":
798 263b8de6 Guido Trotter
        memory = int(arg_list.pop(0))
799 263b8de6 Guido Trotter
      elif arg == "-smp":
800 4888a609 Guido Trotter
        vcpus = int(arg_list.pop(0).split(",")[0])
801 263b8de6 Guido Trotter
802 263b8de6 Guido Trotter
    if instance is None:
803 263b8de6 Guido Trotter
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
804 263b8de6 Guido Trotter
                                   " instance" % pid)
805 263b8de6 Guido Trotter
806 263b8de6 Guido Trotter
    return (instance, memory, vcpus)
807 263b8de6 Guido Trotter
808 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
809 263b8de6 Guido Trotter
    """Returns the instance pidfile, pid, and liveness.
810 263b8de6 Guido Trotter

811 263b8de6 Guido Trotter
    @type instance_name: string
812 263b8de6 Guido Trotter
    @param instance_name: instance name
813 263b8de6 Guido Trotter
    @rtype: tuple
814 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
815 1f8b3a27 Guido Trotter

816 1f8b3a27 Guido Trotter
    """
817 98ec75d6 Iustin Pop
    pidfile = self._InstancePidFile(instance_name)
818 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
819 263b8de6 Guido Trotter
820 263b8de6 Guido Trotter
    alive = False
821 263b8de6 Guido Trotter
    try:
822 263b8de6 Guido Trotter
      cmd_instance = self._InstancePidInfo(pid)[0]
823 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
824 263b8de6 Guido Trotter
    except errors.HypervisorError:
825 263b8de6 Guido Trotter
      pass
826 1f8b3a27 Guido Trotter
827 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
828 1f8b3a27 Guido Trotter
829 5905901c Iustin Pop
  def _CheckDown(self, instance_name):
830 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
831 5905901c Iustin Pop

832 5905901c Iustin Pop
    """
833 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
834 5905901c Iustin Pop
    if alive:
835 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
836 5905901c Iustin Pop
                                   (instance_name, "already running"))
837 5905901c Iustin Pop
838 0df4d98a Guido Trotter
  @classmethod
839 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
840 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
841 c4fbefc8 Guido Trotter

842 c4fbefc8 Guido Trotter
    """
843 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
844 c4fbefc8 Guido Trotter
845 0df4d98a Guido Trotter
  @classmethod
846 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
847 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
848 c4fbefc8 Guido Trotter

849 c4fbefc8 Guido Trotter
    """
850 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
851 c4fbefc8 Guido Trotter
852 91c10532 Andrea Spadaccini
  @classmethod
853 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
854 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
855 91c10532 Andrea Spadaccini

856 91c10532 Andrea Spadaccini
    """
857 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
858 91c10532 Andrea Spadaccini
859 86d6bc2a Guido Trotter
  @staticmethod
860 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
861 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
862 86d6bc2a Guido Trotter

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

865 86d6bc2a Guido Trotter
    """
866 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
867 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
868 86d6bc2a Guido Trotter
    else:
869 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
870 86d6bc2a Guido Trotter
871 0df4d98a Guido Trotter
  @classmethod
872 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
873 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
874 38e250ba Guido Trotter

875 38e250ba Guido Trotter
    """
876 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
877 38e250ba Guido Trotter
878 7e66c35b Guido Trotter
  @classmethod
879 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
880 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
881 547a63b7 Balazs Lecz

882 547a63b7 Balazs Lecz
    """
883 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
884 547a63b7 Balazs Lecz
885 547a63b7 Balazs Lecz
  @classmethod
886 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
887 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
888 5d9bfd87 Apollon Oikonomopoulos
    given instance.
889 5d9bfd87 Apollon Oikonomopoulos

890 5d9bfd87 Apollon Oikonomopoulos
    """
891 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
892 5d9bfd87 Apollon Oikonomopoulos
893 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
894 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
895 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
896 5d9bfd87 Apollon Oikonomopoulos

897 5d9bfd87 Apollon Oikonomopoulos
    """
898 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
899 5d9bfd87 Apollon Oikonomopoulos
900 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
901 4f580fef Sรฉbastien Bocahu
  def _InstanceKeymapFile(cls, instance_name):
902 4f580fef Sรฉbastien Bocahu
    """Returns the name of the file containing the keymap for a given instance
903 4f580fef Sรฉbastien Bocahu

904 4f580fef Sรฉbastien Bocahu
    """
905 4f580fef Sรฉbastien Bocahu
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
906 4f580fef Sรฉbastien Bocahu
907 4f580fef Sรฉbastien Bocahu
  @classmethod
908 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
909 7548396c Guido Trotter
    """Try to read a uid file
910 7548396c Guido Trotter

911 7548396c Guido Trotter
    """
912 7548396c Guido Trotter
    if os.path.exists(uid_file):
913 7548396c Guido Trotter
      try:
914 682f7601 Guido Trotter
        uid = int(utils.ReadOneLineFile(uid_file))
915 aa0b600b Guido Trotter
        return uid
916 7548396c Guido Trotter
      except EnvironmentError:
917 7548396c Guido Trotter
        logging.warning("Can't read uid file", exc_info=True)
918 7548396c Guido Trotter
      except (TypeError, ValueError):
919 7548396c Guido Trotter
        logging.warning("Can't parse uid file contents", exc_info=True)
920 aa0b600b Guido Trotter
    return None
921 7548396c Guido Trotter
922 7548396c Guido Trotter
  @classmethod
923 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
924 547a63b7 Balazs Lecz
    """Removes an instance's rutime sockets/files/dirs.
925 7e66c35b Guido Trotter

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

966 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
967 eb58f9b1 Guido Trotter
    @type instance: instance object
968 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
969 eb58f9b1 Guido Trotter
    @type seq: int
970 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
971 eb58f9b1 Guido Trotter
    @type nic: nic object
972 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
973 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
974 eb58f9b1 Guido Trotter

975 eb58f9b1 Guido Trotter
    """
976 5d9bfd87 Apollon Oikonomopoulos
    env = {
977 5d9bfd87 Apollon Oikonomopoulos
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
978 5d9bfd87 Apollon Oikonomopoulos
      "INSTANCE": instance.name,
979 5d9bfd87 Apollon Oikonomopoulos
      "MAC": nic.mac,
980 5d9bfd87 Apollon Oikonomopoulos
      "MODE": nic.nicparams[constants.NIC_MODE],
981 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE": tap,
982 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE_INDEX": str(seq),
983 2088b563 Dimitris Aragiorgis
      "TAGS": " ".join(instance.GetTags()),
984 5d9bfd87 Apollon Oikonomopoulos
    }
985 6254b733 Dimitris Aragiorgis
    if nic.uuid:
986 6254b733 Dimitris Aragiorgis
      env["INTERFACE_UUID"] = nic.uuid
987 5d9bfd87 Apollon Oikonomopoulos
988 5d9bfd87 Apollon Oikonomopoulos
    if nic.ip:
989 5d9bfd87 Apollon Oikonomopoulos
      env["IP"] = nic.ip
990 5d9bfd87 Apollon Oikonomopoulos
991 38f561d8 Dimitris Aragiorgis
    if nic.name:
992 38f561d8 Dimitris Aragiorgis
      env["INTERFACE_NAME"] = nic.name
993 38f561d8 Dimitris Aragiorgis
994 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_LINK]:
995 5d9bfd87 Apollon Oikonomopoulos
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
996 5d9bfd87 Apollon Oikonomopoulos
997 a5ad5e58 Apollon Oikonomopoulos
    if nic.network:
998 cbe4a0a5 Dimitris Aragiorgis
      n = objects.Network.FromDict(nic.netinfo)
999 7e8f03e3 Dimitris Aragiorgis
      env.update(n.HooksDict())
1000 a5ad5e58 Apollon Oikonomopoulos
1001 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1002 5d9bfd87 Apollon Oikonomopoulos
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
1003 5d9bfd87 Apollon Oikonomopoulos
1004 9d9bded1 Michael Hanselmann
    result = utils.RunCmd([pathutils.KVM_IFUP, tap], env=env)
1005 5d9bfd87 Apollon Oikonomopoulos
    if result.failed:
1006 afa9bb2e Michael Hanselmann
      raise errors.HypervisorError("Failed to configure interface %s: %s;"
1007 afa9bb2e Michael Hanselmann
                                   " network configuration script output: %s" %
1008 5d9bfd87 Apollon Oikonomopoulos
                                   (tap, result.fail_reason, result.output))
1009 eb58f9b1 Guido Trotter
1010 b693125f Tsachy Shacham
  @staticmethod
1011 b693125f Tsachy Shacham
  def _VerifyAffinityPackage():
1012 b693125f Tsachy Shacham
    if affinity is None:
1013 b693125f Tsachy Shacham
      raise errors.HypervisorError("affinity Python package not"
1014 5ae4945a Iustin Pop
                                   " found; cannot use CPU pinning under KVM")
1015 b693125f Tsachy Shacham
1016 b693125f Tsachy Shacham
  @staticmethod
1017 b693125f Tsachy Shacham
  def _BuildAffinityCpuMask(cpu_list):
1018 b693125f Tsachy Shacham
    """Create a CPU mask suitable for sched_setaffinity from a list of
1019 b693125f Tsachy Shacham
    CPUs.
1020 b693125f Tsachy Shacham

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

1024 b693125f Tsachy Shacham
    @type cpu_list: list of int
1025 b693125f Tsachy Shacham
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
1026 b693125f Tsachy Shacham
    @rtype: int
1027 b693125f Tsachy Shacham
    @return: a bit mask of CPU affinities
1028 b693125f Tsachy Shacham

1029 b693125f Tsachy Shacham
    """
1030 b693125f Tsachy Shacham
    if cpu_list == constants.CPU_PINNING_OFF:
1031 b693125f Tsachy Shacham
      return constants.CPU_PINNING_ALL_KVM
1032 b693125f Tsachy Shacham
    else:
1033 b693125f Tsachy Shacham
      return sum(2 ** cpu for cpu in cpu_list)
1034 b693125f Tsachy Shacham
1035 b693125f Tsachy Shacham
  @classmethod
1036 b693125f Tsachy Shacham
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
1037 b693125f Tsachy Shacham
    """Change CPU affinity for running VM according to given CPU mask.
1038 b693125f Tsachy Shacham

1039 b693125f Tsachy Shacham
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
1040 b693125f Tsachy Shacham
    @type cpu_mask: string
1041 b693125f Tsachy Shacham
    @param process_id: process ID of KVM process. Used to pin entire VM
1042 b693125f Tsachy Shacham
                       to physical CPUs.
1043 b693125f Tsachy Shacham
    @type process_id: int
1044 b693125f Tsachy Shacham
    @param thread_dict: map of virtual CPUs to KVM thread IDs
1045 b693125f Tsachy Shacham
    @type thread_dict: dict int:int
1046 b693125f Tsachy Shacham

1047 b693125f Tsachy Shacham
    """
1048 b693125f Tsachy Shacham
    # Convert the string CPU mask to a list of list of int's
1049 b693125f Tsachy Shacham
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
1050 b693125f Tsachy Shacham
1051 b693125f Tsachy Shacham
    if len(cpu_list) == 1:
1052 b693125f Tsachy Shacham
      all_cpu_mapping = cpu_list[0]
1053 b693125f Tsachy Shacham
      if all_cpu_mapping == constants.CPU_PINNING_OFF:
1054 b693125f Tsachy Shacham
        # If CPU pinning has 1 entry that's "all", then do nothing
1055 b693125f Tsachy Shacham
        pass
1056 b693125f Tsachy Shacham
      else:
1057 b693125f Tsachy Shacham
        # If CPU pinning has one non-all entry, map the entire VM to
1058 b693125f Tsachy Shacham
        # one set of physical CPUs
1059 b693125f Tsachy Shacham
        cls._VerifyAffinityPackage()
1060 5ae4945a Iustin Pop
        affinity.set_process_affinity_mask(
1061 5ae4945a Iustin Pop
          process_id, cls._BuildAffinityCpuMask(all_cpu_mapping))
1062 b693125f Tsachy Shacham
    else:
1063 b693125f Tsachy Shacham
      # The number of vCPUs mapped should match the number of vCPUs
1064 b693125f Tsachy Shacham
      # reported by KVM. This was already verified earlier, so
1065 b693125f Tsachy Shacham
      # here only as a sanity check.
1066 b693125f Tsachy Shacham
      assert len(thread_dict) == len(cpu_list)
1067 b693125f Tsachy Shacham
      cls._VerifyAffinityPackage()
1068 b693125f Tsachy Shacham
1069 b693125f Tsachy Shacham
      # For each vCPU, map it to the proper list of physical CPUs
1070 b693125f Tsachy Shacham
      for vcpu, i in zip(cpu_list, range(len(cpu_list))):
1071 b693125f Tsachy Shacham
        affinity.set_process_affinity_mask(thread_dict[i],
1072 5ae4945a Iustin Pop
                                           cls._BuildAffinityCpuMask(vcpu))
1073 b693125f Tsachy Shacham
1074 b693125f Tsachy Shacham
  def _GetVcpuThreadIds(self, instance_name):
1075 b693125f Tsachy Shacham
    """Get a mapping of vCPU no. to thread IDs for the instance
1076 b693125f Tsachy Shacham

1077 b693125f Tsachy Shacham
    @type instance_name: string
1078 b693125f Tsachy Shacham
    @param instance_name: instance in question
1079 b693125f Tsachy Shacham
    @rtype: dictionary of int:int
1080 b693125f Tsachy Shacham
    @return: a dictionary mapping vCPU numbers to thread IDs
1081 b693125f Tsachy Shacham

1082 b693125f Tsachy Shacham
    """
1083 b693125f Tsachy Shacham
    result = {}
1084 b693125f Tsachy Shacham
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
1085 b693125f Tsachy Shacham
    for line in output.stdout.splitlines():
1086 b693125f Tsachy Shacham
      match = self._CPU_INFO_RE.search(line)
1087 b693125f Tsachy Shacham
      if not match:
1088 b693125f Tsachy Shacham
        continue
1089 b693125f Tsachy Shacham
      grp = map(int, match.groups())
1090 b693125f Tsachy Shacham
      result[grp[0]] = grp[1]
1091 b693125f Tsachy Shacham
1092 b693125f Tsachy Shacham
    return result
1093 b693125f Tsachy Shacham
1094 1d8a7812 Andrea Spadaccini
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
1095 1d8a7812 Andrea Spadaccini
    """Complete CPU pinning.
1096 b693125f Tsachy Shacham

1097 b693125f Tsachy Shacham
    @type instance_name: string
1098 b693125f Tsachy Shacham
    @param instance_name: name of instance
1099 b693125f Tsachy Shacham
    @type cpu_mask: string
1100 b693125f Tsachy Shacham
    @param cpu_mask: CPU pinning mask as entered by user
1101 b693125f Tsachy Shacham

1102 b693125f Tsachy Shacham
    """
1103 1d8a7812 Andrea Spadaccini
    # Get KVM process ID, to be used if need to pin entire VM
1104 1d8a7812 Andrea Spadaccini
    _, pid, _ = self._InstancePidAlive(instance_name)
1105 1d8a7812 Andrea Spadaccini
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
1106 1d8a7812 Andrea Spadaccini
    thread_dict = self._GetVcpuThreadIds(instance_name)
1107 1d8a7812 Andrea Spadaccini
    # Run CPU pinning, based on configured mask
1108 1d8a7812 Andrea Spadaccini
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
1109 b693125f Tsachy Shacham
1110 eb58f9b1 Guido Trotter
  def ListInstances(self):
1111 eb58f9b1 Guido Trotter
    """Get the list of running instances.
1112 eb58f9b1 Guido Trotter

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

1116 eb58f9b1 Guido Trotter
    """
1117 eb58f9b1 Guido Trotter
    result = []
1118 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1119 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
1120 eb58f9b1 Guido Trotter
        result.append(name)
1121 eb58f9b1 Guido Trotter
    return result
1122 eb58f9b1 Guido Trotter
1123 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
1124 eb58f9b1 Guido Trotter
    """Get instance properties.
1125 eb58f9b1 Guido Trotter

1126 4fbb3c60 Guido Trotter
    @type instance_name: string
1127 c41eea6e Iustin Pop
    @param instance_name: the instance name
1128 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
1129 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
1130 eb58f9b1 Guido Trotter

1131 eb58f9b1 Guido Trotter
    """
1132 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
1133 1f8b3a27 Guido Trotter
    if not alive:
1134 eb58f9b1 Guido Trotter
      return None
1135 eb58f9b1 Guido Trotter
1136 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
1137 fc84cd5d Guido Trotter
    istat = "---b-"
1138 eb58f9b1 Guido Trotter
    times = "0"
1139 eb58f9b1 Guido Trotter
1140 89da2ff3 Guido Trotter
    try:
1141 89da2ff3 Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
1142 89da2ff3 Guido Trotter
      qmp.connect()
1143 89da2ff3 Guido Trotter
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
1144 89da2ff3 Guido Trotter
      # Will fail if ballooning is not enabled, but we can then just resort to
1145 89da2ff3 Guido Trotter
      # the value above.
1146 89da2ff3 Guido Trotter
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
1147 89da2ff3 Guido Trotter
      memory = mem_bytes / 1048576
1148 89da2ff3 Guido Trotter
    except errors.HypervisorError:
1149 89da2ff3 Guido Trotter
      pass
1150 89da2ff3 Guido Trotter
1151 fc84cd5d Guido Trotter
    return (instance_name, pid, memory, vcpus, istat, times)
1152 eb58f9b1 Guido Trotter
1153 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
1154 eb58f9b1 Guido Trotter
    """Get properties of all instances.
1155 eb58f9b1 Guido Trotter

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

1158 eb58f9b1 Guido Trotter
    """
1159 eb58f9b1 Guido Trotter
    data = []
1160 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1161 263b8de6 Guido Trotter
      try:
1162 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
1163 263b8de6 Guido Trotter
      except errors.HypervisorError:
1164 3bc145d8 Bernardo Dal Seno
        # Ignore exceptions due to instances being shut down
1165 263b8de6 Guido Trotter
        continue
1166 263b8de6 Guido Trotter
      if info:
1167 263b8de6 Guido Trotter
        data.append(info)
1168 eb58f9b1 Guido Trotter
    return data
1169 eb58f9b1 Guido Trotter
1170 55061f27 Dimitris Aragiorgis
  def _GenerateKVMBlockDevicesOptions(self, instance, block_devices,
1171 55061f27 Dimitris Aragiorgis
                                      kvmhelp, devlist):
1172 55061f27 Dimitris Aragiorgis
    """Generate KVM options regarding instance's block devices.
1173 55061f27 Dimitris Aragiorgis

1174 55061f27 Dimitris Aragiorgis
    @type instance: L{objects.Instance}
1175 55061f27 Dimitris Aragiorgis
    @param instance: the instance object
1176 55061f27 Dimitris Aragiorgis
    @type block_devices: list of tuples
1177 55061f27 Dimitris Aragiorgis
    @param block_devices: list of tuples [(disk, link_name)..]
1178 55061f27 Dimitris Aragiorgis
    @type kvmhelp: string
1179 55061f27 Dimitris Aragiorgis
    @param kvmhelp: output of kvm --help
1180 55061f27 Dimitris Aragiorgis
    @type devlist: string
1181 55061f27 Dimitris Aragiorgis
    @param devlist: output of kvm -device ?
1182 55061f27 Dimitris Aragiorgis
    @rtype: list
1183 55061f27 Dimitris Aragiorgis
    @return: list of command line options eventually used by kvm executable
1184 ec3919aa Dimitris Aragiorgis

1185 55061f27 Dimitris Aragiorgis
    """
1186 ec3919aa Dimitris Aragiorgis
    hvp = instance.hvparams
1187 55061f27 Dimitris Aragiorgis
    kernel_path = hvp[constants.HV_KERNEL_PATH]
1188 55061f27 Dimitris Aragiorgis
    if kernel_path:
1189 55061f27 Dimitris Aragiorgis
      boot_disk = False
1190 55061f27 Dimitris Aragiorgis
    else:
1191 55061f27 Dimitris Aragiorgis
      boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
1192 ec3919aa Dimitris Aragiorgis
1193 ec3919aa Dimitris Aragiorgis
    # whether this is an older KVM version that uses the boot=on flag
1194 ec3919aa Dimitris Aragiorgis
    # on devices
1195 ec3919aa Dimitris Aragiorgis
    needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1196 ec3919aa Dimitris Aragiorgis
1197 ec3919aa Dimitris Aragiorgis
    dev_opts = []
1198 68c9f726 Dimitris Aragiorgis
    device_driver = None
1199 ec3919aa Dimitris Aragiorgis
    disk_type = hvp[constants.HV_DISK_TYPE]
1200 ec3919aa Dimitris Aragiorgis
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
1201 ec3919aa Dimitris Aragiorgis
      if_val = ",if=%s" % self._VIRTIO
1202 68c9f726 Dimitris Aragiorgis
      try:
1203 68c9f726 Dimitris Aragiorgis
        if self._VIRTIO_BLK_RE.search(devlist):
1204 3e4fdd70 Dimitris Aragiorgis
          if_val = ",if=none"
1205 68c9f726 Dimitris Aragiorgis
          # will be passed in -device option as driver
1206 68c9f726 Dimitris Aragiorgis
          device_driver = self._VIRTIO_BLK_PCI
1207 68c9f726 Dimitris Aragiorgis
      except errors.HypervisorError, _:
1208 68c9f726 Dimitris Aragiorgis
        pass
1209 ec3919aa Dimitris Aragiorgis
    else:
1210 ec3919aa Dimitris Aragiorgis
      if_val = ",if=%s" % disk_type
1211 ec3919aa Dimitris Aragiorgis
    # Cache mode
1212 ec3919aa Dimitris Aragiorgis
    disk_cache = hvp[constants.HV_DISK_CACHE]
1213 ec3919aa Dimitris Aragiorgis
    if instance.disk_template in constants.DTS_EXT_MIRROR:
1214 ec3919aa Dimitris Aragiorgis
      if disk_cache != "none":
1215 ec3919aa Dimitris Aragiorgis
        # TODO: make this a hard error, instead of a silent overwrite
1216 ec3919aa Dimitris Aragiorgis
        logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
1217 ec3919aa Dimitris Aragiorgis
                        " to prevent shared storage corruption on migration",
1218 ec3919aa Dimitris Aragiorgis
                        disk_cache)
1219 ec3919aa Dimitris Aragiorgis
      cache_val = ",cache=none"
1220 ec3919aa Dimitris Aragiorgis
    elif disk_cache != constants.HT_CACHE_DEFAULT:
1221 ec3919aa Dimitris Aragiorgis
      cache_val = ",cache=%s" % disk_cache
1222 ec3919aa Dimitris Aragiorgis
    else:
1223 ec3919aa Dimitris Aragiorgis
      cache_val = ""
1224 218e4c34 Dimitris Aragiorgis
    for idx, (cfdev, dev_path) in enumerate(block_devices):
1225 ec3919aa Dimitris Aragiorgis
      if cfdev.mode != constants.DISK_RDWR:
1226 ec3919aa Dimitris Aragiorgis
        raise errors.HypervisorError("Instance has read-only disks which"
1227 ec3919aa Dimitris Aragiorgis
                                     " are not supported by KVM")
1228 ec3919aa Dimitris Aragiorgis
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
1229 ec3919aa Dimitris Aragiorgis
      boot_val = ""
1230 ec3919aa Dimitris Aragiorgis
      if boot_disk:
1231 ec3919aa Dimitris Aragiorgis
        dev_opts.extend(["-boot", "c"])
1232 ec3919aa Dimitris Aragiorgis
        boot_disk = False
1233 ec3919aa Dimitris Aragiorgis
        if needs_boot_flag and disk_type != constants.HT_DISK_IDE:
1234 ec3919aa Dimitris Aragiorgis
          boot_val = ",boot=on"
1235 819f326b Dimitris Aragiorgis
1236 819f326b Dimitris Aragiorgis
      # For ext we allow overriding disk_cache hypervisor params per disk
1237 819f326b Dimitris Aragiorgis
      disk_cache = cfdev.params.get("cache", None)
1238 819f326b Dimitris Aragiorgis
      if disk_cache:
1239 819f326b Dimitris Aragiorgis
        cache_val = ",cache=%s" % disk_cache
1240 ec3919aa Dimitris Aragiorgis
      drive_val = "file=%s,format=raw%s%s%s" % \
1241 ec3919aa Dimitris Aragiorgis
                  (dev_path, if_val, boot_val, cache_val)
1242 ec3919aa Dimitris Aragiorgis
1243 68c9f726 Dimitris Aragiorgis
      if device_driver:
1244 3e4fdd70 Dimitris Aragiorgis
        # block_devices are the 4th entry of runtime file that did not exist in
1245 3e4fdd70 Dimitris Aragiorgis
        # the past. That means that cfdev should always have pci slot and
1246 3e4fdd70 Dimitris Aragiorgis
        # _GenerateDeviceKVMId() will not raise a exception.
1247 218e4c34 Dimitris Aragiorgis
        kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_DISK,
1248 218e4c34 Dimitris Aragiorgis
                                         cfdev, idx)
1249 3e4fdd70 Dimitris Aragiorgis
        drive_val += (",id=%s" % kvm_devid)
1250 218e4c34 Dimitris Aragiorgis
        if cfdev.pci:
1251 218e4c34 Dimitris Aragiorgis
          drive_val += (",bus=0,unit=%d" % cfdev.pci)
1252 3e4fdd70 Dimitris Aragiorgis
        dev_val = ("%s,drive=%s,id=%s" %
1253 3e4fdd70 Dimitris Aragiorgis
                   (device_driver, kvm_devid, kvm_devid))
1254 218e4c34 Dimitris Aragiorgis
        if cfdev.pci:
1255 218e4c34 Dimitris Aragiorgis
          dev_val += ",bus=pci.0,addr=%s" % hex(cfdev.pci)
1256 3e4fdd70 Dimitris Aragiorgis
        dev_opts.extend(["-device", dev_val])
1257 3e4fdd70 Dimitris Aragiorgis
1258 f8b4ec36 Dimitris Aragiorgis
      # TODO: export disk geometry in IDISK_PARAMS
1259 f8b4ec36 Dimitris Aragiorgis
      heads = cfdev.params.get('heads', None)
1260 f8b4ec36 Dimitris Aragiorgis
      secs = cfdev.params.get('secs', None)
1261 f8b4ec36 Dimitris Aragiorgis
      if heads and secs:
1262 f8b4ec36 Dimitris Aragiorgis
        nr_sectors = cfdev.size * 1024 * 1024 / 512
1263 f8b4ec36 Dimitris Aragiorgis
        cyls = nr_sectors / (int(heads) * int(secs))
1264 f8b4ec36 Dimitris Aragiorgis
        if cyls and heads and secs:
1265 f8b4ec36 Dimitris Aragiorgis
          drive_val += (",cyls=%d,heads=%d,secs=%d" %
1266 f8b4ec36 Dimitris Aragiorgis
                        (cyls, int(heads), int(secs)))
1267 f8b4ec36 Dimitris Aragiorgis
1268 ec3919aa Dimitris Aragiorgis
      dev_opts.extend(["-drive", drive_val])
1269 ec3919aa Dimitris Aragiorgis
1270 ec3919aa Dimitris Aragiorgis
    return dev_opts
1271 ec3919aa Dimitris Aragiorgis
1272 b73f1c59 Guido Trotter
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused,
1273 b73f1c59 Guido Trotter
                          kvmhelp):
1274 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
1275 eb58f9b1 Guido Trotter

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

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

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

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

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

1659 38e250ba Guido Trotter
    """
1660 30e42c4e Guido Trotter
    if not serialized_runtime:
1661 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1662 8bbcbb9e Dimitris Aragiorgis
1663 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
1664 8bbcbb9e Dimitris Aragiorgis
    if len(loaded_runtime) == 3:
1665 8bbcbb9e Dimitris Aragiorgis
      serialized_blockdevs = []
1666 8bbcbb9e Dimitris Aragiorgis
      kvm_cmd, serialized_nics, hvparams = loaded_runtime
1667 8bbcbb9e Dimitris Aragiorgis
    else:
1668 8bbcbb9e Dimitris Aragiorgis
      kvm_cmd, serialized_nics, hvparams, serialized_blockdevs = loaded_runtime
1669 8bbcbb9e Dimitris Aragiorgis
1670 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
1671 8bbcbb9e Dimitris Aragiorgis
    block_devices = [(objects.Disk.FromDict(sdisk), link)
1672 8bbcbb9e Dimitris Aragiorgis
                     for sdisk, link in serialized_blockdevs]
1673 8bbcbb9e Dimitris Aragiorgis
1674 488115f3 Dimitris Aragiorgis
    # Upgrade kvm_nics and block_devices with missing uuid slot
1675 488115f3 Dimitris Aragiorgis
    # This adds a dummy uuid that will be overriden after reboot
1676 488115f3 Dimitris Aragiorgis
    # These uuids will be writen to runtime files only if
1677 488115f3 Dimitris Aragiorgis
    # a hotplug action takes place.
1678 488115f3 Dimitris Aragiorgis
    for n in kvm_nics:
1679 488115f3 Dimitris Aragiorgis
      if not n.uuid:
1680 488115f3 Dimitris Aragiorgis
        n.uuid = utils.NewUUID()
1681 488115f3 Dimitris Aragiorgis
1682 488115f3 Dimitris Aragiorgis
    for d, p in block_devices:
1683 488115f3 Dimitris Aragiorgis
      if not d.uuid:
1684 488115f3 Dimitris Aragiorgis
        d.uuid = utils.NewUUID()
1685 488115f3 Dimitris Aragiorgis
1686 8bbcbb9e Dimitris Aragiorgis
    return (kvm_cmd, kvm_nics, hvparams, block_devices)
1687 38e250ba Guido Trotter
1688 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1689 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
1690 76431533 Guido Trotter

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

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

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

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

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

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

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

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

2000 e506cce0 Dimitris Aragiorgis
    @raise errors.HypervisorError: in previous cases
2001 e506cce0 Dimitris Aragiorgis

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

2023 ad00ee21 Dimitris Aragiorgis
    Hotplug is *not* supported in case of:
2024 ad00ee21 Dimitris Aragiorgis
     - qemu versions < 1.0
2025 ad00ee21 Dimitris Aragiorgis
     - for stopped instances
2026 ad00ee21 Dimitris Aragiorgis

2027 ad00ee21 Dimitris Aragiorgis
    @raise errors.HypervisorError: in one of the previous cases
2028 ad00ee21 Dimitris Aragiorgis

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

2053 6283c5e3 Dimitris Aragiorgis
    It gets free pci slot generates the device name and invokes the
2054 6283c5e3 Dimitris Aragiorgis
    device specific method.
2055 6283c5e3 Dimitris Aragiorgis

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

2087 6283c5e3 Dimitris Aragiorgis
    It gets device info from runtime file, generates the device name and
2088 6283c5e3 Dimitris Aragiorgis
    invokes the device specific method.
2089 6283c5e3 Dimitris Aragiorgis

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

2112 6283c5e3 Dimitris Aragiorgis
    It gets device info from runtime file, generates the device name and
2113 6283c5e3 Dimitris Aragiorgis
    invokes the device specific method. Currently only NICs support hot-mod
2114 6283c5e3 Dimitris Aragiorgis

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2289 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
2290 30e42c4e Guido Trotter

2291 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2292 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
2293 30e42c4e Guido Trotter

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

2321 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
2322 30e42c4e Guido Trotter
    currently running.
2323 30e42c4e Guido Trotter

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

2331 30e42c4e Guido Trotter
    """
2332 58d38b02 Iustin Pop
    instance_name = instance.name
2333 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
2334 6a1434d7 Andrea Spadaccini
    _, _, alive = self._InstancePidAlive(instance_name)
2335 30e42c4e Guido Trotter
    if not alive:
2336 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
2337 30e42c4e Guido Trotter
2338 30e42c4e Guido Trotter
    if not live:
2339 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
2340 30e42c4e Guido Trotter
2341 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
2342 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
2343 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2344 e43d4f9f Apollon Oikonomopoulos
2345 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
2346 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
2347 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2348 e43d4f9f Apollon Oikonomopoulos
2349 061a6a1d Dimitris Aragiorgis
    # These commands are supported in latest qemu versions.
2350 061a6a1d Dimitris Aragiorgis
    # Since _CallMonitorCommand does not catch monitor errors
2351 061a6a1d Dimitris Aragiorgis
    # this does not raise an exception in case command is not supported
2352 061a6a1d Dimitris Aragiorgis
    # TODO: either parse output of command or see if the command supported
2353 061a6a1d Dimitris Aragiorgis
    # via info help (see hotplug)
2354 061a6a1d Dimitris Aragiorgis
    migrate_command = ("migrate_set_capability xbzrle on")
2355 061a6a1d Dimitris Aragiorgis
    self._CallMonitorCommand(instance_name, migrate_command)
2356 061a6a1d Dimitris Aragiorgis
2357 061a6a1d Dimitris Aragiorgis
    migrate_command = ("migrate_set_capability auto-converge on")
2358 061a6a1d Dimitris Aragiorgis
    self._CallMonitorCommand(instance_name, migrate_command)
2359 061a6a1d Dimitris Aragiorgis
2360 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
2361 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
2362 30e42c4e Guido Trotter
2363 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
2364 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
2365 6a1434d7 Andrea Spadaccini

2366 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2367 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
2368 6a1434d7 Andrea Spadaccini
    @type success: bool
2369 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
2370 6a1434d7 Andrea Spadaccini
    @type live: bool
2371 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
2372 6a1434d7 Andrea Spadaccini

2373 6a1434d7 Andrea Spadaccini
    """
2374 6a1434d7 Andrea Spadaccini
    if success:
2375 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
2376 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
2377 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
2378 6a1434d7 Andrea Spadaccini
    elif live:
2379 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
2380 6a1434d7 Andrea Spadaccini
2381 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
2382 6a1434d7 Andrea Spadaccini
    """Get the migration status
2383 6a1434d7 Andrea Spadaccini

2384 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2385 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
2386 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
2387 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
2388 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
2389 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
2390 6a1434d7 Andrea Spadaccini

2391 6a1434d7 Andrea Spadaccini
    """
2392 d0c8c01d Iustin Pop
    info_command = "info migrate"
2393 6a1434d7 Andrea Spadaccini
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
2394 6a1434d7 Andrea Spadaccini
      result = self._CallMonitorCommand(instance.name, info_command)
2395 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
2396 30e42c4e Guido Trotter
      if not match:
2397 c4e388a5 Guido Trotter
        if not result.stdout:
2398 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
2399 c4e388a5 Guido Trotter
        else:
2400 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
2401 c4e388a5 Guido Trotter
                          result.stdout)
2402 30e42c4e Guido Trotter
      else:
2403 30e42c4e Guido Trotter
        status = match.group(1)
2404 6a1434d7 Andrea Spadaccini
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
2405 6a1434d7 Andrea Spadaccini
          migration_status = objects.MigrationStatus(status=status)
2406 61643226 Andrea Spadaccini
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
2407 61643226 Andrea Spadaccini
          if match:
2408 61643226 Andrea Spadaccini
            migration_status.transferred_ram = match.group("transferred")
2409 61643226 Andrea Spadaccini
            migration_status.total_ram = match.group("total")
2410 61643226 Andrea Spadaccini
2411 6a1434d7 Andrea Spadaccini
          return migration_status
2412 30e42c4e Guido Trotter
2413 6a1434d7 Andrea Spadaccini
        logging.warning("KVM: unknown migration status '%s'", status)
2414 6a1434d7 Andrea Spadaccini
2415 6a1434d7 Andrea Spadaccini
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
2416 6a1434d7 Andrea Spadaccini
2417 62457f51 Iustin Pop
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
2418 30e42c4e Guido Trotter
2419 3d836750 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
2420 3d836750 Guido Trotter
    """Balloon an instance memory to a certain value.
2421 3d836750 Guido Trotter

2422 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
2423 3d836750 Guido Trotter
    @param instance: instance to be accepted
2424 3d836750 Guido Trotter
    @type mem: int
2425 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
2426 3d836750 Guido Trotter

2427 3d836750 Guido Trotter
    """
2428 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2429 3d836750 Guido Trotter
2430 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
2431 eb58f9b1 Guido Trotter
    """Return information about the node.
2432 eb58f9b1 Guido Trotter

2433 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
2434 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
2435 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
2436 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
2437 34fbc862 Andrea Spadaccini
          - hv_version: the hypervisor version in the form (major, minor,
2438 34fbc862 Andrea Spadaccini
                        revision)
2439 eb58f9b1 Guido Trotter

2440 eb58f9b1 Guido Trotter
    """
2441 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
2442 4b9638dc Guido Trotter
    # FIXME: this is the global kvm version, but the actual version can be
2443 4b9638dc Guido Trotter
    # customized as an hv parameter. we should use the nodegroup's default kvm
2444 4b9638dc Guido Trotter
    # path parameter here.
2445 3b59ec02 Guido Trotter
    _, v_major, v_min, v_rev = self._GetKVMVersion(constants.KVM_PATH)
2446 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2447 34fbc862 Andrea Spadaccini
    return result
2448 eb58f9b1 Guido Trotter
2449 637ce7f9 Guido Trotter
  @classmethod
2450 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
2451 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
2452 eb58f9b1 Guido Trotter

2453 eb58f9b1 Guido Trotter
    """
2454 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2455 9d9bded1 Michael Hanselmann
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2456 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2457 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2458 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
2459 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2460 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2461 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
2462 55cc0a44 Michael Hanselmann
                                     host=instance.primary_node,
2463 052783ff Michael Hanselmann
                                     user=constants.SSH_CONSOLE_USER,
2464 55cc0a44 Michael Hanselmann
                                     command=cmd)
2465 3be34f57 Guido Trotter
2466 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2467 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2468 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
2469 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2470 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
2471 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
2472 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
2473 55cc0a44 Michael Hanselmann
                                     display=display)
2474 55cc0a44 Michael Hanselmann
2475 4d2cdb5a Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2476 4d2cdb5a Andrea Spadaccini
    if spice_bind:
2477 4d2cdb5a Andrea Spadaccini
      return objects.InstanceConsole(instance=instance.name,
2478 4d2cdb5a Andrea Spadaccini
                                     kind=constants.CONS_SPICE,
2479 4d2cdb5a Andrea Spadaccini
                                     host=spice_bind,
2480 4d2cdb5a Andrea Spadaccini
                                     port=instance.network_port)
2481 4d2cdb5a Andrea Spadaccini
2482 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
2483 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
2484 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
2485 55cc0a44 Michael Hanselmann
                                            instance.name))
2486 eb58f9b1 Guido Trotter
2487 eb58f9b1 Guido Trotter
  def Verify(self):
2488 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
2489 eb58f9b1 Guido Trotter

2490 cd04dfd2 Michael Hanselmann
    Check that the required binaries exist.
2491 cd04dfd2 Michael Hanselmann

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

2494 eb58f9b1 Guido Trotter
    """
2495 1f4b9d39 Iustin Pop
    msgs = []
2496 1f4b9d39 Iustin Pop
    # FIXME: this is the global kvm binary, but the actual path can be
2497 1f4b9d39 Iustin Pop
    # customized as an hv parameter; we should use the nodegroup's
2498 1f4b9d39 Iustin Pop
    # default kvm path parameter here.
2499 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
2500 1f4b9d39 Iustin Pop
      msgs.append("The KVM binary ('%s') does not exist" % constants.KVM_PATH)
2501 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2502 1f4b9d39 Iustin Pop
      msgs.append("The socat binary ('%s') does not exist" %
2503 1f4b9d39 Iustin Pop
                  constants.SOCAT_PATH)
2504 1f4b9d39 Iustin Pop
2505 1f4b9d39 Iustin Pop
    return self._FormatVerifyResults(msgs)
2506 14aa53cb Guido Trotter
2507 6b5605e8 Iustin Pop
  @classmethod
2508 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2509 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2510 6b5605e8 Iustin Pop

2511 6b5605e8 Iustin Pop
    @type hvparams:  dict
2512 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2513 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2514 6b5605e8 Iustin Pop

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

2584 d19d94db Guido Trotter
    @type hvparams:  dict
2585 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2586 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2587 d19d94db Guido Trotter

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

2635 f5118ade Iustin Pop
    """
2636 f5118ade Iustin Pop
    cls.LinuxPowercycle()