Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 89c10241

History | View | Annotate | Download (96.7 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 e8cbe174 Dimitris Aragiorgis
def _UpgradeSerializedRuntime(serialized_runtime):
192 e8cbe174 Dimitris Aragiorgis
  """Upgrade runtime data
193 e8cbe174 Dimitris Aragiorgis

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

348 91c10532 Andrea Spadaccini
    """
349 91c10532 Andrea Spadaccini
    self.data[field_name] = field_value
350 91c10532 Andrea Spadaccini
351 5e34123e Michele Tartara
  def __len__(self):
352 5e34123e Michele Tartara
    """Return the number of fields stored in this QmpMessage.
353 5e34123e Michele Tartara

354 5e34123e Michele Tartara
    """
355 5e34123e Michele Tartara
    return len(self.data)
356 5e34123e Michele Tartara
357 5e34123e Michele Tartara
  def __delitem__(self, key):
358 5e34123e Michele Tartara
    """Delete the specified element from the QmpMessage.
359 5e34123e Michele Tartara

360 5e34123e Michele Tartara
    """
361 5e34123e Michele Tartara
    del(self.data[key])
362 5e34123e Michele Tartara
363 91c10532 Andrea Spadaccini
  @staticmethod
364 91c10532 Andrea Spadaccini
  def BuildFromJsonString(json_string):
365 91c10532 Andrea Spadaccini
    """Build a QmpMessage from a JSON encoded string.
366 91c10532 Andrea Spadaccini

367 91c10532 Andrea Spadaccini
    @type json_string: str
368 91c10532 Andrea Spadaccini
    @param json_string: JSON string representing the message
369 91c10532 Andrea Spadaccini
    @rtype: L{QmpMessage}
370 91c10532 Andrea Spadaccini
    @return: a L{QmpMessage} built from json_string
371 91c10532 Andrea Spadaccini

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

393 91c10532 Andrea Spadaccini
    @type monitor_filename: string
394 91c10532 Andrea Spadaccini
    @param monitor_filename: the filename of the UNIX raw socket on which the
395 cad837b9 Dimitris Aragiorgis
                             monitor (QMP or simple one) is listening
396 91c10532 Andrea Spadaccini

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

421 91c10532 Andrea Spadaccini
    """
422 91c10532 Andrea Spadaccini
    if not self._connected:
423 cad837b9 Dimitris Aragiorgis
      raise errors.ProgrammerError("To use a MonitorSocket you need to first"
424 91c10532 Andrea Spadaccini
                                   " invoke connect() on it")
425 91c10532 Andrea Spadaccini
426 91c10532 Andrea Spadaccini
  def connect(self):
427 cad837b9 Dimitris Aragiorgis
    """Connects to the monitor.
428 91c10532 Andrea Spadaccini

429 cad837b9 Dimitris Aragiorgis
    Connects to the UNIX socket
430 91c10532 Andrea Spadaccini

431 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
432 91c10532 Andrea Spadaccini

433 91c10532 Andrea Spadaccini
    """
434 fc84cd5d Guido Trotter
    if self._connected:
435 fc84cd5d Guido Trotter
      raise errors.ProgrammerError("Cannot connect twice")
436 fc84cd5d Guido Trotter
437 fc84cd5d Guido Trotter
    self._check_socket()
438 fc84cd5d Guido Trotter
439 fc84cd5d Guido Trotter
    # Check file existance/stuff
440 fc84cd5d Guido Trotter
    try:
441 fc84cd5d Guido Trotter
      self.sock.connect(self.monitor_filename)
442 fc84cd5d Guido Trotter
    except EnvironmentError:
443 fc84cd5d Guido Trotter
      raise errors.HypervisorError("Can't connect to qmp socket")
444 91c10532 Andrea Spadaccini
    self._connected = True
445 91c10532 Andrea Spadaccini
446 cad837b9 Dimitris Aragiorgis
  def close(self):
447 cad837b9 Dimitris Aragiorgis
    """Closes the socket
448 cad837b9 Dimitris Aragiorgis

449 cad837b9 Dimitris Aragiorgis
    It cannot be used after this call.
450 cad837b9 Dimitris Aragiorgis

451 cad837b9 Dimitris Aragiorgis
    """
452 cad837b9 Dimitris Aragiorgis
    self.sock.close()
453 cad837b9 Dimitris Aragiorgis
454 cad837b9 Dimitris Aragiorgis
455 cad837b9 Dimitris Aragiorgis
class QmpConnection(MonitorSocket):
456 cad837b9 Dimitris Aragiorgis
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
457 cad837b9 Dimitris Aragiorgis

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

478 cad837b9 Dimitris Aragiorgis
    Connects to the UNIX socket and makes sure that we can actually send and
479 cad837b9 Dimitris Aragiorgis
    receive data to the kvm instance via QMP.
480 cad837b9 Dimitris Aragiorgis

481 cad837b9 Dimitris Aragiorgis
    @raise errors.HypervisorError: when there are communication errors
482 cad837b9 Dimitris Aragiorgis
    @raise errors.ProgrammerError: when there are data serialization errors
483 cad837b9 Dimitris Aragiorgis

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

502 91c10532 Andrea Spadaccini
    Seeks for a QMP message in the given buf. If found, it parses it and
503 91c10532 Andrea Spadaccini
    returns it together with the rest of the characters in the buf.
504 91c10532 Andrea Spadaccini
    If no message is found, returns None and the whole buffer.
505 91c10532 Andrea Spadaccini

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
    message = None
510 91c10532 Andrea Spadaccini
    # Check if we got the message end token (CRLF, as per the QEMU Protocol
511 91c10532 Andrea Spadaccini
    # Specification 0.1 - Section 2.1.1)
512 91c10532 Andrea Spadaccini
    pos = buf.find(self._MESSAGE_END_TOKEN)
513 91c10532 Andrea Spadaccini
    if pos >= 0:
514 91c10532 Andrea Spadaccini
      try:
515 91c10532 Andrea Spadaccini
        message = QmpMessage.BuildFromJsonString(buf[:pos + 1])
516 91c10532 Andrea Spadaccini
      except Exception, err:
517 91c10532 Andrea Spadaccini
        raise errors.ProgrammerError("QMP data serialization error: %s" % err)
518 91c10532 Andrea Spadaccini
      buf = buf[pos + 1:]
519 91c10532 Andrea Spadaccini
520 91c10532 Andrea Spadaccini
    return (message, buf)
521 91c10532 Andrea Spadaccini
522 91c10532 Andrea Spadaccini
  def _Recv(self):
523 91c10532 Andrea Spadaccini
    """Receives a message from QMP and decodes the received JSON object.
524 91c10532 Andrea Spadaccini

525 91c10532 Andrea Spadaccini
    @rtype: QmpMessage
526 91c10532 Andrea Spadaccini
    @return: the received message
527 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
528 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
529 91c10532 Andrea Spadaccini

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

561 91c10532 Andrea Spadaccini
    @type message: QmpMessage
562 91c10532 Andrea Spadaccini
    @param message: message to send to KVM
563 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
564 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
565 91c10532 Andrea Spadaccini

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1173 4fbb3c60 Guido Trotter
    @type instance_name: string
1174 c41eea6e Iustin Pop
    @param instance_name: the instance name
1175 0bbec3af Helga Velroyen
    @type hvparams: dict of strings
1176 0bbec3af Helga Velroyen
    @param hvparams: hvparams to be used with this instance
1177 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
1178 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
1179 eb58f9b1 Guido Trotter

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

1205 0200a1af Helga Velroyen
    @type hvparams: dict of strings
1206 0200a1af Helga Velroyen
    @param hvparams: hypervisor parameter
1207 c41eea6e Iustin Pop
    @return: list of tuples (name, id, memory, vcpus, stat, times)
1208 c41eea6e Iustin Pop

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

1225 43c6e76f Dimitris Aragiorgis
    @type instance: L{objects.Instance}
1226 43c6e76f Dimitris Aragiorgis
    @param instance: the instance object
1227 41a878b5 Dimitris Aragiorgis
    @type kvm_disks: list of tuples
1228 41a878b5 Dimitris Aragiorgis
    @param kvm_disks: list of tuples [(disk, link_name, uri)..]
1229 43c6e76f Dimitris Aragiorgis
    @type kvmhelp: string
1230 43c6e76f Dimitris Aragiorgis
    @param kvmhelp: output of kvm --help
1231 43c6e76f Dimitris Aragiorgis
    @type devlist: string
1232 43c6e76f Dimitris Aragiorgis
    @param devlist: output of kvm -device ?
1233 43c6e76f Dimitris Aragiorgis
    @rtype: list
1234 43c6e76f Dimitris Aragiorgis
    @return: list of command line options eventually used by kvm executable
1235 af5db30c Dimitris Aragiorgis

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

1317 b73f1c59 Guido Trotter
    @type kvmhelp: string
1318 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1319 839642c2 Iustin Pop
    @attention: this function must not have any side-effects; for
1320 839642c2 Iustin Pop
        example, it must not write to the filesystem, or read values
1321 839642c2 Iustin Pop
        from the current system the are expected to differ between
1322 839642c2 Iustin Pop
        nodes, since it is only run once at instance startup;
1323 839642c2 Iustin Pop
        actions/kvm arguments that can vary between systems should be
1324 839642c2 Iustin Pop
        done in L{_ExecuteKVMRuntime}
1325 839642c2 Iustin Pop

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2055 24711492 Dimitris Aragiorgis
    @raise errors.HypervisorError: in one of the previous cases
2056 24711492 Dimitris Aragiorgis

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

2083 4b82125b Dimitris Aragiorgis
    It gets free pci slot generates the device name and invokes the
2084 4b82125b Dimitris Aragiorgis
    device specific method.
2085 4b82125b Dimitris Aragiorgis

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

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

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

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

2145 4b82125b Dimitris Aragiorgis
    """
2146 4b82125b Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_NIC:
2147 4b82125b Dimitris Aragiorgis
      # putting it back in the same pci slot
2148 4b82125b Dimitris Aragiorgis
      device.pci = self.HotDelDevice(instance, dev_type, device, _, seq)
2149 4b82125b Dimitris Aragiorgis
      self.HotAddDevice(instance, dev_type, device, _, seq)
2150 4b82125b Dimitris Aragiorgis
2151 4b82125b Dimitris Aragiorgis
  def _PassTapFd(self, instance, fd, nic):
2152 4b82125b Dimitris Aragiorgis
    """Pass file descriptor to kvm process via monitor socket using SCM_RIGHTS
2153 4b82125b Dimitris Aragiorgis

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2361 30e42c4e Guido Trotter
    """
2362 58d38b02 Iustin Pop
    instance_name = instance.name
2363 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
2364 6a1434d7 Andrea Spadaccini
    _, _, alive = self._InstancePidAlive(instance_name)
2365 30e42c4e Guido Trotter
    if not alive:
2366 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
2367 30e42c4e Guido Trotter
2368 30e42c4e Guido Trotter
    if not live:
2369 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
2370 30e42c4e Guido Trotter
2371 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
2372 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
2373 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2374 e43d4f9f Apollon Oikonomopoulos
2375 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
2376 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
2377 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2378 e43d4f9f Apollon Oikonomopoulos
2379 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
2380 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
2381 30e42c4e Guido Trotter
2382 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
2383 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
2384 6a1434d7 Andrea Spadaccini

2385 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2386 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
2387 6a1434d7 Andrea Spadaccini
    @type success: bool
2388 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
2389 6a1434d7 Andrea Spadaccini
    @type live: bool
2390 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
2391 6a1434d7 Andrea Spadaccini

2392 6a1434d7 Andrea Spadaccini
    """
2393 6a1434d7 Andrea Spadaccini
    if success:
2394 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
2395 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
2396 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
2397 6a1434d7 Andrea Spadaccini
    elif live:
2398 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
2399 6a1434d7 Andrea Spadaccini
2400 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
2401 6a1434d7 Andrea Spadaccini
    """Get the migration status
2402 6a1434d7 Andrea Spadaccini

2403 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2404 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
2405 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
2406 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
2407 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
2408 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
2409 6a1434d7 Andrea Spadaccini

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

2441 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
2442 3d836750 Guido Trotter
    @param instance: instance to be accepted
2443 3d836750 Guido Trotter
    @type mem: int
2444 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
2445 3d836750 Guido Trotter

2446 3d836750 Guido Trotter
    """
2447 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2448 3d836750 Guido Trotter
2449 fac489a5 Helga Velroyen
  def GetNodeInfo(self, hvparams=None):
2450 eb58f9b1 Guido Trotter
    """Return information about the node.
2451 eb58f9b1 Guido Trotter

2452 fac489a5 Helga Velroyen
    @type hvparams: dict of strings
2453 fac489a5 Helga Velroyen
    @param hvparams: hypervisor parameters, not used in this class
2454 fac489a5 Helga Velroyen

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

2460 eb58f9b1 Guido Trotter
    """
2461 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
2462 25bce647 Santi Raffa
    kvmpath = constants.KVM_PATH
2463 25bce647 Santi Raffa
    if hvparams is not None:
2464 25bce647 Santi Raffa
      kvmpath = hvparams.get(constants.HV_KVM_PATH, constants.KVM_PATH)
2465 25bce647 Santi Raffa
    _, v_major, v_min, v_rev = self._GetKVMVersion(kvmpath)
2466 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2467 34fbc862 Andrea Spadaccini
    return result
2468 eb58f9b1 Guido Trotter
2469 637ce7f9 Guido Trotter
  @classmethod
2470 1c3231aa Thomas Thrainer
  def GetInstanceConsole(cls, instance, primary_node, hvparams, beparams):
2471 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
2472 eb58f9b1 Guido Trotter

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

2510 cd04dfd2 Michael Hanselmann
    Check that the required binaries exist.
2511 cd04dfd2 Michael Hanselmann

2512 75bf3149 Helga Velroyen
    @type hvparams: dict of strings
2513 75bf3149 Helga Velroyen
    @param hvparams: hypervisor parameters to be verified against, not used here
2514 75bf3149 Helga Velroyen

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

2517 eb58f9b1 Guido Trotter
    """
2518 1f4b9d39 Iustin Pop
    msgs = []
2519 25bce647 Santi Raffa
    kvmpath = constants.KVM_PATH
2520 25bce647 Santi Raffa
    if hvparams is not None:
2521 25bce647 Santi Raffa
      kvmpath = hvparams.get(constants.HV_KVM_PATH, constants.KVM_PATH)
2522 25bce647 Santi Raffa
    if not os.path.exists(kvmpath):
2523 25bce647 Santi Raffa
      msgs.append("The KVM binary ('%s') does not exist" % kvmpath)
2524 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2525 1f4b9d39 Iustin Pop
      msgs.append("The socat binary ('%s') does not exist" %
2526 1f4b9d39 Iustin Pop
                  constants.SOCAT_PATH)
2527 1f4b9d39 Iustin Pop
2528 1f4b9d39 Iustin Pop
    return self._FormatVerifyResults(msgs)
2529 14aa53cb Guido Trotter
2530 6b5605e8 Iustin Pop
  @classmethod
2531 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2532 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2533 6b5605e8 Iustin Pop

2534 6b5605e8 Iustin Pop
    @type hvparams:  dict
2535 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2536 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2537 6b5605e8 Iustin Pop

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

2607 d19d94db Guido Trotter
    @type hvparams:  dict
2608 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2609 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2610 d19d94db Guido Trotter

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

2668 8ef418bb Helga Velroyen
    @type hvparams: dict of strings
2669 8ef418bb Helga Velroyen
    @param hvparams: hypervisor params to be used on this node
2670 8ef418bb Helga Velroyen

2671 f5118ade Iustin Pop
    """
2672 f5118ade Iustin Pop
    cls.LinuxPowercycle()