Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 02985c42

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

478 ce0248c6 Dimitris Aragiorgis
    """
479 ce0248c6 Dimitris Aragiorgis
    super(QmpConnection, self).connect()
480 91c10532 Andrea Spadaccini
    # Check if we receive a correct greeting message from the server
481 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 2.2)
482 91c10532 Andrea Spadaccini
    greeting = self._Recv()
483 91c10532 Andrea Spadaccini
    if not greeting[self._FIRST_MESSAGE_KEY]:
484 91c10532 Andrea Spadaccini
      self._connected = False
485 afa9bb2e Michael Hanselmann
      raise errors.HypervisorError("kvm: QMP communication error (wrong"
486 91c10532 Andrea Spadaccini
                                   " server greeting")
487 91c10532 Andrea Spadaccini
488 bd338fab Dimitris Aragiorgis
    # This is needed because QMP can return more than one greetings
489 bd338fab Dimitris Aragiorgis
    # see https://groups.google.com/d/msg/ganeti-devel/gZYcvHKDooU/SnukC8dgS5AJ
490 bd338fab Dimitris Aragiorgis
    self._buf = ""
491 bd338fab Dimitris Aragiorgis
492 91c10532 Andrea Spadaccini
    # Let's put the monitor in command mode using the qmp_capabilities
493 91c10532 Andrea Spadaccini
    # command, or else no command will be executable.
494 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 4)
495 91c10532 Andrea Spadaccini
    self.Execute(self._CAPABILITIES_COMMAND)
496 91c10532 Andrea Spadaccini
497 91c10532 Andrea Spadaccini
  def _ParseMessage(self, buf):
498 91c10532 Andrea Spadaccini
    """Extract and parse a QMP message from the given buffer.
499 91c10532 Andrea Spadaccini

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

504 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
505 91c10532 Andrea Spadaccini

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

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

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

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

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

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

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

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

807 98ec75d6 Iustin Pop
    """
808 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
809 98ec75d6 Iustin Pop
810 263b8de6 Guido Trotter
  @classmethod
811 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
812 7548396c Guido Trotter
    """Returns the instance uidfile.
813 7548396c Guido Trotter

814 7548396c Guido Trotter
    """
815 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
816 7548396c Guido Trotter
817 7548396c Guido Trotter
  @classmethod
818 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
819 263b8de6 Guido Trotter
    """Check pid file for instance information.
820 263b8de6 Guido Trotter

821 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
822 263b8de6 Guido Trotter
    information from its command line.
823 263b8de6 Guido Trotter

824 263b8de6 Guido Trotter
    @type pid: string or int
825 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
826 263b8de6 Guido Trotter
    @rtype: tuple
827 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
828 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
829 263b8de6 Guido Trotter

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

865 263b8de6 Guido Trotter
    @type instance_name: string
866 263b8de6 Guido Trotter
    @param instance_name: instance name
867 263b8de6 Guido Trotter
    @rtype: tuple
868 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
869 1f8b3a27 Guido Trotter

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

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

896 c4fbefc8 Guido Trotter
    """
897 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
898 c4fbefc8 Guido Trotter
899 0df4d98a Guido Trotter
  @classmethod
900 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
901 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
902 c4fbefc8 Guido Trotter

903 c4fbefc8 Guido Trotter
    """
904 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
905 c4fbefc8 Guido Trotter
906 91c10532 Andrea Spadaccini
  @classmethod
907 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
908 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
909 91c10532 Andrea Spadaccini

910 91c10532 Andrea Spadaccini
    """
911 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
912 91c10532 Andrea Spadaccini
913 86d6bc2a Guido Trotter
  @staticmethod
914 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
915 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
916 86d6bc2a Guido Trotter

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

919 86d6bc2a Guido Trotter
    """
920 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
921 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
922 86d6bc2a Guido Trotter
    else:
923 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
924 86d6bc2a Guido Trotter
925 0df4d98a Guido Trotter
  @classmethod
926 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
927 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
928 38e250ba Guido Trotter

929 38e250ba Guido Trotter
    """
930 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
931 38e250ba Guido Trotter
932 7e66c35b Guido Trotter
  @classmethod
933 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
934 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
935 547a63b7 Balazs Lecz

936 547a63b7 Balazs Lecz
    """
937 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
938 547a63b7 Balazs Lecz
939 547a63b7 Balazs Lecz
  @classmethod
940 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
941 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
942 5d9bfd87 Apollon Oikonomopoulos
    given instance.
943 5d9bfd87 Apollon Oikonomopoulos

944 5d9bfd87 Apollon Oikonomopoulos
    """
945 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
946 5d9bfd87 Apollon Oikonomopoulos
947 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
948 2cec9236 Dimitris Aragiorgis
  def _InstanceNICFile(cls, instance_name, seq_or_uuid):
949 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
950 5d9bfd87 Apollon Oikonomopoulos

951 5d9bfd87 Apollon Oikonomopoulos
    """
952 2cec9236 Dimitris Aragiorgis
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq_or_uuid))
953 2cec9236 Dimitris Aragiorgis
954 2cec9236 Dimitris Aragiorgis
  @classmethod
955 2cec9236 Dimitris Aragiorgis
  def _GetInstanceNICTap(cls, instance_name, nic):
956 2cec9236 Dimitris Aragiorgis
    """Returns the tap for the corresponding nic
957 2cec9236 Dimitris Aragiorgis

958 2cec9236 Dimitris Aragiorgis
    Search for tap file named after NIC's uuid.
959 2cec9236 Dimitris Aragiorgis
    For old instances without uuid indexed tap files returns nothing.
960 2cec9236 Dimitris Aragiorgis

961 2cec9236 Dimitris Aragiorgis
    """
962 2cec9236 Dimitris Aragiorgis
    try:
963 2cec9236 Dimitris Aragiorgis
      return utils.ReadFile(cls._InstanceNICFile(instance_name, nic.uuid))
964 2cec9236 Dimitris Aragiorgis
    except EnvironmentError:
965 2cec9236 Dimitris Aragiorgis
      pass
966 2cec9236 Dimitris Aragiorgis
967 2cec9236 Dimitris Aragiorgis
  @classmethod
968 2cec9236 Dimitris Aragiorgis
  def _WriteInstanceNICFiles(cls, instance_name, seq, nic, tap):
969 2cec9236 Dimitris Aragiorgis
    """Write tap name to both instance NIC files
970 2cec9236 Dimitris Aragiorgis

971 2cec9236 Dimitris Aragiorgis
    """
972 2cec9236 Dimitris Aragiorgis
    for ident in [seq, nic.uuid]:
973 2cec9236 Dimitris Aragiorgis
      utils.WriteFile(cls._InstanceNICFile(instance_name, ident), data=tap)
974 2cec9236 Dimitris Aragiorgis
975 2cec9236 Dimitris Aragiorgis
  @classmethod
976 2cec9236 Dimitris Aragiorgis
  def _RemoveInstanceNICFiles(cls, instance_name, seq, nic):
977 2cec9236 Dimitris Aragiorgis
    """Write tap name to both instance NIC files
978 2cec9236 Dimitris Aragiorgis

979 2cec9236 Dimitris Aragiorgis
    """
980 2cec9236 Dimitris Aragiorgis
    for ident in [seq, nic.uuid]:
981 2cec9236 Dimitris Aragiorgis
      utils.RemoveFile(cls._InstanceNICFile(instance_name, ident))
982 5d9bfd87 Apollon Oikonomopoulos
983 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
984 4f580fef Sรฉbastien Bocahu
  def _InstanceKeymapFile(cls, instance_name):
985 4f580fef Sรฉbastien Bocahu
    """Returns the name of the file containing the keymap for a given instance
986 4f580fef Sรฉbastien Bocahu

987 4f580fef Sรฉbastien Bocahu
    """
988 4f580fef Sรฉbastien Bocahu
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
989 4f580fef Sรฉbastien Bocahu
990 4f580fef Sรฉbastien Bocahu
  @classmethod
991 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
992 7548396c Guido Trotter
    """Try to read a uid file
993 7548396c Guido Trotter

994 7548396c Guido Trotter
    """
995 7548396c Guido Trotter
    if os.path.exists(uid_file):
996 7548396c Guido Trotter
      try:
997 682f7601 Guido Trotter
        uid = int(utils.ReadOneLineFile(uid_file))
998 aa0b600b Guido Trotter
        return uid
999 7548396c Guido Trotter
      except EnvironmentError:
1000 7548396c Guido Trotter
        logging.warning("Can't read uid file", exc_info=True)
1001 7548396c Guido Trotter
      except (TypeError, ValueError):
1002 7548396c Guido Trotter
        logging.warning("Can't parse uid file contents", exc_info=True)
1003 aa0b600b Guido Trotter
    return None
1004 7548396c Guido Trotter
1005 7548396c Guido Trotter
  @classmethod
1006 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
1007 547a63b7 Balazs Lecz
    """Removes an instance's rutime sockets/files/dirs.
1008 7e66c35b Guido Trotter

1009 7e66c35b Guido Trotter
    """
1010 7e66c35b Guido Trotter
    utils.RemoveFile(pidfile)
1011 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
1012 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceSerial(instance_name))
1013 91c10532 Andrea Spadaccini
    utils.RemoveFile(cls._InstanceQmpMonitor(instance_name))
1014 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
1015 4f580fef Sรฉbastien Bocahu
    utils.RemoveFile(cls._InstanceKeymapFile(instance_name))
1016 7548396c Guido Trotter
    uid_file = cls._InstanceUidFile(instance_name)
1017 7548396c Guido Trotter
    uid = cls._TryReadUidFile(uid_file)
1018 7548396c Guido Trotter
    utils.RemoveFile(uid_file)
1019 7548396c Guido Trotter
    if uid is not None:
1020 7548396c Guido Trotter
      uidpool.ReleaseUid(uid)
1021 7be85163 Guido Trotter
    try:
1022 7be85163 Guido Trotter
      shutil.rmtree(cls._InstanceNICDir(instance_name))
1023 7be85163 Guido Trotter
    except OSError, err:
1024 7be85163 Guido Trotter
      if err.errno != errno.ENOENT:
1025 7be85163 Guido Trotter
        raise
1026 547a63b7 Balazs Lecz
    try:
1027 547a63b7 Balazs Lecz
      chroot_dir = cls._InstanceChrootDir(instance_name)
1028 547a63b7 Balazs Lecz
      utils.RemoveDir(chroot_dir)
1029 547a63b7 Balazs Lecz
    except OSError, err:
1030 547a63b7 Balazs Lecz
      if err.errno == errno.ENOTEMPTY:
1031 547a63b7 Balazs Lecz
        # The chroot directory is expected to be empty, but it isn't.
1032 547a63b7 Balazs Lecz
        new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
1033 547a63b7 Balazs Lecz
                                          prefix="%s-%s-" %
1034 547a63b7 Balazs Lecz
                                          (instance_name,
1035 547a63b7 Balazs Lecz
                                           utils.TimestampForFilename()))
1036 547a63b7 Balazs Lecz
        logging.warning("The chroot directory of instance %s can not be"
1037 547a63b7 Balazs Lecz
                        " removed as it is not empty. Moving it to the"
1038 547a63b7 Balazs Lecz
                        " quarantine instead. Please investigate the"
1039 547a63b7 Balazs Lecz
                        " contents (%s) and clean up manually",
1040 547a63b7 Balazs Lecz
                        instance_name, new_chroot_dir)
1041 547a63b7 Balazs Lecz
        utils.RenameFile(chroot_dir, new_chroot_dir)
1042 547a63b7 Balazs Lecz
      else:
1043 547a63b7 Balazs Lecz
        raise
1044 7e66c35b Guido Trotter
1045 748e4b5a Michael Hanselmann
  @staticmethod
1046 30007542 Dimitris Aragiorgis
  def _CreateNICEnv(instance_name, nic, tap, seq=None, instance_tags=None):
1047 30007542 Dimitris Aragiorgis
    """Create environment variables for a specific NIC
1048 eb58f9b1 Guido Trotter

1049 30007542 Dimitris Aragiorgis
    This is needed during NIC ifup/ifdown scripts.
1050 30007542 Dimitris Aragiorgis
    Since instance tags may change during NIC creation and removal
1051 30007542 Dimitris Aragiorgis
    and because during cleanup instance object is not available we
1052 30007542 Dimitris Aragiorgis
    pass them only upon NIC creation (instance startup/NIC hot-plugging).
1053 eb58f9b1 Guido Trotter

1054 eb58f9b1 Guido Trotter
    """
1055 5d9bfd87 Apollon Oikonomopoulos
    env = {
1056 5d9bfd87 Apollon Oikonomopoulos
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
1057 30007542 Dimitris Aragiorgis
      "INSTANCE": instance_name,
1058 5d9bfd87 Apollon Oikonomopoulos
      "MAC": nic.mac,
1059 5d9bfd87 Apollon Oikonomopoulos
      "MODE": nic.nicparams[constants.NIC_MODE],
1060 ad721818 Dimitris Aragiorgis
      "INTERFACE_UUID": nic.uuid,
1061 5d9bfd87 Apollon Oikonomopoulos
    }
1062 5d9bfd87 Apollon Oikonomopoulos
1063 30007542 Dimitris Aragiorgis
    if instance_tags:
1064 30007542 Dimitris Aragiorgis
      env["TAGS"] = " ".join(instance_tags)
1065 30007542 Dimitris Aragiorgis
1066 30007542 Dimitris Aragiorgis
    # This should always be available except for old instances in the
1067 30007542 Dimitris Aragiorgis
    # cluster without uuid indexed tap files.
1068 30007542 Dimitris Aragiorgis
    if tap:
1069 30007542 Dimitris Aragiorgis
      env["INTERFACE"] = tap
1070 30007542 Dimitris Aragiorgis
1071 30007542 Dimitris Aragiorgis
    if seq:
1072 30007542 Dimitris Aragiorgis
      env["INTERFACE_INDEX"] = str(seq)
1073 30007542 Dimitris Aragiorgis
1074 5d9bfd87 Apollon Oikonomopoulos
    if nic.ip:
1075 5d9bfd87 Apollon Oikonomopoulos
      env["IP"] = nic.ip
1076 5d9bfd87 Apollon Oikonomopoulos
1077 ad721818 Dimitris Aragiorgis
    if nic.name:
1078 ad721818 Dimitris Aragiorgis
      env["INTERFACE_NAME"] = nic.name
1079 ad721818 Dimitris Aragiorgis
1080 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_LINK]:
1081 5d9bfd87 Apollon Oikonomopoulos
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
1082 5d9bfd87 Apollon Oikonomopoulos
1083 a5ad5e58 Apollon Oikonomopoulos
    if nic.network:
1084 cbe4a0a5 Dimitris Aragiorgis
      n = objects.Network.FromDict(nic.netinfo)
1085 7e8f03e3 Dimitris Aragiorgis
      env.update(n.HooksDict())
1086 a5ad5e58 Apollon Oikonomopoulos
1087 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1088 5d9bfd87 Apollon Oikonomopoulos
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
1089 5d9bfd87 Apollon Oikonomopoulos
1090 30007542 Dimitris Aragiorgis
    return env
1091 30007542 Dimitris Aragiorgis
1092 30007542 Dimitris Aragiorgis
  @classmethod
1093 30007542 Dimitris Aragiorgis
  def _ConfigureNIC(cls, instance, seq, nic, tap):
1094 30007542 Dimitris Aragiorgis
    """Run the network configuration script for a specified NIC
1095 30007542 Dimitris Aragiorgis

1096 30007542 Dimitris Aragiorgis
    @param instance: instance we're acting on
1097 30007542 Dimitris Aragiorgis
    @type instance: instance object
1098 30007542 Dimitris Aragiorgis
    @param seq: nic sequence number
1099 30007542 Dimitris Aragiorgis
    @type seq: int
1100 30007542 Dimitris Aragiorgis
    @param nic: nic we're acting on
1101 30007542 Dimitris Aragiorgis
    @type nic: nic object
1102 30007542 Dimitris Aragiorgis
    @param tap: the host's tap interface this NIC corresponds to
1103 30007542 Dimitris Aragiorgis
    @type tap: str
1104 30007542 Dimitris Aragiorgis

1105 30007542 Dimitris Aragiorgis
    """
1106 30007542 Dimitris Aragiorgis
    env = cls._CreateNICEnv(instance.name, nic, tap, seq, instance.GetTags())
1107 9d9bded1 Michael Hanselmann
    result = utils.RunCmd([pathutils.KVM_IFUP, tap], env=env)
1108 5d9bfd87 Apollon Oikonomopoulos
    if result.failed:
1109 afa9bb2e Michael Hanselmann
      raise errors.HypervisorError("Failed to configure interface %s: %s;"
1110 afa9bb2e Michael Hanselmann
                                   " network configuration script output: %s" %
1111 5d9bfd87 Apollon Oikonomopoulos
                                   (tap, result.fail_reason, result.output))
1112 eb58f9b1 Guido Trotter
1113 b693125f Tsachy Shacham
  @staticmethod
1114 b693125f Tsachy Shacham
  def _VerifyAffinityPackage():
1115 b693125f Tsachy Shacham
    if affinity is None:
1116 b693125f Tsachy Shacham
      raise errors.HypervisorError("affinity Python package not"
1117 5ae4945a Iustin Pop
                                   " found; cannot use CPU pinning under KVM")
1118 b693125f Tsachy Shacham
1119 b693125f Tsachy Shacham
  @staticmethod
1120 b693125f Tsachy Shacham
  def _BuildAffinityCpuMask(cpu_list):
1121 b693125f Tsachy Shacham
    """Create a CPU mask suitable for sched_setaffinity from a list of
1122 b693125f Tsachy Shacham
    CPUs.
1123 b693125f Tsachy Shacham

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

1127 b693125f Tsachy Shacham
    @type cpu_list: list of int
1128 b693125f Tsachy Shacham
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
1129 b693125f Tsachy Shacham
    @rtype: int
1130 b693125f Tsachy Shacham
    @return: a bit mask of CPU affinities
1131 b693125f Tsachy Shacham

1132 b693125f Tsachy Shacham
    """
1133 b693125f Tsachy Shacham
    if cpu_list == constants.CPU_PINNING_OFF:
1134 b693125f Tsachy Shacham
      return constants.CPU_PINNING_ALL_KVM
1135 b693125f Tsachy Shacham
    else:
1136 b693125f Tsachy Shacham
      return sum(2 ** cpu for cpu in cpu_list)
1137 b693125f Tsachy Shacham
1138 b693125f Tsachy Shacham
  @classmethod
1139 b693125f Tsachy Shacham
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
1140 b693125f Tsachy Shacham
    """Change CPU affinity for running VM according to given CPU mask.
1141 b693125f Tsachy Shacham

1142 b693125f Tsachy Shacham
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
1143 b693125f Tsachy Shacham
    @type cpu_mask: string
1144 b693125f Tsachy Shacham
    @param process_id: process ID of KVM process. Used to pin entire VM
1145 b693125f Tsachy Shacham
                       to physical CPUs.
1146 b693125f Tsachy Shacham
    @type process_id: int
1147 b693125f Tsachy Shacham
    @param thread_dict: map of virtual CPUs to KVM thread IDs
1148 b693125f Tsachy Shacham
    @type thread_dict: dict int:int
1149 b693125f Tsachy Shacham

1150 b693125f Tsachy Shacham
    """
1151 b693125f Tsachy Shacham
    # Convert the string CPU mask to a list of list of int's
1152 b693125f Tsachy Shacham
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
1153 b693125f Tsachy Shacham
1154 b693125f Tsachy Shacham
    if len(cpu_list) == 1:
1155 b693125f Tsachy Shacham
      all_cpu_mapping = cpu_list[0]
1156 b693125f Tsachy Shacham
      if all_cpu_mapping == constants.CPU_PINNING_OFF:
1157 b693125f Tsachy Shacham
        # If CPU pinning has 1 entry that's "all", then do nothing
1158 b693125f Tsachy Shacham
        pass
1159 b693125f Tsachy Shacham
      else:
1160 b693125f Tsachy Shacham
        # If CPU pinning has one non-all entry, map the entire VM to
1161 b693125f Tsachy Shacham
        # one set of physical CPUs
1162 b693125f Tsachy Shacham
        cls._VerifyAffinityPackage()
1163 5ae4945a Iustin Pop
        affinity.set_process_affinity_mask(
1164 5ae4945a Iustin Pop
          process_id, cls._BuildAffinityCpuMask(all_cpu_mapping))
1165 b693125f Tsachy Shacham
    else:
1166 b693125f Tsachy Shacham
      # The number of vCPUs mapped should match the number of vCPUs
1167 b693125f Tsachy Shacham
      # reported by KVM. This was already verified earlier, so
1168 b693125f Tsachy Shacham
      # here only as a sanity check.
1169 b693125f Tsachy Shacham
      assert len(thread_dict) == len(cpu_list)
1170 b693125f Tsachy Shacham
      cls._VerifyAffinityPackage()
1171 b693125f Tsachy Shacham
1172 b693125f Tsachy Shacham
      # For each vCPU, map it to the proper list of physical CPUs
1173 b693125f Tsachy Shacham
      for vcpu, i in zip(cpu_list, range(len(cpu_list))):
1174 b693125f Tsachy Shacham
        affinity.set_process_affinity_mask(thread_dict[i],
1175 5ae4945a Iustin Pop
                                           cls._BuildAffinityCpuMask(vcpu))
1176 b693125f Tsachy Shacham
1177 b693125f Tsachy Shacham
  def _GetVcpuThreadIds(self, instance_name):
1178 b693125f Tsachy Shacham
    """Get a mapping of vCPU no. to thread IDs for the instance
1179 b693125f Tsachy Shacham

1180 b693125f Tsachy Shacham
    @type instance_name: string
1181 b693125f Tsachy Shacham
    @param instance_name: instance in question
1182 b693125f Tsachy Shacham
    @rtype: dictionary of int:int
1183 b693125f Tsachy Shacham
    @return: a dictionary mapping vCPU numbers to thread IDs
1184 b693125f Tsachy Shacham

1185 b693125f Tsachy Shacham
    """
1186 b693125f Tsachy Shacham
    result = {}
1187 b693125f Tsachy Shacham
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
1188 b693125f Tsachy Shacham
    for line in output.stdout.splitlines():
1189 b693125f Tsachy Shacham
      match = self._CPU_INFO_RE.search(line)
1190 b693125f Tsachy Shacham
      if not match:
1191 b693125f Tsachy Shacham
        continue
1192 b693125f Tsachy Shacham
      grp = map(int, match.groups())
1193 b693125f Tsachy Shacham
      result[grp[0]] = grp[1]
1194 b693125f Tsachy Shacham
1195 b693125f Tsachy Shacham
    return result
1196 b693125f Tsachy Shacham
1197 1d8a7812 Andrea Spadaccini
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
1198 1d8a7812 Andrea Spadaccini
    """Complete CPU pinning.
1199 b693125f Tsachy Shacham

1200 b693125f Tsachy Shacham
    @type instance_name: string
1201 b693125f Tsachy Shacham
    @param instance_name: name of instance
1202 b693125f Tsachy Shacham
    @type cpu_mask: string
1203 b693125f Tsachy Shacham
    @param cpu_mask: CPU pinning mask as entered by user
1204 b693125f Tsachy Shacham

1205 b693125f Tsachy Shacham
    """
1206 1d8a7812 Andrea Spadaccini
    # Get KVM process ID, to be used if need to pin entire VM
1207 1d8a7812 Andrea Spadaccini
    _, pid, _ = self._InstancePidAlive(instance_name)
1208 1d8a7812 Andrea Spadaccini
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
1209 1d8a7812 Andrea Spadaccini
    thread_dict = self._GetVcpuThreadIds(instance_name)
1210 1d8a7812 Andrea Spadaccini
    # Run CPU pinning, based on configured mask
1211 1d8a7812 Andrea Spadaccini
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
1212 b693125f Tsachy Shacham
1213 eb58f9b1 Guido Trotter
  def ListInstances(self):
1214 eb58f9b1 Guido Trotter
    """Get the list of running instances.
1215 eb58f9b1 Guido Trotter

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

1219 eb58f9b1 Guido Trotter
    """
1220 eb58f9b1 Guido Trotter
    result = []
1221 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1222 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
1223 eb58f9b1 Guido Trotter
        result.append(name)
1224 eb58f9b1 Guido Trotter
    return result
1225 eb58f9b1 Guido Trotter
1226 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
1227 eb58f9b1 Guido Trotter
    """Get instance properties.
1228 eb58f9b1 Guido Trotter

1229 4fbb3c60 Guido Trotter
    @type instance_name: string
1230 c41eea6e Iustin Pop
    @param instance_name: the instance name
1231 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
1232 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
1233 eb58f9b1 Guido Trotter

1234 eb58f9b1 Guido Trotter
    """
1235 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
1236 1f8b3a27 Guido Trotter
    if not alive:
1237 eb58f9b1 Guido Trotter
      return None
1238 eb58f9b1 Guido Trotter
1239 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
1240 fc84cd5d Guido Trotter
    istat = "---b-"
1241 eb58f9b1 Guido Trotter
    times = "0"
1242 eb58f9b1 Guido Trotter
1243 89da2ff3 Guido Trotter
    try:
1244 89da2ff3 Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
1245 89da2ff3 Guido Trotter
      qmp.connect()
1246 89da2ff3 Guido Trotter
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
1247 89da2ff3 Guido Trotter
      # Will fail if ballooning is not enabled, but we can then just resort to
1248 89da2ff3 Guido Trotter
      # the value above.
1249 89da2ff3 Guido Trotter
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
1250 89da2ff3 Guido Trotter
      memory = mem_bytes / 1048576
1251 89da2ff3 Guido Trotter
    except errors.HypervisorError:
1252 89da2ff3 Guido Trotter
      pass
1253 89da2ff3 Guido Trotter
1254 fc84cd5d Guido Trotter
    return (instance_name, pid, memory, vcpus, istat, times)
1255 eb58f9b1 Guido Trotter
1256 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
1257 eb58f9b1 Guido Trotter
    """Get properties of all instances.
1258 eb58f9b1 Guido Trotter

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

1261 eb58f9b1 Guido Trotter
    """
1262 eb58f9b1 Guido Trotter
    data = []
1263 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1264 263b8de6 Guido Trotter
      try:
1265 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
1266 263b8de6 Guido Trotter
      except errors.HypervisorError:
1267 3bc145d8 Bernardo Dal Seno
        # Ignore exceptions due to instances being shut down
1268 263b8de6 Guido Trotter
        continue
1269 263b8de6 Guido Trotter
      if info:
1270 263b8de6 Guido Trotter
        data.append(info)
1271 eb58f9b1 Guido Trotter
    return data
1272 eb58f9b1 Guido Trotter
1273 a80a1d16 Dimitris Aragiorgis
  def _GenerateKVMBlockDevicesOptions(self, instance, kvm_disks,
1274 df07c18f Dimitris Aragiorgis
                                      kvmhelp, devlist):
1275 df07c18f Dimitris Aragiorgis
    """Generate KVM options regarding instance's block devices.
1276 df07c18f Dimitris Aragiorgis

1277 df07c18f Dimitris Aragiorgis
    @type instance: L{objects.Instance}
1278 df07c18f Dimitris Aragiorgis
    @param instance: the instance object
1279 a80a1d16 Dimitris Aragiorgis
    @type kvm_disks: list of tuples
1280 a80a1d16 Dimitris Aragiorgis
    @param kvm_disks: list of tuples [(disk, link_name)..]
1281 df07c18f Dimitris Aragiorgis
    @type kvmhelp: string
1282 df07c18f Dimitris Aragiorgis
    @param kvmhelp: output of kvm --help
1283 df07c18f Dimitris Aragiorgis
    @type devlist: string
1284 df07c18f Dimitris Aragiorgis
    @param devlist: output of kvm -device ?
1285 df07c18f Dimitris Aragiorgis
    @rtype: list
1286 df07c18f Dimitris Aragiorgis
    @return: list of command line options eventually used by kvm executable
1287 1b1a2905 Dimitris Aragiorgis

1288 df07c18f Dimitris Aragiorgis
    """
1289 1b1a2905 Dimitris Aragiorgis
    hvp = instance.hvparams
1290 df07c18f Dimitris Aragiorgis
    kernel_path = hvp[constants.HV_KERNEL_PATH]
1291 df07c18f Dimitris Aragiorgis
    if kernel_path:
1292 df07c18f Dimitris Aragiorgis
      boot_disk = False
1293 df07c18f Dimitris Aragiorgis
    else:
1294 df07c18f Dimitris Aragiorgis
      boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
1295 1b1a2905 Dimitris Aragiorgis
1296 1b1a2905 Dimitris Aragiorgis
    # whether this is an older KVM version that uses the boot=on flag
1297 1b1a2905 Dimitris Aragiorgis
    # on devices
1298 1b1a2905 Dimitris Aragiorgis
    needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1299 1b1a2905 Dimitris Aragiorgis
1300 1b1a2905 Dimitris Aragiorgis
    dev_opts = []
1301 49c3a39c Dimitris Aragiorgis
    device_driver = None
1302 1b1a2905 Dimitris Aragiorgis
    disk_type = hvp[constants.HV_DISK_TYPE]
1303 1b1a2905 Dimitris Aragiorgis
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
1304 1b1a2905 Dimitris Aragiorgis
      if_val = ",if=%s" % self._VIRTIO
1305 49c3a39c Dimitris Aragiorgis
      try:
1306 49c3a39c Dimitris Aragiorgis
        if self._VIRTIO_BLK_RE.search(devlist):
1307 2ef37146 Dimitris Aragiorgis
          if_val = ",if=none"
1308 49c3a39c Dimitris Aragiorgis
          # will be passed in -device option as driver
1309 49c3a39c Dimitris Aragiorgis
          device_driver = self._VIRTIO_BLK_PCI
1310 49c3a39c Dimitris Aragiorgis
      except errors.HypervisorError, _:
1311 49c3a39c Dimitris Aragiorgis
        pass
1312 1b1a2905 Dimitris Aragiorgis
    else:
1313 1b1a2905 Dimitris Aragiorgis
      if_val = ",if=%s" % disk_type
1314 1b1a2905 Dimitris Aragiorgis
    # Cache mode
1315 1b1a2905 Dimitris Aragiorgis
    disk_cache = hvp[constants.HV_DISK_CACHE]
1316 1b1a2905 Dimitris Aragiorgis
    if instance.disk_template in constants.DTS_EXT_MIRROR:
1317 1b1a2905 Dimitris Aragiorgis
      if disk_cache != "none":
1318 1b1a2905 Dimitris Aragiorgis
        # TODO: make this a hard error, instead of a silent overwrite
1319 1b1a2905 Dimitris Aragiorgis
        logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
1320 1b1a2905 Dimitris Aragiorgis
                        " to prevent shared storage corruption on migration",
1321 1b1a2905 Dimitris Aragiorgis
                        disk_cache)
1322 1b1a2905 Dimitris Aragiorgis
      cache_val = ",cache=none"
1323 1b1a2905 Dimitris Aragiorgis
    elif disk_cache != constants.HT_CACHE_DEFAULT:
1324 1b1a2905 Dimitris Aragiorgis
      cache_val = ",cache=%s" % disk_cache
1325 1b1a2905 Dimitris Aragiorgis
    else:
1326 1b1a2905 Dimitris Aragiorgis
      cache_val = ""
1327 af245c80 Dimitris Aragiorgis
    for idx, (cfdev, link_name) in enumerate(kvm_disks):
1328 1b1a2905 Dimitris Aragiorgis
      if cfdev.mode != constants.DISK_RDWR:
1329 1b1a2905 Dimitris Aragiorgis
        raise errors.HypervisorError("Instance has read-only disks which"
1330 1b1a2905 Dimitris Aragiorgis
                                     " are not supported by KVM")
1331 1b1a2905 Dimitris Aragiorgis
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
1332 1b1a2905 Dimitris Aragiorgis
      boot_val = ""
1333 1b1a2905 Dimitris Aragiorgis
      if boot_disk:
1334 1b1a2905 Dimitris Aragiorgis
        dev_opts.extend(["-boot", "c"])
1335 1b1a2905 Dimitris Aragiorgis
        boot_disk = False
1336 1b1a2905 Dimitris Aragiorgis
        if needs_boot_flag and disk_type != constants.HT_DISK_IDE:
1337 1b1a2905 Dimitris Aragiorgis
          boot_val = ",boot=on"
1338 bfdf145a Dimitris Aragiorgis
1339 bfdf145a Dimitris Aragiorgis
      # For ext we allow overriding disk_cache hypervisor params per disk
1340 bfdf145a Dimitris Aragiorgis
      disk_cache = cfdev.params.get("cache", None)
1341 bfdf145a Dimitris Aragiorgis
      if disk_cache:
1342 bfdf145a Dimitris Aragiorgis
        cache_val = ",cache=%s" % disk_cache
1343 1b1a2905 Dimitris Aragiorgis
      drive_val = "file=%s,format=raw%s%s%s" % \
1344 af245c80 Dimitris Aragiorgis
                  (link_name, if_val, boot_val, cache_val)
1345 1b1a2905 Dimitris Aragiorgis
1346 49c3a39c Dimitris Aragiorgis
      if device_driver:
1347 a80a1d16 Dimitris Aragiorgis
        # kvm_disks are the 4th entry of runtime file that did not exist in
1348 2ef37146 Dimitris Aragiorgis
        # the past. That means that cfdev should always have pci slot and
1349 2ef37146 Dimitris Aragiorgis
        # _GenerateDeviceKVMId() will not raise a exception.
1350 af245c80 Dimitris Aragiorgis
        kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_DISK,
1351 af245c80 Dimitris Aragiorgis
                                         cfdev, idx)
1352 2ef37146 Dimitris Aragiorgis
        drive_val += (",id=%s" % kvm_devid)
1353 af245c80 Dimitris Aragiorgis
        if cfdev.pci:
1354 af245c80 Dimitris Aragiorgis
          drive_val += (",bus=0,unit=%d" % cfdev.pci)
1355 2ef37146 Dimitris Aragiorgis
        dev_val = ("%s,drive=%s,id=%s" %
1356 2ef37146 Dimitris Aragiorgis
                   (device_driver, kvm_devid, kvm_devid))
1357 af245c80 Dimitris Aragiorgis
        if cfdev.pci:
1358 af245c80 Dimitris Aragiorgis
          dev_val += ",bus=pci.0,addr=%s" % hex(cfdev.pci)
1359 2ef37146 Dimitris Aragiorgis
        dev_opts.extend(["-device", dev_val])
1360 2ef37146 Dimitris Aragiorgis
1361 70dfdeea Dimitris Aragiorgis
      # TODO: export disk geometry in IDISK_PARAMS
1362 70dfdeea Dimitris Aragiorgis
      heads = cfdev.params.get('heads', None)
1363 70dfdeea Dimitris Aragiorgis
      secs = cfdev.params.get('secs', None)
1364 70dfdeea Dimitris Aragiorgis
      if heads and secs:
1365 70dfdeea Dimitris Aragiorgis
        nr_sectors = cfdev.size * 1024 * 1024 / 512
1366 70dfdeea Dimitris Aragiorgis
        cyls = nr_sectors / (int(heads) * int(secs))
1367 70dfdeea Dimitris Aragiorgis
        if cyls > 16383:
1368 70dfdeea Dimitris Aragiorgis
          cyls = 16383
1369 70dfdeea Dimitris Aragiorgis
        elif cyls < 2:
1370 70dfdeea Dimitris Aragiorgis
          cyls = 2
1371 70dfdeea Dimitris Aragiorgis
        if cyls and heads and secs:
1372 70dfdeea Dimitris Aragiorgis
          drive_val += (",cyls=%d,heads=%d,secs=%d" %
1373 70dfdeea Dimitris Aragiorgis
                        (cyls, int(heads), int(secs)))
1374 70dfdeea Dimitris Aragiorgis
1375 1b1a2905 Dimitris Aragiorgis
      dev_opts.extend(["-drive", drive_val])
1376 1b1a2905 Dimitris Aragiorgis
1377 1b1a2905 Dimitris Aragiorgis
    return dev_opts
1378 1b1a2905 Dimitris Aragiorgis
1379 b73f1c59 Guido Trotter
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused,
1380 b73f1c59 Guido Trotter
                          kvmhelp):
1381 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
1382 eb58f9b1 Guido Trotter

1383 b73f1c59 Guido Trotter
    @type kvmhelp: string
1384 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1385 839642c2 Iustin Pop
    @attention: this function must not have any side-effects; for
1386 839642c2 Iustin Pop
        example, it must not write to the filesystem, or read values
1387 839642c2 Iustin Pop
        from the current system the are expected to differ between
1388 839642c2 Iustin Pop
        nodes, since it is only run once at instance startup;
1389 839642c2 Iustin Pop
        actions/kvm arguments that can vary between systems should be
1390 839642c2 Iustin Pop
        done in L{_ExecuteKVMRuntime}
1391 839642c2 Iustin Pop

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

1733 38e250ba Guido Trotter
    """
1734 38e250ba Guido Trotter
    try:
1735 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1736 38e250ba Guido Trotter
                      data=data)
1737 90c024f6 Guido Trotter
    except EnvironmentError, err:
1738 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1739 38e250ba Guido Trotter
1740 02985c42 Dimitris Aragiorgis
  @classmethod
1741 02985c42 Dimitris Aragiorgis
  def _ReadKVMRuntime(cls, instance_name):
1742 38e250ba Guido Trotter
    """Read an instance's KVM runtime
1743 38e250ba Guido Trotter

1744 38e250ba Guido Trotter
    """
1745 38e250ba Guido Trotter
    try:
1746 02985c42 Dimitris Aragiorgis
      file_content = utils.ReadFile(cls._InstanceKVMRuntime(instance_name))
1747 90c024f6 Guido Trotter
    except EnvironmentError, err:
1748 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1749 38e250ba Guido Trotter
    return file_content
1750 38e250ba Guido Trotter
1751 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1752 38e250ba Guido Trotter
    """Save an instance's KVM runtime
1753 38e250ba Guido Trotter

1754 38e250ba Guido Trotter
    """
1755 a80a1d16 Dimitris Aragiorgis
    kvm_cmd, kvm_nics, hvparams, kvm_disks = kvm_runtime
1756 7115b660 Dimitris Aragiorgis
1757 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1758 a80a1d16 Dimitris Aragiorgis
    serialized_disks = [(blk.ToDict(), link)
1759 a80a1d16 Dimitris Aragiorgis
                            for blk, link in kvm_disks]
1760 7115b660 Dimitris Aragiorgis
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams,
1761 a80a1d16 Dimitris Aragiorgis
                                      serialized_disks))
1762 7115b660 Dimitris Aragiorgis
1763 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
1764 38e250ba Guido Trotter
1765 02985c42 Dimitris Aragiorgis
  @classmethod
1766 02985c42 Dimitris Aragiorgis
  def _LoadKVMRuntime(cls, instance_name, serialized_runtime=None):
1767 38e250ba Guido Trotter
    """Load an instance's KVM runtime
1768 38e250ba Guido Trotter

1769 38e250ba Guido Trotter
    """
1770 30e42c4e Guido Trotter
    if not serialized_runtime:
1771 02985c42 Dimitris Aragiorgis
      serialized_runtime = cls._ReadKVMRuntime(instance_name)
1772 7115b660 Dimitris Aragiorgis
1773 7115b660 Dimitris Aragiorgis
    return _AnalyzeSerializedRuntime(serialized_runtime)
1774 38e250ba Guido Trotter
1775 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1776 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
1777 76431533 Guido Trotter

1778 76431533 Guido Trotter
    @type name: string
1779 76431533 Guido Trotter
    @param name: instance name
1780 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1781 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1782 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1783 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1784 76431533 Guido Trotter

1785 76431533 Guido Trotter
    """
1786 5d9bfd87 Apollon Oikonomopoulos
    try:
1787 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1788 5d9bfd87 Apollon Oikonomopoulos
    finally:
1789 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
1790 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
1791 5d9bfd87 Apollon Oikonomopoulos
1792 76431533 Guido Trotter
    if result.failed:
1793 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1794 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
1795 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
1796 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
1797 76431533 Guido Trotter
1798 a80a1d16 Dimitris Aragiorgis
  # too many local variables
1799 7115b660 Dimitris Aragiorgis
  # pylint: disable=R0914
1800 b73f1c59 Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1801 839642c2 Iustin Pop
    """Execute a KVM cmd, after completing it with some last minute data.
1802 ee5f20b0 Guido Trotter

1803 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1804 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1805 b73f1c59 Guido Trotter
    @type kvmhelp: string
1806 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1807 30e42c4e Guido Trotter

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

2028 ee5f20b0 Guido Trotter
    """
2029 5905901c Iustin Pop
    self._CheckDown(instance.name)
2030 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2031 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2032 7238edb5 Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
2033 b73f1c59 Guido Trotter
                                           startup_paused, kvmhelp)
2034 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
2035 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
2036 ee5f20b0 Guido Trotter
2037 2a2d087a Michele Tartara
  def _CallMonitorCommand(self, instance_name, command, timeout=None):
2038 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
2039 6567aff3 Guido Trotter

2040 6567aff3 Guido Trotter
    """
2041 2a2d087a Michele Tartara
    if timeout is not None:
2042 2a2d087a Michele Tartara
      timeout_cmd = "timeout %s" % (timeout, )
2043 2a2d087a Michele Tartara
    else:
2044 2a2d087a Michele Tartara
      timeout_cmd = ""
2045 2a2d087a Michele Tartara
2046 eace6157 Michael Hanselmann
    # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
2047 eace6157 Michael Hanselmann
    # version. The monitor protocol is designed for human consumption, whereas
2048 eace6157 Michael Hanselmann
    # QMP is made for programmatic usage. In the worst case QMP can also
2049 eace6157 Michael Hanselmann
    # execute monitor commands. As it is, all calls to socat take at least
2050 eace6157 Michael Hanselmann
    # 500ms and likely more: socat can't detect the end of the reply and waits
2051 eace6157 Michael Hanselmann
    # for 500ms of no data received before exiting (500 ms is the default for
2052 eace6157 Michael Hanselmann
    # the "-t" parameter).
2053 874f6148 Michele Tartara
    socat = ("echo %s | %s %s STDIO UNIX-CONNECT:%s" %
2054 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
2055 874f6148 Michele Tartara
              timeout_cmd,
2056 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
2057 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
2058 874f6148 Michele Tartara
2059 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
2060 6567aff3 Guido Trotter
    if result.failed:
2061 afa9bb2e Michael Hanselmann
      msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
2062 afa9bb2e Michael Hanselmann
             " output: %s" %
2063 afa9bb2e Michael Hanselmann
             (command, instance_name, result.fail_reason, result.output))
2064 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
2065 6567aff3 Guido Trotter
2066 6567aff3 Guido Trotter
    return result
2067 6567aff3 Guido Trotter
2068 7dff7128 Dimitris Aragiorgis
  def _GetFreePCISlot(self, instance, dev):
2069 7dff7128 Dimitris Aragiorgis
    """Get the first available pci slot of a runnung instance.
2070 7dff7128 Dimitris Aragiorgis

2071 7dff7128 Dimitris Aragiorgis
    """
2072 7dff7128 Dimitris Aragiorgis
    slots = bitarray(32)
2073 7dff7128 Dimitris Aragiorgis
    slots.setall(False) # pylint: disable=E1101
2074 7dff7128 Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance.name, self._INFO_PCI_CMD)
2075 7dff7128 Dimitris Aragiorgis
    for line in output.stdout.splitlines():
2076 7dff7128 Dimitris Aragiorgis
      match = self._INFO_PCI_RE.search(line)
2077 7dff7128 Dimitris Aragiorgis
      if match:
2078 7dff7128 Dimitris Aragiorgis
        slot = int(match.group(1))
2079 7dff7128 Dimitris Aragiorgis
        slots[slot] = True
2080 7dff7128 Dimitris Aragiorgis
2081 7dff7128 Dimitris Aragiorgis
    [free] = slots.search(_AVAILABLE_PCI_SLOT, 1) # pylint: disable=E1101
2082 7dff7128 Dimitris Aragiorgis
    if not free:
2083 7dff7128 Dimitris Aragiorgis
      raise errors.HypervisorError("All PCI slots occupied")
2084 7dff7128 Dimitris Aragiorgis
2085 7dff7128 Dimitris Aragiorgis
    dev.pci = int(free)
2086 7dff7128 Dimitris Aragiorgis
2087 68169c48 Dimitris Aragiorgis
  def VerifyHotplugSupport(self, instance, action, dev_type):
2088 68169c48 Dimitris Aragiorgis
    """Verifies that hotplug is supported.
2089 a05ff8a2 Dimitris Aragiorgis

2090 a05ff8a2 Dimitris Aragiorgis
    Hotplug is *not* supported in case of:
2091 a05ff8a2 Dimitris Aragiorgis
     - security models and chroot (disk hotplug)
2092 a05ff8a2 Dimitris Aragiorgis
     - fdsend module is missing (nic hot-add)
2093 a05ff8a2 Dimitris Aragiorgis

2094 68169c48 Dimitris Aragiorgis
    @raise errors.HypervisorError: in one of the previous cases
2095 a05ff8a2 Dimitris Aragiorgis

2096 a05ff8a2 Dimitris Aragiorgis
    """
2097 a05ff8a2 Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2098 a05ff8a2 Dimitris Aragiorgis
      hvp = instance.hvparams
2099 a05ff8a2 Dimitris Aragiorgis
      security_model = hvp[constants.HV_SECURITY_MODEL]
2100 a05ff8a2 Dimitris Aragiorgis
      use_chroot = hvp[constants.HV_KVM_USE_CHROOT]
2101 a05ff8a2 Dimitris Aragiorgis
      if use_chroot:
2102 a05ff8a2 Dimitris Aragiorgis
        raise errors.HotplugError("Disk hotplug is not supported"
2103 a05ff8a2 Dimitris Aragiorgis
                                  " in case of chroot.")
2104 a05ff8a2 Dimitris Aragiorgis
      if security_model != constants.HT_SM_NONE:
2105 a05ff8a2 Dimitris Aragiorgis
        raise errors.HotplugError("Disk Hotplug is not supported in case"
2106 a05ff8a2 Dimitris Aragiorgis
                                  " security models are used.")
2107 a05ff8a2 Dimitris Aragiorgis
2108 a05ff8a2 Dimitris Aragiorgis
    if (dev_type == constants.HOTPLUG_TARGET_NIC and
2109 a05ff8a2 Dimitris Aragiorgis
        action == constants.HOTPLUG_ACTION_ADD and not fdsend):
2110 a05ff8a2 Dimitris Aragiorgis
      raise errors.HotplugError("Cannot hot-add NIC."
2111 a05ff8a2 Dimitris Aragiorgis
                                " fdsend python module is missing.")
2112 a05ff8a2 Dimitris Aragiorgis
2113 75b21ca0 Dimitris Aragiorgis
  def HotplugSupported(self, instance):
2114 75b21ca0 Dimitris Aragiorgis
    """Checks if hotplug is generally supported.
2115 75b21ca0 Dimitris Aragiorgis

2116 75b21ca0 Dimitris Aragiorgis
    Hotplug is *not* supported in case of:
2117 75b21ca0 Dimitris Aragiorgis
     - qemu versions < 1.0
2118 75b21ca0 Dimitris Aragiorgis
     - for stopped instances
2119 75b21ca0 Dimitris Aragiorgis

2120 75b21ca0 Dimitris Aragiorgis
    @raise errors.HypervisorError: in one of the previous cases
2121 75b21ca0 Dimitris Aragiorgis

2122 75b21ca0 Dimitris Aragiorgis
    """
2123 4eb33085 Dimitris Aragiorgis
    try:
2124 4eb33085 Dimitris Aragiorgis
      output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD)
2125 4eb33085 Dimitris Aragiorgis
    except errors.HypervisorError:
2126 4eb33085 Dimitris Aragiorgis
      raise errors.HotplugError("Instance is probably down")
2127 4eb33085 Dimitris Aragiorgis
2128 75b21ca0 Dimitris Aragiorgis
    # TODO: search for netdev_add, drive_add, device_add.....
2129 75b21ca0 Dimitris Aragiorgis
    match = self._INFO_VERSION_RE.search(output.stdout)
2130 75b21ca0 Dimitris Aragiorgis
    if not match:
2131 4eb33085 Dimitris Aragiorgis
      raise errors.HotplugError("Cannot parse qemu version via monitor")
2132 4eb33085 Dimitris Aragiorgis
2133 75b21ca0 Dimitris Aragiorgis
    v_major, v_min, _, _ = match.groups()
2134 75b21ca0 Dimitris Aragiorgis
    if (int(v_major), int(v_min)) < (1, 0):
2135 75b21ca0 Dimitris Aragiorgis
      raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0")
2136 75b21ca0 Dimitris Aragiorgis
2137 a30e9f99 Dimitris Aragiorgis
  def _CallHotplugCommands(self, name, cmds):
2138 a30e9f99 Dimitris Aragiorgis
    for c in cmds:
2139 070eec15 Dimitris Aragiorgis
      self._CallMonitorCommand(name, c)
2140 a30e9f99 Dimitris Aragiorgis
      time.sleep(1)
2141 a05ff8a2 Dimitris Aragiorgis
2142 070eec15 Dimitris Aragiorgis
  def _VerifyHotplugCommand(self, instance_name, device, dev_type,
2143 070eec15 Dimitris Aragiorgis
                            should_exist):
2144 070eec15 Dimitris Aragiorgis
    """Checks if a previous hotplug command has succeeded.
2145 070eec15 Dimitris Aragiorgis

2146 070eec15 Dimitris Aragiorgis
    It issues info pci monitor command and checks depending on should_exist
2147 070eec15 Dimitris Aragiorgis
    value if an entry with PCI slot and device ID is found or not.
2148 070eec15 Dimitris Aragiorgis

2149 070eec15 Dimitris Aragiorgis
    @raise errors.HypervisorError: if result is not the expected one
2150 070eec15 Dimitris Aragiorgis

2151 070eec15 Dimitris Aragiorgis
    """
2152 070eec15 Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance_name, self._INFO_PCI_CMD)
2153 070eec15 Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, device)
2154 070eec15 Dimitris Aragiorgis
    match = \
2155 070eec15 Dimitris Aragiorgis
      self._FIND_PCI_DEVICE_RE(device.pci, kvm_devid).search(output.stdout)
2156 070eec15 Dimitris Aragiorgis
    if match and not should_exist:
2157 070eec15 Dimitris Aragiorgis
      msg = "Device %s should have been removed but is still there" % kvm_devid
2158 070eec15 Dimitris Aragiorgis
      raise errors.HypervisorError(msg)
2159 070eec15 Dimitris Aragiorgis
2160 070eec15 Dimitris Aragiorgis
    if not match and should_exist:
2161 070eec15 Dimitris Aragiorgis
      msg = "Device %s should have been added but is missing" % kvm_devid
2162 070eec15 Dimitris Aragiorgis
      raise errors.HypervisorError(msg)
2163 070eec15 Dimitris Aragiorgis
2164 070eec15 Dimitris Aragiorgis
    logging.info("Device %s has been correctly hot-plugged", kvm_devid)
2165 070eec15 Dimitris Aragiorgis
2166 878ddc80 Dimitris Aragiorgis
  def HotAddDevice(self, instance, dev_type, device, extra, seq):
2167 878ddc80 Dimitris Aragiorgis
    """ Helper method to hot-add a new device
2168 878ddc80 Dimitris Aragiorgis

2169 878ddc80 Dimitris Aragiorgis
    It gets free pci slot generates the device name and invokes the
2170 878ddc80 Dimitris Aragiorgis
    device specific method.
2171 878ddc80 Dimitris Aragiorgis

2172 878ddc80 Dimitris Aragiorgis
    """
2173 878ddc80 Dimitris Aragiorgis
    # in case of hot-mod this is given
2174 878ddc80 Dimitris Aragiorgis
    if device.pci is None:
2175 878ddc80 Dimitris Aragiorgis
      self._GetFreePCISlot(instance, device)
2176 878ddc80 Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, device)
2177 02985c42 Dimitris Aragiorgis
    runtime = self._LoadKVMRuntime(instance.name)
2178 878ddc80 Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2179 a30e9f99 Dimitris Aragiorgis
      cmds = ["drive_add dummy file=%s,if=none,id=%s,format=raw" %
2180 a30e9f99 Dimitris Aragiorgis
                (extra, kvm_devid)]
2181 a30e9f99 Dimitris Aragiorgis
      cmds += ["device_add virtio-blk-pci,bus=pci.0,addr=%s,drive=%s,id=%s" %
2182 a30e9f99 Dimitris Aragiorgis
                (hex(device.pci), kvm_devid, kvm_devid)]
2183 878ddc80 Dimitris Aragiorgis
    elif dev_type == constants.HOTPLUG_TARGET_NIC:
2184 878ddc80 Dimitris Aragiorgis
      (tap, fd) = _OpenTap()
2185 878ddc80 Dimitris Aragiorgis
      self._ConfigureNIC(instance, seq, device, tap)
2186 878ddc80 Dimitris Aragiorgis
      self._PassTapFd(instance, fd, device)
2187 a30e9f99 Dimitris Aragiorgis
      cmds = ["netdev_add tap,id=%s,fd=%s" % (kvm_devid, kvm_devid)]
2188 878ddc80 Dimitris Aragiorgis
      args = "virtio-net-pci,bus=pci.0,addr=%s,mac=%s,netdev=%s,id=%s" % \
2189 878ddc80 Dimitris Aragiorgis
               (hex(device.pci), device.mac, kvm_devid, kvm_devid)
2190 a30e9f99 Dimitris Aragiorgis
      cmds += ["device_add %s" % args]
2191 878ddc80 Dimitris Aragiorgis
      utils.WriteFile(self._InstanceNICFile(instance.name, seq), data=tap)
2192 878ddc80 Dimitris Aragiorgis
2193 a30e9f99 Dimitris Aragiorgis
    self._CallHotplugCommands(instance.name, cmds)
2194 070eec15 Dimitris Aragiorgis
    self._VerifyHotplugCommand(instance.name, device, dev_type, True)
2195 878ddc80 Dimitris Aragiorgis
    # update relevant entries in runtime file
2196 878ddc80 Dimitris Aragiorgis
    index = _DEVICE_RUNTIME_INDEX[dev_type]
2197 878ddc80 Dimitris Aragiorgis
    entry = _RUNTIME_ENTRY[dev_type](device, extra)
2198 878ddc80 Dimitris Aragiorgis
    runtime[index].append(entry)
2199 878ddc80 Dimitris Aragiorgis
    self._SaveKVMRuntime(instance, runtime)
2200 878ddc80 Dimitris Aragiorgis
2201 878ddc80 Dimitris Aragiorgis
  def HotDelDevice(self, instance, dev_type, device, _, seq):
2202 878ddc80 Dimitris Aragiorgis
    """ Helper method for hot-del device
2203 878ddc80 Dimitris Aragiorgis

2204 878ddc80 Dimitris Aragiorgis
    It gets device info from runtime file, generates the device name and
2205 878ddc80 Dimitris Aragiorgis
    invokes the device specific method.
2206 878ddc80 Dimitris Aragiorgis

2207 878ddc80 Dimitris Aragiorgis
    """
2208 02985c42 Dimitris Aragiorgis
    runtime = self._LoadKVMRuntime(instance.name)
2209 878ddc80 Dimitris Aragiorgis
    entry = _GetExistingDeviceInfo(dev_type, device, runtime)
2210 878ddc80 Dimitris Aragiorgis
    kvm_device = _RUNTIME_DEVICE[dev_type](entry)
2211 878ddc80 Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, kvm_device)
2212 878ddc80 Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2213 a30e9f99 Dimitris Aragiorgis
      cmds = ["device_del %s" % kvm_devid]
2214 a30e9f99 Dimitris Aragiorgis
      cmds += ["drive_del %s" % kvm_devid]
2215 878ddc80 Dimitris Aragiorgis
    elif dev_type == constants.HOTPLUG_TARGET_NIC:
2216 a30e9f99 Dimitris Aragiorgis
      cmds = ["device_del %s" % kvm_devid]
2217 a30e9f99 Dimitris Aragiorgis
      cmds += ["netdev_del %s" % kvm_devid]
2218 878ddc80 Dimitris Aragiorgis
      utils.RemoveFile(self._InstanceNICFile(instance.name, seq))
2219 a30e9f99 Dimitris Aragiorgis
    self._CallHotplugCommands(instance.name, cmds)
2220 070eec15 Dimitris Aragiorgis
    self._VerifyHotplugCommand(instance.name, kvm_device, dev_type, False)
2221 878ddc80 Dimitris Aragiorgis
    index = _DEVICE_RUNTIME_INDEX[dev_type]
2222 878ddc80 Dimitris Aragiorgis
    runtime[index].remove(entry)
2223 878ddc80 Dimitris Aragiorgis
    self._SaveKVMRuntime(instance, runtime)
2224 878ddc80 Dimitris Aragiorgis
2225 878ddc80 Dimitris Aragiorgis
    return kvm_device.pci
2226 878ddc80 Dimitris Aragiorgis
2227 878ddc80 Dimitris Aragiorgis
  def HotModDevice(self, instance, dev_type, device, _, seq):
2228 878ddc80 Dimitris Aragiorgis
    """ Helper method for hot-mod device
2229 878ddc80 Dimitris Aragiorgis

2230 878ddc80 Dimitris Aragiorgis
    It gets device info from runtime file, generates the device name and
2231 878ddc80 Dimitris Aragiorgis
    invokes the device specific method. Currently only NICs support hot-mod
2232 878ddc80 Dimitris Aragiorgis

2233 878ddc80 Dimitris Aragiorgis
    """
2234 878ddc80 Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_NIC:
2235 878ddc80 Dimitris Aragiorgis
      # putting it back in the same pci slot
2236 878ddc80 Dimitris Aragiorgis
      device.pci = self.HotDelDevice(instance, dev_type, device, _, seq)
2237 878ddc80 Dimitris Aragiorgis
      # TODO: remove sleep when socat gets removed
2238 878ddc80 Dimitris Aragiorgis
      self.HotAddDevice(instance, dev_type, device, _, seq)
2239 878ddc80 Dimitris Aragiorgis
2240 878ddc80 Dimitris Aragiorgis
  def _PassTapFd(self, instance, fd, nic):
2241 878ddc80 Dimitris Aragiorgis
    """Pass file descriptor to kvm process via monitor socket using SCM_RIGHTS
2242 878ddc80 Dimitris Aragiorgis

2243 878ddc80 Dimitris Aragiorgis
    """
2244 878ddc80 Dimitris Aragiorgis
    # TODO: factor out code related to unix sockets.
2245 878ddc80 Dimitris Aragiorgis
    #       squash common parts between monitor and qmp
2246 878ddc80 Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_NIC, nic)
2247 878ddc80 Dimitris Aragiorgis
    command = "getfd %s\n" % kvm_devid
2248 878ddc80 Dimitris Aragiorgis
    fds = [fd]
2249 878ddc80 Dimitris Aragiorgis
    logging.info("%s", fds)
2250 878ddc80 Dimitris Aragiorgis
    try:
2251 878ddc80 Dimitris Aragiorgis
      monsock = MonitorSocket(self._InstanceMonitor(instance.name))
2252 878ddc80 Dimitris Aragiorgis
      monsock.connect()
2253 878ddc80 Dimitris Aragiorgis
      fdsend.sendfds(monsock.sock, command, fds=fds)
2254 878ddc80 Dimitris Aragiorgis
    finally:
2255 878ddc80 Dimitris Aragiorgis
      monsock.close()
2256 878ddc80 Dimitris Aragiorgis
2257 b52d85c1 Guido Trotter
  @classmethod
2258 585c8187 Guido Trotter
  def _ParseKVMVersion(cls, text):
2259 585c8187 Guido Trotter
    """Parse the KVM version from the --help output.
2260 585c8187 Guido Trotter

2261 585c8187 Guido Trotter
    @type text: string
2262 585c8187 Guido Trotter
    @param text: output of kvm --help
2263 585c8187 Guido Trotter
    @return: (version, v_maj, v_min, v_rev)
2264 5c3d5dfd Iustin Pop
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
2265 585c8187 Guido Trotter

2266 585c8187 Guido Trotter
    """
2267 585c8187 Guido Trotter
    match = cls._VERSION_RE.search(text.splitlines()[0])
2268 585c8187 Guido Trotter
    if not match:
2269 585c8187 Guido Trotter
      raise errors.HypervisorError("Unable to get KVM version")
2270 585c8187 Guido Trotter
2271 585c8187 Guido Trotter
    v_all = match.group(0)
2272 585c8187 Guido Trotter
    v_maj = int(match.group(1))
2273 585c8187 Guido Trotter
    v_min = int(match.group(2))
2274 585c8187 Guido Trotter
    if match.group(4):
2275 585c8187 Guido Trotter
      v_rev = int(match.group(4))
2276 585c8187 Guido Trotter
    else:
2277 585c8187 Guido Trotter
      v_rev = 0
2278 585c8187 Guido Trotter
    return (v_all, v_maj, v_min, v_rev)
2279 585c8187 Guido Trotter
2280 585c8187 Guido Trotter
  @classmethod
2281 6e043e60 Guido Trotter
  def _GetKVMOutput(cls, kvm_path, option):
2282 6e043e60 Guido Trotter
    """Return the output of a kvm invocation
2283 e3b89628 Guido Trotter

2284 bc0fed4b Guido Trotter
    @type kvm_path: string
2285 bc0fed4b Guido Trotter
    @param kvm_path: path to the kvm executable
2286 bc0fed4b Guido Trotter
    @type option: a key of _KVMOPTS_CMDS
2287 bc0fed4b Guido Trotter
    @param option: kvm option to fetch the output from
2288 6e043e60 Guido Trotter
    @return: output a supported kvm invocation
2289 e3b89628 Guido Trotter
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
2290 e3b89628 Guido Trotter

2291 e3b89628 Guido Trotter
    """
2292 6e043e60 Guido Trotter
    assert option in cls._KVMOPTS_CMDS, "Invalid output option"
2293 6e043e60 Guido Trotter
2294 bc0fed4b Guido Trotter
    optlist, can_fail = cls._KVMOPTS_CMDS[option]
2295 bc0fed4b Guido Trotter
2296 bc0fed4b Guido Trotter
    result = utils.RunCmd([kvm_path] + optlist)
2297 bc0fed4b Guido Trotter
    if result.failed and not can_fail:
2298 af89fa76 Helga Velroyen
      raise errors.HypervisorError("Unable to get KVM %s output" %
2299 3ddc7650 Jose A. Lopes
                                    " ".join(optlist))
2300 e3b89628 Guido Trotter
    return result.output
2301 e3b89628 Guido Trotter
2302 e3b89628 Guido Trotter
  @classmethod
2303 3b59ec02 Guido Trotter
  def _GetKVMVersion(cls, kvm_path):
2304 d7e4a2b1 Andrea Spadaccini
    """Return the installed KVM version.
2305 b52d85c1 Guido Trotter

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

2309 b52d85c1 Guido Trotter
    """
2310 6e043e60 Guido Trotter
    return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
2311 82e3bf85 Dimitris Aragiorgis
2312 82e3bf85 Dimitris Aragiorgis
  @classmethod
2313 82e3bf85 Dimitris Aragiorgis
  def _GetDefaultMachineVersion(cls, kvm_path):
2314 82e3bf85 Dimitris Aragiorgis
    """Return the default hardware revision (e.g. pc-1.1)
2315 82e3bf85 Dimitris Aragiorgis

2316 82e3bf85 Dimitris Aragiorgis
    """
2317 6e043e60 Guido Trotter
    output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2318 82e3bf85 Dimitris Aragiorgis
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
2319 82e3bf85 Dimitris Aragiorgis
    if match:
2320 82e3bf85 Dimitris Aragiorgis
      return match.group(1)
2321 82e3bf85 Dimitris Aragiorgis
    else:
2322 82e3bf85 Dimitris Aragiorgis
      return "pc"
2323 82e3bf85 Dimitris Aragiorgis
2324 874f6148 Michele Tartara
  def StopInstance(self, instance, force=False, retry=False, name=None,
2325 874f6148 Michele Tartara
                   timeout=None):
2326 eb58f9b1 Guido Trotter
    """Stop an instance.
2327 eb58f9b1 Guido Trotter

2328 eb58f9b1 Guido Trotter
    """
2329 874f6148 Michele Tartara
    assert(timeout is None or force is not None)
2330 874f6148 Michele Tartara
2331 bbcf7ad0 Iustin Pop
    if name is not None and not force:
2332 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
2333 bbcf7ad0 Iustin Pop
    if name is None:
2334 bbcf7ad0 Iustin Pop
      name = instance.name
2335 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
2336 bbcf7ad0 Iustin Pop
    else:
2337 bbcf7ad0 Iustin Pop
      acpi = False
2338 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
2339 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
2340 bbcf7ad0 Iustin Pop
      if force or not acpi:
2341 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
2342 eb58f9b1 Guido Trotter
      else:
2343 874f6148 Michele Tartara
        self._CallMonitorCommand(name, "system_powerdown", timeout)
2344 eb58f9b1 Guido Trotter
2345 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
2346 8904b35c Guido Trotter
    """Cleanup after a stopped instance
2347 8904b35c Guido Trotter

2348 8904b35c Guido Trotter
    """
2349 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
2350 8904b35c Guido Trotter
    if pid > 0 and alive:
2351 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
2352 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
2353 eb58f9b1 Guido Trotter
2354 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
2355 eb58f9b1 Guido Trotter
    """Reboot an instance.
2356 eb58f9b1 Guido Trotter

2357 eb58f9b1 Guido Trotter
    """
2358 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
2359 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
2360 eb58f9b1 Guido Trotter
    # to shutdown and restart.
2361 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
2362 1f8b3a27 Guido Trotter
    if not alive:
2363 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
2364 78411c60 Iustin Pop
                                   " not running" % instance.name)
2365 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
2366 f02881e0 Guido Trotter
    # ...first load it...
2367 02985c42 Dimitris Aragiorgis
    kvm_runtime = self._LoadKVMRuntime(instance.name)
2368 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
2369 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
2370 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
2371 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
2372 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
2373 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2374 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2375 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
2376 eb58f9b1 Guido Trotter
2377 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
2378 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
2379 30e42c4e Guido Trotter

2380 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2381 30e42c4e Guido Trotter
    @param instance: instance to be migrated
2382 30e42c4e Guido Trotter
    @rtype: string
2383 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
2384 30e42c4e Guido Trotter

2385 30e42c4e Guido Trotter
    """
2386 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
2387 30e42c4e Guido Trotter
2388 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
2389 30e42c4e Guido Trotter
    """Prepare to accept an instance.
2390 30e42c4e Guido Trotter

2391 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2392 30e42c4e Guido Trotter
    @param instance: instance to be accepted
2393 30e42c4e Guido Trotter
    @type info: string
2394 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
2395 30e42c4e Guido Trotter
    @type target: string
2396 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
2397 30e42c4e Guido Trotter

2398 30e42c4e Guido Trotter
    """
2399 02985c42 Dimitris Aragiorgis
    kvm_runtime = self._LoadKVMRuntime(instance.name, serialized_runtime=info)
2400 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
2401 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2402 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2403 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
2404 b73f1c59 Guido Trotter
                            incoming=incoming_address)
2405 30e42c4e Guido Trotter
2406 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
2407 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
2408 30e42c4e Guido Trotter

2409 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
2410 30e42c4e Guido Trotter

2411 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2412 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
2413 30e42c4e Guido Trotter

2414 30e42c4e Guido Trotter
    """
2415 30e42c4e Guido Trotter
    if success:
2416 02985c42 Dimitris Aragiorgis
      kvm_runtime = self._LoadKVMRuntime(instance.name, serialized_runtime=info)
2417 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
2418 5d9bfd87 Apollon Oikonomopoulos
2419 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
2420 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
2421 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
2422 cc8a8ed7 Apollon Oikonomopoulos
          continue
2423 5d9bfd87 Apollon Oikonomopoulos
        try:
2424 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
2425 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
2426 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
2427 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
2428 5d9bfd87 Apollon Oikonomopoulos
          continue
2429 5d9bfd87 Apollon Oikonomopoulos
        try:
2430 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
2431 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
2432 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
2433 5d9bfd87 Apollon Oikonomopoulos
2434 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
2435 30e42c4e Guido Trotter
    else:
2436 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
2437 30e42c4e Guido Trotter
2438 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
2439 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
2440 30e42c4e Guido Trotter

2441 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
2442 30e42c4e Guido Trotter
    currently running.
2443 30e42c4e Guido Trotter

2444 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
2445 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
2446 30e42c4e Guido Trotter
    @type target: string
2447 30e42c4e Guido Trotter
    @param target: ip address of the target node
2448 30e42c4e Guido Trotter
    @type live: boolean
2449 30e42c4e Guido Trotter
    @param live: perform a live migration
2450 30e42c4e Guido Trotter

2451 30e42c4e Guido Trotter
    """
2452 58d38b02 Iustin Pop
    instance_name = instance.name
2453 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
2454 6a1434d7 Andrea Spadaccini
    _, _, alive = self._InstancePidAlive(instance_name)
2455 30e42c4e Guido Trotter
    if not alive:
2456 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
2457 30e42c4e Guido Trotter
2458 30e42c4e Guido Trotter
    if not live:
2459 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
2460 30e42c4e Guido Trotter
2461 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
2462 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
2463 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2464 e43d4f9f Apollon Oikonomopoulos
2465 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
2466 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
2467 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2468 e43d4f9f Apollon Oikonomopoulos
2469 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
2470 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
2471 30e42c4e Guido Trotter
2472 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
2473 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
2474 6a1434d7 Andrea Spadaccini

2475 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2476 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
2477 6a1434d7 Andrea Spadaccini
    @type success: bool
2478 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
2479 6a1434d7 Andrea Spadaccini
    @type live: bool
2480 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
2481 6a1434d7 Andrea Spadaccini

2482 6a1434d7 Andrea Spadaccini
    """
2483 6a1434d7 Andrea Spadaccini
    if success:
2484 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
2485 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
2486 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
2487 6a1434d7 Andrea Spadaccini
    elif live:
2488 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
2489 6a1434d7 Andrea Spadaccini
2490 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
2491 6a1434d7 Andrea Spadaccini
    """Get the migration status
2492 6a1434d7 Andrea Spadaccini

2493 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2494 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
2495 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
2496 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
2497 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
2498 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
2499 6a1434d7 Andrea Spadaccini

2500 6a1434d7 Andrea Spadaccini
    """
2501 d0c8c01d Iustin Pop
    info_command = "info migrate"
2502 6a1434d7 Andrea Spadaccini
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
2503 6a1434d7 Andrea Spadaccini
      result = self._CallMonitorCommand(instance.name, info_command)
2504 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
2505 30e42c4e Guido Trotter
      if not match:
2506 c4e388a5 Guido Trotter
        if not result.stdout:
2507 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
2508 c4e388a5 Guido Trotter
        else:
2509 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
2510 c4e388a5 Guido Trotter
                          result.stdout)
2511 30e42c4e Guido Trotter
      else:
2512 30e42c4e Guido Trotter
        status = match.group(1)
2513 6a1434d7 Andrea Spadaccini
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
2514 6a1434d7 Andrea Spadaccini
          migration_status = objects.MigrationStatus(status=status)
2515 61643226 Andrea Spadaccini
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
2516 61643226 Andrea Spadaccini
          if match:
2517 61643226 Andrea Spadaccini
            migration_status.transferred_ram = match.group("transferred")
2518 61643226 Andrea Spadaccini
            migration_status.total_ram = match.group("total")
2519 61643226 Andrea Spadaccini
2520 6a1434d7 Andrea Spadaccini
          return migration_status
2521 30e42c4e Guido Trotter
2522 6a1434d7 Andrea Spadaccini
        logging.warning("KVM: unknown migration status '%s'", status)
2523 6a1434d7 Andrea Spadaccini
2524 6a1434d7 Andrea Spadaccini
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
2525 6a1434d7 Andrea Spadaccini
2526 62457f51 Iustin Pop
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
2527 30e42c4e Guido Trotter
2528 3d836750 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
2529 3d836750 Guido Trotter
    """Balloon an instance memory to a certain value.
2530 3d836750 Guido Trotter

2531 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
2532 3d836750 Guido Trotter
    @param instance: instance to be accepted
2533 3d836750 Guido Trotter
    @type mem: int
2534 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
2535 3d836750 Guido Trotter

2536 3d836750 Guido Trotter
    """
2537 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2538 3d836750 Guido Trotter
2539 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
2540 eb58f9b1 Guido Trotter
    """Return information about the node.
2541 eb58f9b1 Guido Trotter

2542 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
2543 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
2544 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
2545 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
2546 34fbc862 Andrea Spadaccini
          - hv_version: the hypervisor version in the form (major, minor,
2547 34fbc862 Andrea Spadaccini
                        revision)
2548 eb58f9b1 Guido Trotter

2549 eb58f9b1 Guido Trotter
    """
2550 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
2551 4b9638dc Guido Trotter
    # FIXME: this is the global kvm version, but the actual version can be
2552 4b9638dc Guido Trotter
    # customized as an hv parameter. we should use the nodegroup's default kvm
2553 4b9638dc Guido Trotter
    # path parameter here.
2554 3b59ec02 Guido Trotter
    _, v_major, v_min, v_rev = self._GetKVMVersion(constants.KVM_PATH)
2555 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2556 34fbc862 Andrea Spadaccini
    return result
2557 eb58f9b1 Guido Trotter
2558 637ce7f9 Guido Trotter
  @classmethod
2559 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
2560 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
2561 eb58f9b1 Guido Trotter

2562 eb58f9b1 Guido Trotter
    """
2563 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2564 9d9bded1 Michael Hanselmann
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2565 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2566 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2567 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
2568 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2569 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2570 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
2571 55cc0a44 Michael Hanselmann
                                     host=instance.primary_node,
2572 052783ff Michael Hanselmann
                                     user=constants.SSH_CONSOLE_USER,
2573 55cc0a44 Michael Hanselmann
                                     command=cmd)
2574 3be34f57 Guido Trotter
2575 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2576 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2577 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
2578 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2579 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
2580 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
2581 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
2582 55cc0a44 Michael Hanselmann
                                     display=display)
2583 55cc0a44 Michael Hanselmann
2584 4d2cdb5a Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2585 4d2cdb5a Andrea Spadaccini
    if spice_bind:
2586 4d2cdb5a Andrea Spadaccini
      return objects.InstanceConsole(instance=instance.name,
2587 4d2cdb5a Andrea Spadaccini
                                     kind=constants.CONS_SPICE,
2588 4d2cdb5a Andrea Spadaccini
                                     host=spice_bind,
2589 4d2cdb5a Andrea Spadaccini
                                     port=instance.network_port)
2590 4d2cdb5a Andrea Spadaccini
2591 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
2592 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
2593 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
2594 55cc0a44 Michael Hanselmann
                                            instance.name))
2595 eb58f9b1 Guido Trotter
2596 eb58f9b1 Guido Trotter
  def Verify(self):
2597 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
2598 eb58f9b1 Guido Trotter

2599 cd04dfd2 Michael Hanselmann
    Check that the required binaries exist.
2600 cd04dfd2 Michael Hanselmann

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

2603 eb58f9b1 Guido Trotter
    """
2604 1f4b9d39 Iustin Pop
    msgs = []
2605 1f4b9d39 Iustin Pop
    # FIXME: this is the global kvm binary, but the actual path can be
2606 1f4b9d39 Iustin Pop
    # customized as an hv parameter; we should use the nodegroup's
2607 1f4b9d39 Iustin Pop
    # default kvm path parameter here.
2608 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
2609 1f4b9d39 Iustin Pop
      msgs.append("The KVM binary ('%s') does not exist" % constants.KVM_PATH)
2610 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2611 1f4b9d39 Iustin Pop
      msgs.append("The socat binary ('%s') does not exist" %
2612 1f4b9d39 Iustin Pop
                  constants.SOCAT_PATH)
2613 1f4b9d39 Iustin Pop
2614 1f4b9d39 Iustin Pop
    return self._FormatVerifyResults(msgs)
2615 14aa53cb Guido Trotter
2616 6b5605e8 Iustin Pop
  @classmethod
2617 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2618 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2619 6b5605e8 Iustin Pop

2620 6b5605e8 Iustin Pop
    @type hvparams:  dict
2621 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2622 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2623 6b5605e8 Iustin Pop

2624 6b5605e8 Iustin Pop
    """
2625 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2626 6b5605e8 Iustin Pop
2627 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
2628 df5ab9f0 Guido Trotter
    if kernel_path:
2629 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
2630 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
2631 205ab586 Iustin Pop
                                     " if a kernel is defined")
2632 6b5605e8 Iustin Pop
2633 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
2634 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
2635 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
2636 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
2637 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
2638 66d5dbef Guido Trotter
2639 14fd6c81 Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2640 14fd6c81 Guido Trotter
      serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2641 14fd6c81 Guido Trotter
      valid_speeds = constants.VALID_SERIAL_SPEEDS
2642 14fd6c81 Guido Trotter
      if not serial_speed or serial_speed not in valid_speeds:
2643 14fd6c81 Guido Trotter
        raise errors.HypervisorError("Invalid serial console speed, must be"
2644 14fd6c81 Guido Trotter
                                     " one of: %s" %
2645 14fd6c81 Guido Trotter
                                     utils.CommaJoin(valid_speeds))
2646 14fd6c81 Guido Trotter
2647 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2648 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
2649 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2650 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2651 835528af Iustin Pop
                                   " ISO path")
2652 f5118ade Iustin Pop
2653 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2654 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2655 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
2656 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
2657 d19d94db Guido Trotter
                                     " must be specified")
2658 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
2659 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
2660 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
2661 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
2662 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
2663 d19d94db Guido Trotter
2664 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2665 b451c4c7 Andrea Spadaccini
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2666 b1cb62bd Andrea Spadaccini
    if spice_bind:
2667 b1cb62bd Andrea Spadaccini
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2668 b1cb62bd Andrea Spadaccini
        # if an IP version is specified, the spice_bind parameter must be an
2669 b1cb62bd Andrea Spadaccini
        # IP of that family
2670 b1cb62bd Andrea Spadaccini
        if (netutils.IP4Address.IsValid(spice_bind) and
2671 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP4_VERSION):
2672 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv4 address (%s), but"
2673 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2674 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2675 b1cb62bd Andrea Spadaccini
2676 b1cb62bd Andrea Spadaccini
        if (netutils.IP6Address.IsValid(spice_bind) and
2677 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP6_VERSION):
2678 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv6 address (%s), but"
2679 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2680 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2681 b451c4c7 Andrea Spadaccini
    else:
2682 0e1b03b9 Andrea Spadaccini
      # All the other SPICE parameters depend on spice_bind being set. Raise an
2683 0e1b03b9 Andrea Spadaccini
      # error if any of them is set without it.
2684 07788a0b Michael Hanselmann
      for param in _SPICE_ADDITIONAL_PARAMS:
2685 0e1b03b9 Andrea Spadaccini
        if hvparams[param]:
2686 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: %s requires %s to be set" %
2687 0e1b03b9 Andrea Spadaccini
                                       (param, constants.HV_KVM_SPICE_BIND))
2688 b1cb62bd Andrea Spadaccini
2689 d19d94db Guido Trotter
  @classmethod
2690 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
2691 d19d94db Guido Trotter
    """Check the given parameters for validity.
2692 d19d94db Guido Trotter

2693 d19d94db Guido Trotter
    @type hvparams:  dict
2694 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2695 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2696 d19d94db Guido Trotter

2697 d19d94db Guido Trotter
    """
2698 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2699 d19d94db Guido Trotter
2700 82e3bf85 Dimitris Aragiorgis
    kvm_path = hvparams[constants.HV_KVM_PATH]
2701 82e3bf85 Dimitris Aragiorgis
2702 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2703 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2704 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2705 d19d94db Guido Trotter
      try:
2706 1feb39ec Guido Trotter
        pwd.getpwnam(username)
2707 d19d94db Guido Trotter
      except KeyError:
2708 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
2709 d19d94db Guido Trotter
                                     % username)
2710 d19d94db Guido Trotter
2711 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2712 b1cb62bd Andrea Spadaccini
    if spice_bind:
2713 b1cb62bd Andrea Spadaccini
      # only one of VNC and SPICE can be used currently.
2714 b1cb62bd Andrea Spadaccini
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2715 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("Both SPICE and VNC are configured, but"
2716 b1cb62bd Andrea Spadaccini
                                     " only one of them can be used at a"
2717 afa9bb2e Michael Hanselmann
                                     " given time")
2718 b1cb62bd Andrea Spadaccini
2719 3b59ec02 Guido Trotter
      # check that KVM supports SPICE
2720 6e043e60 Guido Trotter
      kvmhelp = cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP)
2721 0ad7f5d8 Guido Trotter
      if not cls._SPICE_RE.search(kvmhelp):
2722 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE is configured, but it is not"
2723 afa9bb2e Michael Hanselmann
                                     " supported according to 'kvm --help'")
2724 b1cb62bd Andrea Spadaccini
2725 b1cb62bd Andrea Spadaccini
      # if spice_bind is not an IP address, it must be a valid interface
2726 afa9bb2e Michael Hanselmann
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind) or
2727 afa9bb2e Michael Hanselmann
                       netutils.IP6Address.IsValid(spice_bind))
2728 b1cb62bd Andrea Spadaccini
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2729 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE: The %s parameter must be either"
2730 b1cb62bd Andrea Spadaccini
                                     " a valid IP address or interface name" %
2731 b1cb62bd Andrea Spadaccini
                                     constants.HV_KVM_SPICE_BIND)
2732 b1cb62bd Andrea Spadaccini
2733 82e3bf85 Dimitris Aragiorgis
    machine_version = hvparams[constants.HV_KVM_MACHINE_VERSION]
2734 82e3bf85 Dimitris Aragiorgis
    if machine_version:
2735 6e043e60 Guido Trotter
      output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2736 82e3bf85 Dimitris Aragiorgis
      if not cls._CHECK_MACHINE_VERSION_RE(machine_version).search(output):
2737 82e3bf85 Dimitris Aragiorgis
        raise errors.HypervisorError("Unsupported machine version: %s" %
2738 82e3bf85 Dimitris Aragiorgis
                                     machine_version)
2739 82e3bf85 Dimitris Aragiorgis
2740 f5118ade Iustin Pop
  @classmethod
2741 f5118ade Iustin Pop
  def PowercycleNode(cls):
2742 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
2743 f5118ade Iustin Pop

2744 f5118ade Iustin Pop
    """
2745 f5118ade Iustin Pop
    cls.LinuxPowercycle()