Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 912b2278

History | View | Annotate | Download (96.5 kB)

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

24 eb58f9b1 Guido Trotter
"""
25 eb58f9b1 Guido Trotter
26 547a63b7 Balazs Lecz
import errno
27 eb58f9b1 Guido Trotter
import os
28 eb58f9b1 Guido Trotter
import os.path
29 eb58f9b1 Guido Trotter
import re
30 eb58f9b1 Guido Trotter
import tempfile
31 6567aff3 Guido Trotter
import time
32 30e42c4e Guido Trotter
import logging
33 d19d94db Guido Trotter
import pwd
34 199b2053 Apollon Oikonomopoulos
import struct
35 199b2053 Apollon Oikonomopoulos
import fcntl
36 5d9bfd87 Apollon Oikonomopoulos
import shutil
37 91c10532 Andrea Spadaccini
import socket
38 fc84cd5d Guido Trotter
import stat
39 91c10532 Andrea Spadaccini
import StringIO
40 2615646c Dimitris Aragiorgis
from bitarray import bitarray
41 b693125f Tsachy Shacham
try:
42 471a31b6 Andrea Spadaccini
  import affinity   # pylint: disable=F0401
43 b693125f Tsachy Shacham
except ImportError:
44 b693125f Tsachy Shacham
  affinity = None
45 97cd9092 Dimitris Aragiorgis
try:
46 97cd9092 Dimitris Aragiorgis
  import fdsend   # pylint: disable=F0401
47 97cd9092 Dimitris Aragiorgis
except ImportError:
48 97cd9092 Dimitris Aragiorgis
  fdsend = None
49 eb58f9b1 Guido Trotter
50 eb58f9b1 Guido Trotter
from ganeti import utils
51 eb58f9b1 Guido Trotter
from ganeti import constants
52 eb58f9b1 Guido Trotter
from ganeti import errors
53 38e250ba Guido Trotter
from ganeti import serializer
54 38e250ba Guido Trotter
from ganeti import objects
55 76431533 Guido Trotter
from ganeti import uidpool
56 76431533 Guido Trotter
from ganeti import ssconf
57 a744b676 Manuel Franceschini
from ganeti import netutils
58 9d9bded1 Michael Hanselmann
from ganeti import pathutils
59 9d9bded1 Michael Hanselmann
from ganeti.hypervisor import hv_base
60 5d9bfd87 Apollon Oikonomopoulos
from ganeti.utils import wrapper as utils_wrapper
61 eb58f9b1 Guido Trotter
62 eb58f9b1 Guido Trotter
63 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 2615646c Dimitris Aragiorgis
# Constant bitarray that reflects to a free pci slot
88 2615646c Dimitris Aragiorgis
# Use it with bitarray.search()
89 2615646c Dimitris Aragiorgis
_AVAILABLE_PCI_SLOT = bitarray("0")
90 2615646c Dimitris Aragiorgis
91 0fe22ad2 Dimitris Aragiorgis
# below constants show the format of runtime file
92 0fe22ad2 Dimitris Aragiorgis
# the nics are in second possition, while the disks in 4th (last)
93 41a878b5 Dimitris Aragiorgis
# moreover disk entries are stored as a list of in tuples
94 41a878b5 Dimitris Aragiorgis
# (L{objects.Disk}, link_name, uri)
95 0fe22ad2 Dimitris Aragiorgis
_KVM_NICS_RUNTIME_INDEX = 1
96 0fe22ad2 Dimitris Aragiorgis
_KVM_DISKS_RUNTIME_INDEX = 3
97 0fe22ad2 Dimitris Aragiorgis
_DEVICE_RUNTIME_INDEX = {
98 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK: _KVM_DISKS_RUNTIME_INDEX,
99 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC: _KVM_NICS_RUNTIME_INDEX
100 0fe22ad2 Dimitris Aragiorgis
  }
101 0fe22ad2 Dimitris Aragiorgis
_FIND_RUNTIME_ENTRY = {
102 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC:
103 0fe22ad2 Dimitris Aragiorgis
    lambda nic, kvm_nics: [n for n in kvm_nics if n.uuid == nic.uuid],
104 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK:
105 0fe22ad2 Dimitris Aragiorgis
    lambda disk, kvm_disks: [(d, l, u) for (d, l, u) in kvm_disks
106 0fe22ad2 Dimitris Aragiorgis
                             if d.uuid == disk.uuid]
107 0fe22ad2 Dimitris Aragiorgis
  }
108 0fe22ad2 Dimitris Aragiorgis
_RUNTIME_DEVICE = {
109 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC: lambda d: d,
110 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK: lambda (d, e, _): d
111 0fe22ad2 Dimitris Aragiorgis
  }
112 0fe22ad2 Dimitris Aragiorgis
_RUNTIME_ENTRY = {
113 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC: lambda d, e: d,
114 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK: lambda d, e: (d, e, None)
115 0fe22ad2 Dimitris Aragiorgis
  }
116 0fe22ad2 Dimitris Aragiorgis
117 0fe22ad2 Dimitris Aragiorgis
118 2615646c Dimitris Aragiorgis
def _GenerateDeviceKVMId(dev_type, dev):
119 2615646c Dimitris Aragiorgis
  """Helper function to generate a unique device name used by KVM
120 2615646c Dimitris Aragiorgis

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

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

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

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

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

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

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

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

181 0fe22ad2 Dimitris Aragiorgis
  """
182 0fe22ad2 Dimitris Aragiorgis
  index = _DEVICE_RUNTIME_INDEX[dev_type]
183 0fe22ad2 Dimitris Aragiorgis
  found = _FIND_RUNTIME_ENTRY[dev_type](device, runtime[index])
184 0fe22ad2 Dimitris Aragiorgis
  if not found:
185 0fe22ad2 Dimitris Aragiorgis
    raise errors.HotplugError("Cannot find runtime info for %s with UUID %s" %
186 0fe22ad2 Dimitris Aragiorgis
                              (dev_type, device.uuid))
187 0fe22ad2 Dimitris Aragiorgis
188 0fe22ad2 Dimitris Aragiorgis
  return found[0]
189 0fe22ad2 Dimitris Aragiorgis
190 0fe22ad2 Dimitris Aragiorgis
191 0fe22ad2 Dimitris Aragiorgis
def _AnalyzeSerializedRuntime(serialized_runtime):
192 0fe22ad2 Dimitris Aragiorgis
  """Return runtime entries for a serialized runtime file
193 0fe22ad2 Dimitris Aragiorgis

194 0fe22ad2 Dimitris Aragiorgis
  @type serialized_runtime: string
195 0fe22ad2 Dimitris Aragiorgis
  @param serialized_runtime: raw text data read from actual runtime file
196 0fe22ad2 Dimitris Aragiorgis
  @return: (cmd, nics, hvparams, bdevs)
197 0fe22ad2 Dimitris Aragiorgis
  @rtype: list
198 0fe22ad2 Dimitris Aragiorgis

199 0fe22ad2 Dimitris Aragiorgis
  """
200 0fe22ad2 Dimitris Aragiorgis
  loaded_runtime = serializer.Load(serialized_runtime)
201 0fe22ad2 Dimitris Aragiorgis
  if len(loaded_runtime) == 3:
202 41a878b5 Dimitris Aragiorgis
    serialized_disks = []
203 0fe22ad2 Dimitris Aragiorgis
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
204 0fe22ad2 Dimitris Aragiorgis
  else:
205 41a878b5 Dimitris Aragiorgis
    kvm_cmd, serialized_nics, hvparams, serialized_disks = loaded_runtime
206 0fe22ad2 Dimitris Aragiorgis
207 0fe22ad2 Dimitris Aragiorgis
  kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
208 41a878b5 Dimitris Aragiorgis
  kvm_disks = [(objects.Disk.FromDict(sdisk), link, uri)
209 41a878b5 Dimitris Aragiorgis
               for sdisk, link, uri in serialized_disks]
210 0fe22ad2 Dimitris Aragiorgis
211 41a878b5 Dimitris Aragiorgis
  return (kvm_cmd, kvm_nics, hvparams, kvm_disks)
212 0fe22ad2 Dimitris Aragiorgis
213 199b2053 Apollon Oikonomopoulos
214 ea2bcb82 Michael Hanselmann
def _GetTunFeatures(fd, _ioctl=fcntl.ioctl):
215 ea2bcb82 Michael Hanselmann
  """Retrieves supported TUN features from file descriptor.
216 ea2bcb82 Michael Hanselmann

217 ea2bcb82 Michael Hanselmann
  @see: L{_ProbeTapVnetHdr}
218 ea2bcb82 Michael Hanselmann

219 ea2bcb82 Michael Hanselmann
  """
220 ea2bcb82 Michael Hanselmann
  req = struct.pack("I", 0)
221 ea2bcb82 Michael Hanselmann
  try:
222 ea2bcb82 Michael Hanselmann
    buf = _ioctl(fd, TUNGETFEATURES, req)
223 ea2bcb82 Michael Hanselmann
  except EnvironmentError, err:
224 cfc24646 Iustin Pop
    logging.warning("ioctl(TUNGETFEATURES) failed: %s", err)
225 ea2bcb82 Michael Hanselmann
    return None
226 ea2bcb82 Michael Hanselmann
  else:
227 ea2bcb82 Michael Hanselmann
    (flags, ) = struct.unpack("I", buf)
228 ea2bcb82 Michael Hanselmann
    return flags
229 ea2bcb82 Michael Hanselmann
230 ea2bcb82 Michael Hanselmann
231 ea2bcb82 Michael Hanselmann
def _ProbeTapVnetHdr(fd, _features_fn=_GetTunFeatures):
232 199b2053 Apollon Oikonomopoulos
  """Check whether to enable the IFF_VNET_HDR flag.
233 199b2053 Apollon Oikonomopoulos

234 199b2053 Apollon Oikonomopoulos
  To do this, _all_ of the following conditions must be met:
235 199b2053 Apollon Oikonomopoulos
   1. TUNGETFEATURES ioctl() *must* be implemented
236 199b2053 Apollon Oikonomopoulos
   2. TUNGETFEATURES ioctl() result *must* contain the IFF_VNET_HDR flag
237 199b2053 Apollon Oikonomopoulos
   3. TUNGETIFF ioctl() *must* be implemented; reading the kernel code in
238 199b2053 Apollon Oikonomopoulos
      drivers/net/tun.c there is no way to test this until after the tap device
239 199b2053 Apollon Oikonomopoulos
      has been created using TUNSETIFF, and there is no way to change the
240 199b2053 Apollon Oikonomopoulos
      IFF_VNET_HDR flag after creating the interface, catch-22! However both
241 199b2053 Apollon Oikonomopoulos
      TUNGETIFF and TUNGETFEATURES were introduced in kernel version 2.6.27,
242 199b2053 Apollon Oikonomopoulos
      thus we can expect TUNGETIFF to be present if TUNGETFEATURES is.
243 199b2053 Apollon Oikonomopoulos

244 199b2053 Apollon Oikonomopoulos
   @type fd: int
245 199b2053 Apollon Oikonomopoulos
   @param fd: the file descriptor of /dev/net/tun
246 199b2053 Apollon Oikonomopoulos

247 199b2053 Apollon Oikonomopoulos
  """
248 ea2bcb82 Michael Hanselmann
  flags = _features_fn(fd)
249 199b2053 Apollon Oikonomopoulos
250 ea2bcb82 Michael Hanselmann
  if flags is None:
251 ea2bcb82 Michael Hanselmann
    # Not supported
252 199b2053 Apollon Oikonomopoulos
    return False
253 199b2053 Apollon Oikonomopoulos
254 ea2bcb82 Michael Hanselmann
  result = bool(flags & IFF_VNET_HDR)
255 ea2bcb82 Michael Hanselmann
256 ea2bcb82 Michael Hanselmann
  if not result:
257 ea2bcb82 Michael Hanselmann
    logging.warning("Kernel does not support IFF_VNET_HDR, not enabling")
258 ea2bcb82 Michael Hanselmann
259 ea2bcb82 Michael Hanselmann
  return result
260 ea2bcb82 Michael Hanselmann
261 199b2053 Apollon Oikonomopoulos
262 199b2053 Apollon Oikonomopoulos
def _OpenTap(vnet_hdr=True):
263 199b2053 Apollon Oikonomopoulos
  """Open a new tap device and return its file descriptor.
264 199b2053 Apollon Oikonomopoulos

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

268 199b2053 Apollon Oikonomopoulos
  @type vnet_hdr: boolean
269 199b2053 Apollon Oikonomopoulos
  @param vnet_hdr: Enable the VNET Header
270 199b2053 Apollon Oikonomopoulos
  @return: (ifname, tapfd)
271 199b2053 Apollon Oikonomopoulos
  @rtype: tuple
272 199b2053 Apollon Oikonomopoulos

273 199b2053 Apollon Oikonomopoulos
  """
274 199b2053 Apollon Oikonomopoulos
  try:
275 199b2053 Apollon Oikonomopoulos
    tapfd = os.open("/dev/net/tun", os.O_RDWR)
276 199b2053 Apollon Oikonomopoulos
  except EnvironmentError:
277 199b2053 Apollon Oikonomopoulos
    raise errors.HypervisorError("Failed to open /dev/net/tun")
278 199b2053 Apollon Oikonomopoulos
279 199b2053 Apollon Oikonomopoulos
  flags = IFF_TAP | IFF_NO_PI
280 199b2053 Apollon Oikonomopoulos
281 199b2053 Apollon Oikonomopoulos
  if vnet_hdr and _ProbeTapVnetHdr(tapfd):
282 199b2053 Apollon Oikonomopoulos
    flags |= IFF_VNET_HDR
283 199b2053 Apollon Oikonomopoulos
284 199b2053 Apollon Oikonomopoulos
  # The struct ifreq ioctl request (see netdevice(7))
285 199b2053 Apollon Oikonomopoulos
  ifr = struct.pack("16sh", "", flags)
286 199b2053 Apollon Oikonomopoulos
287 199b2053 Apollon Oikonomopoulos
  try:
288 199b2053 Apollon Oikonomopoulos
    res = fcntl.ioctl(tapfd, TUNSETIFF, ifr)
289 6f1e1921 Michael Hanselmann
  except EnvironmentError, err:
290 6f1e1921 Michael Hanselmann
    raise errors.HypervisorError("Failed to allocate a new TAP device: %s" %
291 6f1e1921 Michael Hanselmann
                                 err)
292 199b2053 Apollon Oikonomopoulos
293 199b2053 Apollon Oikonomopoulos
  # Get the interface name from the ioctl
294 199b2053 Apollon Oikonomopoulos
  ifname = struct.unpack("16sh", res)[0].strip("\x00")
295 199b2053 Apollon Oikonomopoulos
  return (ifname, tapfd)
296 199b2053 Apollon Oikonomopoulos
297 748e4b5a Michael Hanselmann
298 91c10532 Andrea Spadaccini
class QmpMessage:
299 91c10532 Andrea Spadaccini
  """QEMU Messaging Protocol (QMP) message.
300 91c10532 Andrea Spadaccini

301 91c10532 Andrea Spadaccini
  """
302 91c10532 Andrea Spadaccini
  def __init__(self, data):
303 91c10532 Andrea Spadaccini
    """Creates a new QMP message based on the passed data.
304 91c10532 Andrea Spadaccini

305 91c10532 Andrea Spadaccini
    """
306 91c10532 Andrea Spadaccini
    if not isinstance(data, dict):
307 91c10532 Andrea Spadaccini
      raise TypeError("QmpMessage must be initialized with a dict")
308 91c10532 Andrea Spadaccini
309 91c10532 Andrea Spadaccini
    self.data = data
310 91c10532 Andrea Spadaccini
311 91c10532 Andrea Spadaccini
  def __getitem__(self, field_name):
312 91c10532 Andrea Spadaccini
    """Get the value of the required field if present, or None.
313 91c10532 Andrea Spadaccini

314 91c10532 Andrea Spadaccini
    Overrides the [] operator to provide access to the message data,
315 91c10532 Andrea Spadaccini
    returning None if the required item is not in the message
316 91c10532 Andrea Spadaccini
    @return: the value of the field_name field, or None if field_name
317 91c10532 Andrea Spadaccini
             is not contained in the message
318 91c10532 Andrea Spadaccini

319 91c10532 Andrea Spadaccini
    """
320 9b87c2cf Michael Hanselmann
    return self.data.get(field_name, None)
321 91c10532 Andrea Spadaccini
322 91c10532 Andrea Spadaccini
  def __setitem__(self, field_name, field_value):
323 91c10532 Andrea Spadaccini
    """Set the value of the required field_name to field_value.
324 91c10532 Andrea Spadaccini

325 91c10532 Andrea Spadaccini
    """
326 91c10532 Andrea Spadaccini
    self.data[field_name] = field_value
327 91c10532 Andrea Spadaccini
328 5e34123e Michele Tartara
  def __len__(self):
329 5e34123e Michele Tartara
    """Return the number of fields stored in this QmpMessage.
330 5e34123e Michele Tartara

331 5e34123e Michele Tartara
    """
332 5e34123e Michele Tartara
    return len(self.data)
333 5e34123e Michele Tartara
334 5e34123e Michele Tartara
  def __delitem__(self, key):
335 5e34123e Michele Tartara
    """Delete the specified element from the QmpMessage.
336 5e34123e Michele Tartara

337 5e34123e Michele Tartara
    """
338 5e34123e Michele Tartara
    del(self.data[key])
339 5e34123e Michele Tartara
340 91c10532 Andrea Spadaccini
  @staticmethod
341 91c10532 Andrea Spadaccini
  def BuildFromJsonString(json_string):
342 91c10532 Andrea Spadaccini
    """Build a QmpMessage from a JSON encoded string.
343 91c10532 Andrea Spadaccini

344 91c10532 Andrea Spadaccini
    @type json_string: str
345 91c10532 Andrea Spadaccini
    @param json_string: JSON string representing the message
346 91c10532 Andrea Spadaccini
    @rtype: L{QmpMessage}
347 91c10532 Andrea Spadaccini
    @return: a L{QmpMessage} built from json_string
348 91c10532 Andrea Spadaccini

349 91c10532 Andrea Spadaccini
    """
350 91c10532 Andrea Spadaccini
    # Parse the string
351 91c10532 Andrea Spadaccini
    data = serializer.LoadJson(json_string)
352 91c10532 Andrea Spadaccini
    return QmpMessage(data)
353 91c10532 Andrea Spadaccini
354 91c10532 Andrea Spadaccini
  def __str__(self):
355 a182a3ed Michael Hanselmann
    # The protocol expects the JSON object to be sent as a single line.
356 a182a3ed Michael Hanselmann
    return serializer.DumpJson(self.data)
357 91c10532 Andrea Spadaccini
358 91c10532 Andrea Spadaccini
  def __eq__(self, other):
359 91c10532 Andrea Spadaccini
    # When comparing two QmpMessages, we are interested in comparing
360 91c10532 Andrea Spadaccini
    # their internal representation of the message data
361 91c10532 Andrea Spadaccini
    return self.data == other.data
362 91c10532 Andrea Spadaccini
363 91c10532 Andrea Spadaccini
364 cad837b9 Dimitris Aragiorgis
class MonitorSocket(object):
365 91c10532 Andrea Spadaccini
  _SOCKET_TIMEOUT = 5
366 91c10532 Andrea Spadaccini
367 91c10532 Andrea Spadaccini
  def __init__(self, monitor_filename):
368 cad837b9 Dimitris Aragiorgis
    """Instantiates the MonitorSocket object.
369 91c10532 Andrea Spadaccini

370 91c10532 Andrea Spadaccini
    @type monitor_filename: string
371 91c10532 Andrea Spadaccini
    @param monitor_filename: the filename of the UNIX raw socket on which the
372 cad837b9 Dimitris Aragiorgis
                             monitor (QMP or simple one) is listening
373 91c10532 Andrea Spadaccini

374 91c10532 Andrea Spadaccini
    """
375 91c10532 Andrea Spadaccini
    self.monitor_filename = monitor_filename
376 91c10532 Andrea Spadaccini
    self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
377 91c10532 Andrea Spadaccini
    # We want to fail if the server doesn't send a complete message
378 91c10532 Andrea Spadaccini
    # in a reasonable amount of time
379 91c10532 Andrea Spadaccini
    self.sock.settimeout(self._SOCKET_TIMEOUT)
380 91c10532 Andrea Spadaccini
    self._connected = False
381 91c10532 Andrea Spadaccini
382 fc84cd5d Guido Trotter
  def _check_socket(self):
383 fc84cd5d Guido Trotter
    sock_stat = None
384 fc84cd5d Guido Trotter
    try:
385 fc84cd5d Guido Trotter
      sock_stat = os.stat(self.monitor_filename)
386 fc84cd5d Guido Trotter
    except EnvironmentError, err:
387 fc84cd5d Guido Trotter
      if err.errno == errno.ENOENT:
388 cad837b9 Dimitris Aragiorgis
        raise errors.HypervisorError("No monitor socket found")
389 fc84cd5d Guido Trotter
      else:
390 cad837b9 Dimitris Aragiorgis
        raise errors.HypervisorError("Error checking monitor socket: %s",
391 fc84cd5d Guido Trotter
                                     utils.ErrnoOrStr(err))
392 fc84cd5d Guido Trotter
    if not stat.S_ISSOCK(sock_stat.st_mode):
393 cad837b9 Dimitris Aragiorgis
      raise errors.HypervisorError("Monitor socket is not a socket")
394 fc84cd5d Guido Trotter
395 91c10532 Andrea Spadaccini
  def _check_connection(self):
396 91c10532 Andrea Spadaccini
    """Make sure that the connection is established.
397 91c10532 Andrea Spadaccini

398 91c10532 Andrea Spadaccini
    """
399 91c10532 Andrea Spadaccini
    if not self._connected:
400 cad837b9 Dimitris Aragiorgis
      raise errors.ProgrammerError("To use a MonitorSocket you need to first"
401 91c10532 Andrea Spadaccini
                                   " invoke connect() on it")
402 91c10532 Andrea Spadaccini
403 91c10532 Andrea Spadaccini
  def connect(self):
404 cad837b9 Dimitris Aragiorgis
    """Connects to the monitor.
405 91c10532 Andrea Spadaccini

406 cad837b9 Dimitris Aragiorgis
    Connects to the UNIX socket
407 91c10532 Andrea Spadaccini

408 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
409 91c10532 Andrea Spadaccini

410 91c10532 Andrea Spadaccini
    """
411 fc84cd5d Guido Trotter
    if self._connected:
412 fc84cd5d Guido Trotter
      raise errors.ProgrammerError("Cannot connect twice")
413 fc84cd5d Guido Trotter
414 fc84cd5d Guido Trotter
    self._check_socket()
415 fc84cd5d Guido Trotter
416 fc84cd5d Guido Trotter
    # Check file existance/stuff
417 fc84cd5d Guido Trotter
    try:
418 fc84cd5d Guido Trotter
      self.sock.connect(self.monitor_filename)
419 fc84cd5d Guido Trotter
    except EnvironmentError:
420 fc84cd5d Guido Trotter
      raise errors.HypervisorError("Can't connect to qmp socket")
421 91c10532 Andrea Spadaccini
    self._connected = True
422 91c10532 Andrea Spadaccini
423 cad837b9 Dimitris Aragiorgis
  def close(self):
424 cad837b9 Dimitris Aragiorgis
    """Closes the socket
425 cad837b9 Dimitris Aragiorgis

426 cad837b9 Dimitris Aragiorgis
    It cannot be used after this call.
427 cad837b9 Dimitris Aragiorgis

428 cad837b9 Dimitris Aragiorgis
    """
429 cad837b9 Dimitris Aragiorgis
    self.sock.close()
430 cad837b9 Dimitris Aragiorgis
431 cad837b9 Dimitris Aragiorgis
432 cad837b9 Dimitris Aragiorgis
class QmpConnection(MonitorSocket):
433 cad837b9 Dimitris Aragiorgis
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
434 cad837b9 Dimitris Aragiorgis

435 cad837b9 Dimitris Aragiorgis
  """
436 cad837b9 Dimitris Aragiorgis
  _FIRST_MESSAGE_KEY = "QMP"
437 cad837b9 Dimitris Aragiorgis
  _EVENT_KEY = "event"
438 cad837b9 Dimitris Aragiorgis
  _ERROR_KEY = "error"
439 cad837b9 Dimitris Aragiorgis
  _RETURN_KEY = RETURN_KEY = "return"
440 cad837b9 Dimitris Aragiorgis
  _ACTUAL_KEY = ACTUAL_KEY = "actual"
441 cad837b9 Dimitris Aragiorgis
  _ERROR_CLASS_KEY = "class"
442 cad837b9 Dimitris Aragiorgis
  _ERROR_DATA_KEY = "data"
443 cad837b9 Dimitris Aragiorgis
  _ERROR_DESC_KEY = "desc"
444 cad837b9 Dimitris Aragiorgis
  _EXECUTE_KEY = "execute"
445 cad837b9 Dimitris Aragiorgis
  _ARGUMENTS_KEY = "arguments"
446 cad837b9 Dimitris Aragiorgis
  _CAPABILITIES_COMMAND = "qmp_capabilities"
447 cad837b9 Dimitris Aragiorgis
  _MESSAGE_END_TOKEN = "\r\n"
448 cad837b9 Dimitris Aragiorgis
449 cad837b9 Dimitris Aragiorgis
  def __init__(self, monitor_filename):
450 cad837b9 Dimitris Aragiorgis
    super(QmpConnection, self).__init__(monitor_filename)
451 cad837b9 Dimitris Aragiorgis
    self._buf = ""
452 cad837b9 Dimitris Aragiorgis
453 cad837b9 Dimitris Aragiorgis
  def connect(self):
454 cad837b9 Dimitris Aragiorgis
    """Connects to the QMP monitor.
455 cad837b9 Dimitris Aragiorgis

456 cad837b9 Dimitris Aragiorgis
    Connects to the UNIX socket and makes sure that we can actually send and
457 cad837b9 Dimitris Aragiorgis
    receive data to the kvm instance via QMP.
458 cad837b9 Dimitris Aragiorgis

459 cad837b9 Dimitris Aragiorgis
    @raise errors.HypervisorError: when there are communication errors
460 cad837b9 Dimitris Aragiorgis
    @raise errors.ProgrammerError: when there are data serialization errors
461 cad837b9 Dimitris Aragiorgis

462 cad837b9 Dimitris Aragiorgis
    """
463 cad837b9 Dimitris Aragiorgis
    super(QmpConnection, self).connect()
464 91c10532 Andrea Spadaccini
    # Check if we receive a correct greeting message from the server
465 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 2.2)
466 91c10532 Andrea Spadaccini
    greeting = self._Recv()
467 91c10532 Andrea Spadaccini
    if not greeting[self._FIRST_MESSAGE_KEY]:
468 91c10532 Andrea Spadaccini
      self._connected = False
469 afa9bb2e Michael Hanselmann
      raise errors.HypervisorError("kvm: QMP communication error (wrong"
470 91c10532 Andrea Spadaccini
                                   " server greeting")
471 91c10532 Andrea Spadaccini
472 91c10532 Andrea Spadaccini
    # Let's put the monitor in command mode using the qmp_capabilities
473 91c10532 Andrea Spadaccini
    # command, or else no command will be executable.
474 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 4)
475 91c10532 Andrea Spadaccini
    self.Execute(self._CAPABILITIES_COMMAND)
476 91c10532 Andrea Spadaccini
477 91c10532 Andrea Spadaccini
  def _ParseMessage(self, buf):
478 91c10532 Andrea Spadaccini
    """Extract and parse a QMP message from the given buffer.
479 91c10532 Andrea Spadaccini

480 91c10532 Andrea Spadaccini
    Seeks for a QMP message in the given buf. If found, it parses it and
481 91c10532 Andrea Spadaccini
    returns it together with the rest of the characters in the buf.
482 91c10532 Andrea Spadaccini
    If no message is found, returns None and the whole buffer.
483 91c10532 Andrea Spadaccini

484 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
485 91c10532 Andrea Spadaccini

486 91c10532 Andrea Spadaccini
    """
487 91c10532 Andrea Spadaccini
    message = None
488 91c10532 Andrea Spadaccini
    # Check if we got the message end token (CRLF, as per the QEMU Protocol
489 91c10532 Andrea Spadaccini
    # Specification 0.1 - Section 2.1.1)
490 91c10532 Andrea Spadaccini
    pos = buf.find(self._MESSAGE_END_TOKEN)
491 91c10532 Andrea Spadaccini
    if pos >= 0:
492 91c10532 Andrea Spadaccini
      try:
493 91c10532 Andrea Spadaccini
        message = QmpMessage.BuildFromJsonString(buf[:pos + 1])
494 91c10532 Andrea Spadaccini
      except Exception, err:
495 91c10532 Andrea Spadaccini
        raise errors.ProgrammerError("QMP data serialization error: %s" % err)
496 91c10532 Andrea Spadaccini
      buf = buf[pos + 1:]
497 91c10532 Andrea Spadaccini
498 91c10532 Andrea Spadaccini
    return (message, buf)
499 91c10532 Andrea Spadaccini
500 91c10532 Andrea Spadaccini
  def _Recv(self):
501 91c10532 Andrea Spadaccini
    """Receives a message from QMP and decodes the received JSON object.
502 91c10532 Andrea Spadaccini

503 91c10532 Andrea Spadaccini
    @rtype: QmpMessage
504 91c10532 Andrea Spadaccini
    @return: the received message
505 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
506 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
507 91c10532 Andrea Spadaccini

508 91c10532 Andrea Spadaccini
    """
509 91c10532 Andrea Spadaccini
    self._check_connection()
510 91c10532 Andrea Spadaccini
511 91c10532 Andrea Spadaccini
    # Check if there is already a message in the buffer
512 91c10532 Andrea Spadaccini
    (message, self._buf) = self._ParseMessage(self._buf)
513 91c10532 Andrea Spadaccini
    if message:
514 91c10532 Andrea Spadaccini
      return message
515 91c10532 Andrea Spadaccini
516 91c10532 Andrea Spadaccini
    recv_buffer = StringIO.StringIO(self._buf)
517 91c10532 Andrea Spadaccini
    recv_buffer.seek(len(self._buf))
518 91c10532 Andrea Spadaccini
    try:
519 91c10532 Andrea Spadaccini
      while True:
520 91c10532 Andrea Spadaccini
        data = self.sock.recv(4096)
521 91c10532 Andrea Spadaccini
        if not data:
522 91c10532 Andrea Spadaccini
          break
523 91c10532 Andrea Spadaccini
        recv_buffer.write(data)
524 91c10532 Andrea Spadaccini
525 91c10532 Andrea Spadaccini
        (message, self._buf) = self._ParseMessage(recv_buffer.getvalue())
526 91c10532 Andrea Spadaccini
        if message:
527 91c10532 Andrea Spadaccini
          return message
528 91c10532 Andrea Spadaccini
529 91c10532 Andrea Spadaccini
    except socket.timeout, err:
530 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while receiving a QMP message: "
531 91c10532 Andrea Spadaccini
                                   "%s" % (err))
532 91c10532 Andrea Spadaccini
    except socket.error, err:
533 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to receive data from KVM using the"
534 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
535 91c10532 Andrea Spadaccini
536 91c10532 Andrea Spadaccini
  def _Send(self, message):
537 91c10532 Andrea Spadaccini
    """Encodes and sends a message to KVM using QMP.
538 91c10532 Andrea Spadaccini

539 91c10532 Andrea Spadaccini
    @type message: QmpMessage
540 91c10532 Andrea Spadaccini
    @param message: message to send to KVM
541 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
542 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
543 91c10532 Andrea Spadaccini

544 91c10532 Andrea Spadaccini
    """
545 91c10532 Andrea Spadaccini
    self._check_connection()
546 91c10532 Andrea Spadaccini
    try:
547 91c10532 Andrea Spadaccini
      message_str = str(message)
548 91c10532 Andrea Spadaccini
    except Exception, err:
549 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("QMP data deserialization error: %s" % err)
550 91c10532 Andrea Spadaccini
551 91c10532 Andrea Spadaccini
    try:
552 91c10532 Andrea Spadaccini
      self.sock.sendall(message_str)
553 91c10532 Andrea Spadaccini
    except socket.timeout, err:
554 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while sending a QMP message: "
555 91c10532 Andrea Spadaccini
                                   "%s (%s)" % (err.string, err.errno))
556 91c10532 Andrea Spadaccini
    except socket.error, err:
557 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to send data from KVM using the"
558 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
559 91c10532 Andrea Spadaccini
560 91c10532 Andrea Spadaccini
  def Execute(self, command, arguments=None):
561 91c10532 Andrea Spadaccini
    """Executes a QMP command and returns the response of the server.
562 91c10532 Andrea Spadaccini

563 91c10532 Andrea Spadaccini
    @type command: str
564 91c10532 Andrea Spadaccini
    @param command: the command to execute
565 91c10532 Andrea Spadaccini
    @type arguments: dict
566 91c10532 Andrea Spadaccini
    @param arguments: dictionary of arguments to be passed to the command
567 91c10532 Andrea Spadaccini
    @rtype: dict
568 91c10532 Andrea Spadaccini
    @return: dictionary representing the received JSON object
569 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
570 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
571 91c10532 Andrea Spadaccini

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

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

780 98ec75d6 Iustin Pop
    """
781 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
782 98ec75d6 Iustin Pop
783 263b8de6 Guido Trotter
  @classmethod
784 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
785 7548396c Guido Trotter
    """Returns the instance uidfile.
786 7548396c Guido Trotter

787 7548396c Guido Trotter
    """
788 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
789 7548396c Guido Trotter
790 7548396c Guido Trotter
  @classmethod
791 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
792 263b8de6 Guido Trotter
    """Check pid file for instance information.
793 263b8de6 Guido Trotter

794 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
795 263b8de6 Guido Trotter
    information from its command line.
796 263b8de6 Guido Trotter

797 263b8de6 Guido Trotter
    @type pid: string or int
798 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
799 263b8de6 Guido Trotter
    @rtype: tuple
800 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
801 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
802 263b8de6 Guido Trotter

803 263b8de6 Guido Trotter
    """
804 263b8de6 Guido Trotter
    alive = utils.IsProcessAlive(pid)
805 263b8de6 Guido Trotter
    if not alive:
806 263b8de6 Guido Trotter
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
807 263b8de6 Guido Trotter
808 263b8de6 Guido Trotter
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
809 263b8de6 Guido Trotter
    try:
810 263b8de6 Guido Trotter
      cmdline = utils.ReadFile(cmdline_file)
811 263b8de6 Guido Trotter
    except EnvironmentError, err:
812 263b8de6 Guido Trotter
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
813 263b8de6 Guido Trotter
                                   (pid, err))
814 263b8de6 Guido Trotter
815 263b8de6 Guido Trotter
    instance = None
816 263b8de6 Guido Trotter
    memory = 0
817 263b8de6 Guido Trotter
    vcpus = 0
818 263b8de6 Guido Trotter
819 d0c8c01d Iustin Pop
    arg_list = cmdline.split("\x00")
820 263b8de6 Guido Trotter
    while arg_list:
821 e687ec01 Michael Hanselmann
      arg = arg_list.pop(0)
822 263b8de6 Guido Trotter
      if arg == "-name":
823 263b8de6 Guido Trotter
        instance = arg_list.pop(0)
824 263b8de6 Guido Trotter
      elif arg == "-m":
825 263b8de6 Guido Trotter
        memory = int(arg_list.pop(0))
826 263b8de6 Guido Trotter
      elif arg == "-smp":
827 4888a609 Guido Trotter
        vcpus = int(arg_list.pop(0).split(",")[0])
828 263b8de6 Guido Trotter
829 263b8de6 Guido Trotter
    if instance is None:
830 263b8de6 Guido Trotter
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
831 263b8de6 Guido Trotter
                                   " instance" % pid)
832 263b8de6 Guido Trotter
833 263b8de6 Guido Trotter
    return (instance, memory, vcpus)
834 263b8de6 Guido Trotter
835 70f25a49 Jose A. Lopes
  @classmethod
836 70f25a49 Jose A. Lopes
  def _InstancePidAlive(cls, instance_name):
837 263b8de6 Guido Trotter
    """Returns the instance pidfile, pid, and liveness.
838 263b8de6 Guido Trotter

839 263b8de6 Guido Trotter
    @type instance_name: string
840 263b8de6 Guido Trotter
    @param instance_name: instance name
841 263b8de6 Guido Trotter
    @rtype: tuple
842 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
843 1f8b3a27 Guido Trotter

844 1f8b3a27 Guido Trotter
    """
845 70f25a49 Jose A. Lopes
    pidfile = cls._InstancePidFile(instance_name)
846 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
847 263b8de6 Guido Trotter
848 263b8de6 Guido Trotter
    alive = False
849 263b8de6 Guido Trotter
    try:
850 70f25a49 Jose A. Lopes
      cmd_instance = cls._InstancePidInfo(pid)[0]
851 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
852 263b8de6 Guido Trotter
    except errors.HypervisorError:
853 263b8de6 Guido Trotter
      pass
854 1f8b3a27 Guido Trotter
855 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
856 1f8b3a27 Guido Trotter
857 70f25a49 Jose A. Lopes
  @classmethod
858 70f25a49 Jose A. Lopes
  def _CheckDown(cls, instance_name):
859 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
860 5905901c Iustin Pop

861 5905901c Iustin Pop
    """
862 70f25a49 Jose A. Lopes
    alive = cls._InstancePidAlive(instance_name)[2]
863 5905901c Iustin Pop
    if alive:
864 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
865 5905901c Iustin Pop
                                   (instance_name, "already running"))
866 5905901c Iustin Pop
867 0df4d98a Guido Trotter
  @classmethod
868 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
869 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
870 c4fbefc8 Guido Trotter

871 c4fbefc8 Guido Trotter
    """
872 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
873 c4fbefc8 Guido Trotter
874 0df4d98a Guido Trotter
  @classmethod
875 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
876 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
877 c4fbefc8 Guido Trotter

878 c4fbefc8 Guido Trotter
    """
879 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
880 c4fbefc8 Guido Trotter
881 91c10532 Andrea Spadaccini
  @classmethod
882 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
883 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
884 91c10532 Andrea Spadaccini

885 91c10532 Andrea Spadaccini
    """
886 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
887 91c10532 Andrea Spadaccini
888 86d6bc2a Guido Trotter
  @staticmethod
889 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
890 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
891 86d6bc2a Guido Trotter

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

894 86d6bc2a Guido Trotter
    """
895 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
896 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
897 86d6bc2a Guido Trotter
    else:
898 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
899 86d6bc2a Guido Trotter
900 0df4d98a Guido Trotter
  @classmethod
901 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
902 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
903 38e250ba Guido Trotter

904 38e250ba Guido Trotter
    """
905 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
906 38e250ba Guido Trotter
907 7e66c35b Guido Trotter
  @classmethod
908 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
909 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
910 547a63b7 Balazs Lecz

911 547a63b7 Balazs Lecz
    """
912 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
913 547a63b7 Balazs Lecz
914 547a63b7 Balazs Lecz
  @classmethod
915 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
916 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
917 5d9bfd87 Apollon Oikonomopoulos
    given instance.
918 5d9bfd87 Apollon Oikonomopoulos

919 5d9bfd87 Apollon Oikonomopoulos
    """
920 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
921 5d9bfd87 Apollon Oikonomopoulos
922 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
923 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
924 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
925 5d9bfd87 Apollon Oikonomopoulos

926 5d9bfd87 Apollon Oikonomopoulos
    """
927 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
928 5d9bfd87 Apollon Oikonomopoulos
929 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
930 4f580fef Sรฉbastien Bocahu
  def _InstanceKeymapFile(cls, instance_name):
931 4f580fef Sรฉbastien Bocahu
    """Returns the name of the file containing the keymap for a given instance
932 4f580fef Sรฉbastien Bocahu

933 4f580fef Sรฉbastien Bocahu
    """
934 4f580fef Sรฉbastien Bocahu
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
935 4f580fef Sรฉbastien Bocahu
936 4f580fef Sรฉbastien Bocahu
  @classmethod
937 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
938 7548396c Guido Trotter
    """Try to read a uid file
939 7548396c Guido Trotter

940 7548396c Guido Trotter
    """
941 7548396c Guido Trotter
    if os.path.exists(uid_file):
942 7548396c Guido Trotter
      try:
943 682f7601 Guido Trotter
        uid = int(utils.ReadOneLineFile(uid_file))
944 aa0b600b Guido Trotter
        return uid
945 7548396c Guido Trotter
      except EnvironmentError:
946 7548396c Guido Trotter
        logging.warning("Can't read uid file", exc_info=True)
947 7548396c Guido Trotter
      except (TypeError, ValueError):
948 7548396c Guido Trotter
        logging.warning("Can't parse uid file contents", exc_info=True)
949 aa0b600b Guido Trotter
    return None
950 7548396c Guido Trotter
951 7548396c Guido Trotter
  @classmethod
952 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
953 547a63b7 Balazs Lecz
    """Removes an instance's rutime sockets/files/dirs.
954 7e66c35b Guido Trotter

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

995 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
996 eb58f9b1 Guido Trotter
    @type instance: instance object
997 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
998 eb58f9b1 Guido Trotter
    @type seq: int
999 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
1000 eb58f9b1 Guido Trotter
    @type nic: nic object
1001 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
1002 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
1003 eb58f9b1 Guido Trotter

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

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

1053 b693125f Tsachy Shacham
    @type cpu_list: list of int
1054 b693125f Tsachy Shacham
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
1055 b693125f Tsachy Shacham
    @rtype: int
1056 b693125f Tsachy Shacham
    @return: a bit mask of CPU affinities
1057 b693125f Tsachy Shacham

1058 b693125f Tsachy Shacham
    """
1059 b693125f Tsachy Shacham
    if cpu_list == constants.CPU_PINNING_OFF:
1060 b693125f Tsachy Shacham
      return constants.CPU_PINNING_ALL_KVM
1061 b693125f Tsachy Shacham
    else:
1062 b693125f Tsachy Shacham
      return sum(2 ** cpu for cpu in cpu_list)
1063 b693125f Tsachy Shacham
1064 b693125f Tsachy Shacham
  @classmethod
1065 b693125f Tsachy Shacham
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
1066 b693125f Tsachy Shacham
    """Change CPU affinity for running VM according to given CPU mask.
1067 b693125f Tsachy Shacham

1068 b693125f Tsachy Shacham
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
1069 b693125f Tsachy Shacham
    @type cpu_mask: string
1070 b693125f Tsachy Shacham
    @param process_id: process ID of KVM process. Used to pin entire VM
1071 b693125f Tsachy Shacham
                       to physical CPUs.
1072 b693125f Tsachy Shacham
    @type process_id: int
1073 b693125f Tsachy Shacham
    @param thread_dict: map of virtual CPUs to KVM thread IDs
1074 b693125f Tsachy Shacham
    @type thread_dict: dict int:int
1075 b693125f Tsachy Shacham

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

1106 b693125f Tsachy Shacham
    @type instance_name: string
1107 b693125f Tsachy Shacham
    @param instance_name: instance in question
1108 b693125f Tsachy Shacham
    @rtype: dictionary of int:int
1109 b693125f Tsachy Shacham
    @return: a dictionary mapping vCPU numbers to thread IDs
1110 b693125f Tsachy Shacham

1111 b693125f Tsachy Shacham
    """
1112 b693125f Tsachy Shacham
    result = {}
1113 b693125f Tsachy Shacham
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
1114 b693125f Tsachy Shacham
    for line in output.stdout.splitlines():
1115 b693125f Tsachy Shacham
      match = self._CPU_INFO_RE.search(line)
1116 b693125f Tsachy Shacham
      if not match:
1117 b693125f Tsachy Shacham
        continue
1118 b693125f Tsachy Shacham
      grp = map(int, match.groups())
1119 b693125f Tsachy Shacham
      result[grp[0]] = grp[1]
1120 b693125f Tsachy Shacham
1121 b693125f Tsachy Shacham
    return result
1122 b693125f Tsachy Shacham
1123 1d8a7812 Andrea Spadaccini
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
1124 1d8a7812 Andrea Spadaccini
    """Complete CPU pinning.
1125 b693125f Tsachy Shacham

1126 b693125f Tsachy Shacham
    @type instance_name: string
1127 b693125f Tsachy Shacham
    @param instance_name: name of instance
1128 b693125f Tsachy Shacham
    @type cpu_mask: string
1129 b693125f Tsachy Shacham
    @param cpu_mask: CPU pinning mask as entered by user
1130 b693125f Tsachy Shacham

1131 b693125f Tsachy Shacham
    """
1132 1d8a7812 Andrea Spadaccini
    # Get KVM process ID, to be used if need to pin entire VM
1133 1d8a7812 Andrea Spadaccini
    _, pid, _ = self._InstancePidAlive(instance_name)
1134 1d8a7812 Andrea Spadaccini
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
1135 1d8a7812 Andrea Spadaccini
    thread_dict = self._GetVcpuThreadIds(instance_name)
1136 1d8a7812 Andrea Spadaccini
    # Run CPU pinning, based on configured mask
1137 1d8a7812 Andrea Spadaccini
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
1138 b693125f Tsachy Shacham
1139 58e356a9 Helga Velroyen
  def ListInstances(self, hvparams=None):
1140 eb58f9b1 Guido Trotter
    """Get the list of running instances.
1141 eb58f9b1 Guido Trotter

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

1145 eb58f9b1 Guido Trotter
    """
1146 eb58f9b1 Guido Trotter
    result = []
1147 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1148 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
1149 eb58f9b1 Guido Trotter
        result.append(name)
1150 eb58f9b1 Guido Trotter
    return result
1151 eb58f9b1 Guido Trotter
1152 0bbec3af Helga Velroyen
  def GetInstanceInfo(self, instance_name, hvparams=None):
1153 eb58f9b1 Guido Trotter
    """Get instance properties.
1154 eb58f9b1 Guido Trotter

1155 4fbb3c60 Guido Trotter
    @type instance_name: string
1156 c41eea6e Iustin Pop
    @param instance_name: the instance name
1157 0bbec3af Helga Velroyen
    @type hvparams: dict of strings
1158 0bbec3af Helga Velroyen
    @param hvparams: hvparams to be used with this instance
1159 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
1160 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
1161 eb58f9b1 Guido Trotter

1162 eb58f9b1 Guido Trotter
    """
1163 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
1164 1f8b3a27 Guido Trotter
    if not alive:
1165 eb58f9b1 Guido Trotter
      return None
1166 eb58f9b1 Guido Trotter
1167 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
1168 a3f0f306 Jose A. Lopes
    istat = hv_base.HvInstanceState.RUNNING
1169 697e573c Hrvoje Ribicic
    times = 0
1170 eb58f9b1 Guido Trotter
1171 89da2ff3 Guido Trotter
    try:
1172 89da2ff3 Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
1173 89da2ff3 Guido Trotter
      qmp.connect()
1174 89da2ff3 Guido Trotter
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
1175 89da2ff3 Guido Trotter
      # Will fail if ballooning is not enabled, but we can then just resort to
1176 89da2ff3 Guido Trotter
      # the value above.
1177 89da2ff3 Guido Trotter
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
1178 89da2ff3 Guido Trotter
      memory = mem_bytes / 1048576
1179 89da2ff3 Guido Trotter
    except errors.HypervisorError:
1180 89da2ff3 Guido Trotter
      pass
1181 89da2ff3 Guido Trotter
1182 fc84cd5d Guido Trotter
    return (instance_name, pid, memory, vcpus, istat, times)
1183 eb58f9b1 Guido Trotter
1184 0200a1af Helga Velroyen
  def GetAllInstancesInfo(self, hvparams=None):
1185 eb58f9b1 Guido Trotter
    """Get properties of all instances.
1186 eb58f9b1 Guido Trotter

1187 0200a1af Helga Velroyen
    @type hvparams: dict of strings
1188 0200a1af Helga Velroyen
    @param hvparams: hypervisor parameter
1189 c41eea6e Iustin Pop
    @return: list of tuples (name, id, memory, vcpus, stat, times)
1190 c41eea6e Iustin Pop

1191 eb58f9b1 Guido Trotter
    """
1192 eb58f9b1 Guido Trotter
    data = []
1193 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1194 263b8de6 Guido Trotter
      try:
1195 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
1196 263b8de6 Guido Trotter
      except errors.HypervisorError:
1197 3bc145d8 Bernardo Dal Seno
        # Ignore exceptions due to instances being shut down
1198 263b8de6 Guido Trotter
        continue
1199 263b8de6 Guido Trotter
      if info:
1200 263b8de6 Guido Trotter
        data.append(info)
1201 eb58f9b1 Guido Trotter
    return data
1202 eb58f9b1 Guido Trotter
1203 41a878b5 Dimitris Aragiorgis
  def _GenerateKVMBlockDevicesOptions(self, instance, kvm_disks,
1204 43c6e76f Dimitris Aragiorgis
                                      kvmhelp, devlist):
1205 43c6e76f Dimitris Aragiorgis
    """Generate KVM options regarding instance's block devices.
1206 43c6e76f Dimitris Aragiorgis

1207 43c6e76f Dimitris Aragiorgis
    @type instance: L{objects.Instance}
1208 43c6e76f Dimitris Aragiorgis
    @param instance: the instance object
1209 41a878b5 Dimitris Aragiorgis
    @type kvm_disks: list of tuples
1210 41a878b5 Dimitris Aragiorgis
    @param kvm_disks: list of tuples [(disk, link_name, uri)..]
1211 43c6e76f Dimitris Aragiorgis
    @type kvmhelp: string
1212 43c6e76f Dimitris Aragiorgis
    @param kvmhelp: output of kvm --help
1213 43c6e76f Dimitris Aragiorgis
    @type devlist: string
1214 43c6e76f Dimitris Aragiorgis
    @param devlist: output of kvm -device ?
1215 43c6e76f Dimitris Aragiorgis
    @rtype: list
1216 43c6e76f Dimitris Aragiorgis
    @return: list of command line options eventually used by kvm executable
1217 af5db30c Dimitris Aragiorgis

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

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

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

1661 38e250ba Guido Trotter
    """
1662 38e250ba Guido Trotter
    try:
1663 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1664 38e250ba Guido Trotter
                      data=data)
1665 90c024f6 Guido Trotter
    except EnvironmentError, err:
1666 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1667 38e250ba Guido Trotter
1668 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
1669 38e250ba Guido Trotter
    """Read an instance's KVM runtime
1670 38e250ba Guido Trotter

1671 38e250ba Guido Trotter
    """
1672 38e250ba Guido Trotter
    try:
1673 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1674 90c024f6 Guido Trotter
    except EnvironmentError, err:
1675 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1676 38e250ba Guido Trotter
    return file_content
1677 38e250ba Guido Trotter
1678 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1679 38e250ba Guido Trotter
    """Save an instance's KVM runtime
1680 38e250ba Guido Trotter

1681 38e250ba Guido Trotter
    """
1682 41a878b5 Dimitris Aragiorgis
    kvm_cmd, kvm_nics, hvparams, kvm_disks = kvm_runtime
1683 0fe22ad2 Dimitris Aragiorgis
1684 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1685 41a878b5 Dimitris Aragiorgis
    serialized_disks = [(blk.ToDict(), link, uri)
1686 41a878b5 Dimitris Aragiorgis
                        for blk, link, uri in kvm_disks]
1687 0fe22ad2 Dimitris Aragiorgis
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams,
1688 41a878b5 Dimitris Aragiorgis
                                      serialized_disks))
1689 0fe22ad2 Dimitris Aragiorgis
1690 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
1691 38e250ba Guido Trotter
1692 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1693 38e250ba Guido Trotter
    """Load an instance's KVM runtime
1694 38e250ba Guido Trotter

1695 38e250ba Guido Trotter
    """
1696 30e42c4e Guido Trotter
    if not serialized_runtime:
1697 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1698 0fe22ad2 Dimitris Aragiorgis
1699 0fe22ad2 Dimitris Aragiorgis
    return _AnalyzeSerializedRuntime(serialized_runtime)
1700 38e250ba Guido Trotter
1701 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1702 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
1703 76431533 Guido Trotter

1704 76431533 Guido Trotter
    @type name: string
1705 76431533 Guido Trotter
    @param name: instance name
1706 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1707 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1708 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1709 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1710 76431533 Guido Trotter

1711 76431533 Guido Trotter
    """
1712 5d9bfd87 Apollon Oikonomopoulos
    try:
1713 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1714 5d9bfd87 Apollon Oikonomopoulos
    finally:
1715 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
1716 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
1717 5d9bfd87 Apollon Oikonomopoulos
1718 76431533 Guido Trotter
    if result.failed:
1719 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1720 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
1721 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
1722 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
1723 76431533 Guido Trotter
1724 41a878b5 Dimitris Aragiorgis
  # too many local variables
1725 0fe22ad2 Dimitris Aragiorgis
  # pylint: disable=R0914
1726 b73f1c59 Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1727 839642c2 Iustin Pop
    """Execute a KVM cmd, after completing it with some last minute data.
1728 ee5f20b0 Guido Trotter

1729 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1730 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1731 b73f1c59 Guido Trotter
    @type kvmhelp: string
1732 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1733 30e42c4e Guido Trotter

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

1952 ee5f20b0 Guido Trotter
    """
1953 5905901c Iustin Pop
    self._CheckDown(instance.name)
1954 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1955 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1956 7238edb5 Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1957 b73f1c59 Guido Trotter
                                           startup_paused, kvmhelp)
1958 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1959 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1960 ee5f20b0 Guido Trotter
1961 70f25a49 Jose A. Lopes
  @classmethod
1962 70f25a49 Jose A. Lopes
  def _CallMonitorCommand(cls, instance_name, command):
1963 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
1964 6567aff3 Guido Trotter

1965 6567aff3 Guido Trotter
    """
1966 eace6157 Michael Hanselmann
    # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
1967 eace6157 Michael Hanselmann
    # version. The monitor protocol is designed for human consumption, whereas
1968 eace6157 Michael Hanselmann
    # QMP is made for programmatic usage. In the worst case QMP can also
1969 eace6157 Michael Hanselmann
    # execute monitor commands. As it is, all calls to socat take at least
1970 eace6157 Michael Hanselmann
    # 500ms and likely more: socat can't detect the end of the reply and waits
1971 eace6157 Michael Hanselmann
    # for 500ms of no data received before exiting (500 ms is the default for
1972 eace6157 Michael Hanselmann
    # the "-t" parameter).
1973 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1974 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
1975 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
1976 70f25a49 Jose A. Lopes
              utils.ShellQuote(cls._InstanceMonitor(instance_name))))
1977 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
1978 6567aff3 Guido Trotter
    if result.failed:
1979 afa9bb2e Michael Hanselmann
      msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
1980 afa9bb2e Michael Hanselmann
             " output: %s" %
1981 afa9bb2e Michael Hanselmann
             (command, instance_name, result.fail_reason, result.output))
1982 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
1983 6567aff3 Guido Trotter
1984 6567aff3 Guido Trotter
    return result
1985 6567aff3 Guido Trotter
1986 2615646c Dimitris Aragiorgis
  def _GetFreePCISlot(self, instance, dev):
1987 2615646c Dimitris Aragiorgis
    """Get the first available pci slot of a runnung instance.
1988 2615646c Dimitris Aragiorgis

1989 2615646c Dimitris Aragiorgis
    """
1990 2615646c Dimitris Aragiorgis
    slots = bitarray(32)
1991 2615646c Dimitris Aragiorgis
    slots.setall(False) # pylint: disable=E1101
1992 2615646c Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance.name, self._INFO_PCI_CMD)
1993 2615646c Dimitris Aragiorgis
    for line in output.stdout.splitlines():
1994 2615646c Dimitris Aragiorgis
      match = self._INFO_PCI_RE.search(line)
1995 2615646c Dimitris Aragiorgis
      if match:
1996 2615646c Dimitris Aragiorgis
        slot = int(match.group(1))
1997 2615646c Dimitris Aragiorgis
        slots[slot] = True
1998 2615646c Dimitris Aragiorgis
1999 2615646c Dimitris Aragiorgis
    [free] = slots.search(_AVAILABLE_PCI_SLOT, 1) # pylint: disable=E1101
2000 2615646c Dimitris Aragiorgis
    if not free:
2001 2615646c Dimitris Aragiorgis
      raise errors.HypervisorError("All PCI slots occupied")
2002 2615646c Dimitris Aragiorgis
2003 2615646c Dimitris Aragiorgis
    dev.pci = int(free)
2004 2615646c Dimitris Aragiorgis
2005 50e0f1d9 Dimitris Aragiorgis
  def VerifyHotplugSupport(self, instance, action, dev_type):
2006 50e0f1d9 Dimitris Aragiorgis
    """Verifies that hotplug is supported.
2007 97cd9092 Dimitris Aragiorgis

2008 97cd9092 Dimitris Aragiorgis
    Hotplug is *not* supported in case of:
2009 97cd9092 Dimitris Aragiorgis
     - security models and chroot (disk hotplug)
2010 97cd9092 Dimitris Aragiorgis
     - fdsend module is missing (nic hot-add)
2011 97cd9092 Dimitris Aragiorgis

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

2014 97cd9092 Dimitris Aragiorgis
    """
2015 97cd9092 Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2016 97cd9092 Dimitris Aragiorgis
      hvp = instance.hvparams
2017 97cd9092 Dimitris Aragiorgis
      security_model = hvp[constants.HV_SECURITY_MODEL]
2018 97cd9092 Dimitris Aragiorgis
      use_chroot = hvp[constants.HV_KVM_USE_CHROOT]
2019 97cd9092 Dimitris Aragiorgis
      if use_chroot:
2020 97cd9092 Dimitris Aragiorgis
        raise errors.HotplugError("Disk hotplug is not supported"
2021 97cd9092 Dimitris Aragiorgis
                                  " in case of chroot.")
2022 97cd9092 Dimitris Aragiorgis
      if security_model != constants.HT_SM_NONE:
2023 97cd9092 Dimitris Aragiorgis
        raise errors.HotplugError("Disk Hotplug is not supported in case"
2024 97cd9092 Dimitris Aragiorgis
                                  " security models are used.")
2025 97cd9092 Dimitris Aragiorgis
2026 97cd9092 Dimitris Aragiorgis
    if (dev_type == constants.HOTPLUG_TARGET_NIC and
2027 97cd9092 Dimitris Aragiorgis
        action == constants.HOTPLUG_ACTION_ADD and not fdsend):
2028 97cd9092 Dimitris Aragiorgis
      raise errors.HotplugError("Cannot hot-add NIC."
2029 97cd9092 Dimitris Aragiorgis
                                " fdsend python module is missing.")
2030 97cd9092 Dimitris Aragiorgis
2031 24711492 Dimitris Aragiorgis
  def HotplugSupported(self, instance):
2032 24711492 Dimitris Aragiorgis
    """Checks if hotplug is generally supported.
2033 24711492 Dimitris Aragiorgis

2034 24711492 Dimitris Aragiorgis
    Hotplug is *not* supported in case of:
2035 24711492 Dimitris Aragiorgis
     - qemu versions < 1.0
2036 24711492 Dimitris Aragiorgis
     - for stopped instances
2037 24711492 Dimitris Aragiorgis

2038 24711492 Dimitris Aragiorgis
    @raise errors.HypervisorError: in one of the previous cases
2039 24711492 Dimitris Aragiorgis

2040 24711492 Dimitris Aragiorgis
    """
2041 24711492 Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD)
2042 24711492 Dimitris Aragiorgis
    # TODO: search for netdev_add, drive_add, device_add.....
2043 24711492 Dimitris Aragiorgis
    match = self._INFO_VERSION_RE.search(output.stdout)
2044 24711492 Dimitris Aragiorgis
    if not match:
2045 24711492 Dimitris Aragiorgis
      raise errors.HotplugError("Try hotplug only in running instances.")
2046 24711492 Dimitris Aragiorgis
    v_major, v_min, _, _ = match.groups()
2047 24711492 Dimitris Aragiorgis
    if (int(v_major), int(v_min)) < (1, 0):
2048 24711492 Dimitris Aragiorgis
      raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0")
2049 24711492 Dimitris Aragiorgis
2050 97cd9092 Dimitris Aragiorgis
  def _CallHotplugCommand(self, name, cmd):
2051 97cd9092 Dimitris Aragiorgis
    output = self._CallMonitorCommand(name, cmd)
2052 97cd9092 Dimitris Aragiorgis
    # TODO: parse output and check if succeeded
2053 97cd9092 Dimitris Aragiorgis
    for line in output.stdout.splitlines():
2054 97cd9092 Dimitris Aragiorgis
      logging.info("%s", line)
2055 97cd9092 Dimitris Aragiorgis
2056 4b82125b Dimitris Aragiorgis
  def HotAddDevice(self, instance, dev_type, device, extra, seq):
2057 4b82125b Dimitris Aragiorgis
    """ Helper method to hot-add a new device
2058 4b82125b Dimitris Aragiorgis

2059 4b82125b Dimitris Aragiorgis
    It gets free pci slot generates the device name and invokes the
2060 4b82125b Dimitris Aragiorgis
    device specific method.
2061 4b82125b Dimitris Aragiorgis

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

2093 4b82125b Dimitris Aragiorgis
    It gets device info from runtime file, generates the device name and
2094 4b82125b Dimitris Aragiorgis
    invokes the device specific method.
2095 4b82125b Dimitris Aragiorgis

2096 4b82125b Dimitris Aragiorgis
    """
2097 4b82125b Dimitris Aragiorgis
    runtime = self._LoadKVMRuntime(instance)
2098 4b82125b Dimitris Aragiorgis
    entry = _GetExistingDeviceInfo(dev_type, device, runtime)
2099 4b82125b Dimitris Aragiorgis
    kvm_device = _RUNTIME_DEVICE[dev_type](entry)
2100 4b82125b Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, kvm_device)
2101 4b82125b Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2102 4f2f98f1 Dimitris Aragiorgis
      command = "device_del %s\n" % kvm_devid
2103 4f2f98f1 Dimitris Aragiorgis
      command += "drive_del %s" % kvm_devid
2104 4b82125b Dimitris Aragiorgis
    elif dev_type == constants.HOTPLUG_TARGET_NIC:
2105 4b82125b Dimitris Aragiorgis
      command = "device_del %s\n" % kvm_devid
2106 4b82125b Dimitris Aragiorgis
      command += "netdev_del %s" % kvm_devid
2107 4b82125b Dimitris Aragiorgis
      utils.RemoveFile(self._InstanceNICFile(instance.name, seq))
2108 4b82125b Dimitris Aragiorgis
    self._CallHotplugCommand(instance.name, command)
2109 4b82125b Dimitris Aragiorgis
    index = _DEVICE_RUNTIME_INDEX[dev_type]
2110 4b82125b Dimitris Aragiorgis
    runtime[index].remove(entry)
2111 4b82125b Dimitris Aragiorgis
    self._SaveKVMRuntime(instance, runtime)
2112 4b82125b Dimitris Aragiorgis
2113 4b82125b Dimitris Aragiorgis
    return kvm_device.pci
2114 4b82125b Dimitris Aragiorgis
2115 4b82125b Dimitris Aragiorgis
  def HotModDevice(self, instance, dev_type, device, _, seq):
2116 4b82125b Dimitris Aragiorgis
    """ Helper method for hot-mod device
2117 4b82125b Dimitris Aragiorgis

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

2121 4b82125b Dimitris Aragiorgis
    """
2122 4b82125b Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_NIC:
2123 4b82125b Dimitris Aragiorgis
      # putting it back in the same pci slot
2124 4b82125b Dimitris Aragiorgis
      device.pci = self.HotDelDevice(instance, dev_type, device, _, seq)
2125 4b82125b Dimitris Aragiorgis
      # TODO: remove sleep when socat gets removed
2126 4b82125b Dimitris Aragiorgis
      time.sleep(2)
2127 4b82125b Dimitris Aragiorgis
      self.HotAddDevice(instance, dev_type, device, _, seq)
2128 4b82125b Dimitris Aragiorgis
2129 4b82125b Dimitris Aragiorgis
  def _PassTapFd(self, instance, fd, nic):
2130 4b82125b Dimitris Aragiorgis
    """Pass file descriptor to kvm process via monitor socket using SCM_RIGHTS
2131 4b82125b Dimitris Aragiorgis

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

2150 585c8187 Guido Trotter
    @type text: string
2151 585c8187 Guido Trotter
    @param text: output of kvm --help
2152 585c8187 Guido Trotter
    @return: (version, v_maj, v_min, v_rev)
2153 5c3d5dfd Iustin Pop
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
2154 585c8187 Guido Trotter

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

2173 bc0fed4b Guido Trotter
    @type kvm_path: string
2174 bc0fed4b Guido Trotter
    @param kvm_path: path to the kvm executable
2175 bc0fed4b Guido Trotter
    @type option: a key of _KVMOPTS_CMDS
2176 bc0fed4b Guido Trotter
    @param option: kvm option to fetch the output from
2177 6e043e60 Guido Trotter
    @return: output a supported kvm invocation
2178 e3b89628 Guido Trotter
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
2179 e3b89628 Guido Trotter

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

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

2198 b52d85c1 Guido Trotter
    """
2199 6e043e60 Guido Trotter
    return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
2200 82e3bf85 Dimitris Aragiorgis
2201 82e3bf85 Dimitris Aragiorgis
  @classmethod
2202 82e3bf85 Dimitris Aragiorgis
  def _GetDefaultMachineVersion(cls, kvm_path):
2203 82e3bf85 Dimitris Aragiorgis
    """Return the default hardware revision (e.g. pc-1.1)
2204 82e3bf85 Dimitris Aragiorgis

2205 82e3bf85 Dimitris Aragiorgis
    """
2206 6e043e60 Guido Trotter
    output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2207 82e3bf85 Dimitris Aragiorgis
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
2208 82e3bf85 Dimitris Aragiorgis
    if match:
2209 82e3bf85 Dimitris Aragiorgis
      return match.group(1)
2210 82e3bf85 Dimitris Aragiorgis
    else:
2211 82e3bf85 Dimitris Aragiorgis
      return "pc"
2212 82e3bf85 Dimitris Aragiorgis
2213 70f25a49 Jose A. Lopes
  @classmethod
2214 70f25a49 Jose A. Lopes
  def _StopInstance(cls, instance, force=False, name=None):
2215 eb58f9b1 Guido Trotter
    """Stop an instance.
2216 eb58f9b1 Guido Trotter

2217 eb58f9b1 Guido Trotter
    """
2218 bbcf7ad0 Iustin Pop
    if name is not None and not force:
2219 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
2220 bbcf7ad0 Iustin Pop
    if name is None:
2221 bbcf7ad0 Iustin Pop
      name = instance.name
2222 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
2223 bbcf7ad0 Iustin Pop
    else:
2224 bbcf7ad0 Iustin Pop
      acpi = False
2225 70f25a49 Jose A. Lopes
    _, pid, alive = cls._InstancePidAlive(name)
2226 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
2227 bbcf7ad0 Iustin Pop
      if force or not acpi:
2228 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
2229 eb58f9b1 Guido Trotter
      else:
2230 70f25a49 Jose A. Lopes
        cls._CallMonitorCommand(name, "system_powerdown")
2231 70f25a49 Jose A. Lopes
2232 70f25a49 Jose A. Lopes
  def StopInstance(self, instance, force=False, retry=False, name=None):
2233 70f25a49 Jose A. Lopes
    """Stop an instance.
2234 70f25a49 Jose A. Lopes

2235 70f25a49 Jose A. Lopes
    """
2236 70f25a49 Jose A. Lopes
    self._StopInstance(instance, force, name)
2237 eb58f9b1 Guido Trotter
2238 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
2239 8904b35c Guido Trotter
    """Cleanup after a stopped instance
2240 8904b35c Guido Trotter

2241 8904b35c Guido Trotter
    """
2242 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
2243 8904b35c Guido Trotter
    if pid > 0 and alive:
2244 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
2245 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
2246 eb58f9b1 Guido Trotter
2247 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
2248 eb58f9b1 Guido Trotter
    """Reboot an instance.
2249 eb58f9b1 Guido Trotter

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

2273 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2274 30e42c4e Guido Trotter
    @param instance: instance to be migrated
2275 30e42c4e Guido Trotter
    @rtype: string
2276 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
2277 30e42c4e Guido Trotter

2278 30e42c4e Guido Trotter
    """
2279 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
2280 30e42c4e Guido Trotter
2281 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
2282 30e42c4e Guido Trotter
    """Prepare to accept an instance.
2283 30e42c4e Guido Trotter

2284 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2285 30e42c4e Guido Trotter
    @param instance: instance to be accepted
2286 30e42c4e Guido Trotter
    @type info: string
2287 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
2288 30e42c4e Guido Trotter
    @type target: string
2289 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
2290 30e42c4e Guido Trotter

2291 30e42c4e Guido Trotter
    """
2292 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2293 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
2294 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2295 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2296 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
2297 b73f1c59 Guido Trotter
                            incoming=incoming_address)
2298 30e42c4e Guido Trotter
2299 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
2300 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
2301 30e42c4e Guido Trotter

2302 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
2303 30e42c4e Guido Trotter

2304 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2305 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
2306 30e42c4e Guido Trotter

2307 30e42c4e Guido Trotter
    """
2308 30e42c4e Guido Trotter
    if success:
2309 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2310 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
2311 5d9bfd87 Apollon Oikonomopoulos
2312 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
2313 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
2314 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
2315 cc8a8ed7 Apollon Oikonomopoulos
          continue
2316 5d9bfd87 Apollon Oikonomopoulos
        try:
2317 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
2318 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
2319 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
2320 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
2321 5d9bfd87 Apollon Oikonomopoulos
          continue
2322 5d9bfd87 Apollon Oikonomopoulos
        try:
2323 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
2324 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
2325 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
2326 5d9bfd87 Apollon Oikonomopoulos
2327 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
2328 30e42c4e Guido Trotter
    else:
2329 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
2330 30e42c4e Guido Trotter
2331 bc0a2284 Helga Velroyen
  def MigrateInstance(self, cluster_name, instance, target, live):
2332 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
2333 30e42c4e Guido Trotter

2334 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
2335 30e42c4e Guido Trotter
    currently running.
2336 30e42c4e Guido Trotter

2337 bc0a2284 Helga Velroyen
    @type cluster_name: string
2338 bc0a2284 Helga Velroyen
    @param cluster_name: name of the cluster
2339 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
2340 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
2341 30e42c4e Guido Trotter
    @type target: string
2342 30e42c4e Guido Trotter
    @param target: ip address of the target node
2343 30e42c4e Guido Trotter
    @type live: boolean
2344 30e42c4e Guido Trotter
    @param live: perform a live migration
2345 30e42c4e Guido Trotter

2346 30e42c4e Guido Trotter
    """
2347 58d38b02 Iustin Pop
    instance_name = instance.name
2348 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
2349 6a1434d7 Andrea Spadaccini
    _, _, alive = self._InstancePidAlive(instance_name)
2350 30e42c4e Guido Trotter
    if not alive:
2351 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
2352 30e42c4e Guido Trotter
2353 30e42c4e Guido Trotter
    if not live:
2354 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
2355 30e42c4e Guido Trotter
2356 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
2357 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
2358 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2359 e43d4f9f Apollon Oikonomopoulos
2360 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
2361 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
2362 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2363 e43d4f9f Apollon Oikonomopoulos
2364 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
2365 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
2366 30e42c4e Guido Trotter
2367 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
2368 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
2369 6a1434d7 Andrea Spadaccini

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

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

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

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

2426 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
2427 3d836750 Guido Trotter
    @param instance: instance to be accepted
2428 3d836750 Guido Trotter
    @type mem: int
2429 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
2430 3d836750 Guido Trotter

2431 3d836750 Guido Trotter
    """
2432 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2433 3d836750 Guido Trotter
2434 fac489a5 Helga Velroyen
  def GetNodeInfo(self, hvparams=None):
2435 eb58f9b1 Guido Trotter
    """Return information about the node.
2436 eb58f9b1 Guido Trotter

2437 fac489a5 Helga Velroyen
    @type hvparams: dict of strings
2438 fac489a5 Helga Velroyen
    @param hvparams: hypervisor parameters, not used in this class
2439 fac489a5 Helga Velroyen

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

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

2459 eb58f9b1 Guido Trotter
    """
2460 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2461 9d9bded1 Michael Hanselmann
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2462 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2463 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2464 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
2465 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2466 c42be2c0 Petr Pudlak
      ndparams = node_group.FillND(primary_node)
2467 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2468 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
2469 1c3231aa Thomas Thrainer
                                     host=primary_node.name,
2470 c42be2c0 Petr Pudlak
                                     port=ndparams.get(constants.ND_SSH_PORT),
2471 052783ff Michael Hanselmann
                                     user=constants.SSH_CONSOLE_USER,
2472 55cc0a44 Michael Hanselmann
                                     command=cmd)
2473 3be34f57 Guido Trotter
2474 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2475 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2476 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
2477 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2478 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
2479 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
2480 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
2481 55cc0a44 Michael Hanselmann
                                     display=display)
2482 55cc0a44 Michael Hanselmann
2483 4d2cdb5a Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2484 4d2cdb5a Andrea Spadaccini
    if spice_bind:
2485 4d2cdb5a Andrea Spadaccini
      return objects.InstanceConsole(instance=instance.name,
2486 4d2cdb5a Andrea Spadaccini
                                     kind=constants.CONS_SPICE,
2487 4d2cdb5a Andrea Spadaccini
                                     host=spice_bind,
2488 4d2cdb5a Andrea Spadaccini
                                     port=instance.network_port)
2489 4d2cdb5a Andrea Spadaccini
2490 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
2491 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
2492 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
2493 55cc0a44 Michael Hanselmann
                                            instance.name))
2494 eb58f9b1 Guido Trotter
2495 75bf3149 Helga Velroyen
  def Verify(self, hvparams=None):
2496 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
2497 eb58f9b1 Guido Trotter

2498 cd04dfd2 Michael Hanselmann
    Check that the required binaries exist.
2499 cd04dfd2 Michael Hanselmann

2500 75bf3149 Helga Velroyen
    @type hvparams: dict of strings
2501 75bf3149 Helga Velroyen
    @param hvparams: hypervisor parameters to be verified against, not used here
2502 75bf3149 Helga Velroyen

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

2505 eb58f9b1 Guido Trotter
    """
2506 1f4b9d39 Iustin Pop
    msgs = []
2507 1f4b9d39 Iustin Pop
    # FIXME: this is the global kvm binary, but the actual path can be
2508 1f4b9d39 Iustin Pop
    # customized as an hv parameter; we should use the nodegroup's
2509 1f4b9d39 Iustin Pop
    # default kvm path parameter here.
2510 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
2511 1f4b9d39 Iustin Pop
      msgs.append("The KVM binary ('%s') does not exist" % constants.KVM_PATH)
2512 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2513 1f4b9d39 Iustin Pop
      msgs.append("The socat binary ('%s') does not exist" %
2514 1f4b9d39 Iustin Pop
                  constants.SOCAT_PATH)
2515 1f4b9d39 Iustin Pop
2516 1f4b9d39 Iustin Pop
    return self._FormatVerifyResults(msgs)
2517 14aa53cb Guido Trotter
2518 6b5605e8 Iustin Pop
  @classmethod
2519 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2520 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2521 6b5605e8 Iustin Pop

2522 6b5605e8 Iustin Pop
    @type hvparams:  dict
2523 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2524 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2525 6b5605e8 Iustin Pop

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

2595 d19d94db Guido Trotter
    @type hvparams:  dict
2596 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2597 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2598 d19d94db Guido Trotter

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

2656 8ef418bb Helga Velroyen
    @type hvparams: dict of strings
2657 8ef418bb Helga Velroyen
    @param hvparams: hypervisor params to be used on this node
2658 8ef418bb Helga Velroyen

2659 f5118ade Iustin Pop
    """
2660 f5118ade Iustin Pop
    cls.LinuxPowercycle()