Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 653bc0f1

History | View | Annotate | Download (99.6 kB)

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

24 eb58f9b1 Guido Trotter
"""
25 eb58f9b1 Guido Trotter
26 547a63b7 Balazs Lecz
import errno
27 eb58f9b1 Guido Trotter
import os
28 eb58f9b1 Guido Trotter
import os.path
29 eb58f9b1 Guido Trotter
import re
30 eb58f9b1 Guido Trotter
import tempfile
31 6567aff3 Guido Trotter
import time
32 30e42c4e Guido Trotter
import logging
33 d19d94db Guido Trotter
import pwd
34 199b2053 Apollon Oikonomopoulos
import struct
35 199b2053 Apollon Oikonomopoulos
import fcntl
36 5d9bfd87 Apollon Oikonomopoulos
import shutil
37 91c10532 Andrea Spadaccini
import socket
38 fc84cd5d Guido Trotter
import stat
39 91c10532 Andrea Spadaccini
import StringIO
40 2615646c Dimitris Aragiorgis
from bitarray import bitarray
41 b693125f Tsachy Shacham
try:
42 471a31b6 Andrea Spadaccini
  import affinity   # pylint: disable=F0401
43 b693125f Tsachy Shacham
except ImportError:
44 b693125f Tsachy Shacham
  affinity = None
45 97cd9092 Dimitris Aragiorgis
try:
46 97cd9092 Dimitris Aragiorgis
  import fdsend   # pylint: disable=F0401
47 97cd9092 Dimitris Aragiorgis
except ImportError:
48 97cd9092 Dimitris Aragiorgis
  fdsend = None
49 eb58f9b1 Guido Trotter
50 eb58f9b1 Guido Trotter
from ganeti import utils
51 eb58f9b1 Guido Trotter
from ganeti import constants
52 eb58f9b1 Guido Trotter
from ganeti import errors
53 38e250ba Guido Trotter
from ganeti import serializer
54 38e250ba Guido Trotter
from ganeti import objects
55 76431533 Guido Trotter
from ganeti import uidpool
56 76431533 Guido Trotter
from ganeti import ssconf
57 a744b676 Manuel Franceschini
from ganeti import netutils
58 9d9bded1 Michael Hanselmann
from ganeti import pathutils
59 9d9bded1 Michael Hanselmann
from ganeti.hypervisor import hv_base
60 5d9bfd87 Apollon Oikonomopoulos
from ganeti.utils import wrapper as utils_wrapper
61 eb58f9b1 Guido Trotter
62 eb58f9b1 Guido Trotter
63 0e1e0b6a Michael Hanselmann
_KVM_NETWORK_SCRIPT = pathutils.CONF_DIR + "/kvm-vif-bridge"
64 b693125f Tsachy Shacham
_KVM_START_PAUSED_FLAG = "-S"
65 748e4b5a Michael Hanselmann
66 199b2053 Apollon Oikonomopoulos
# TUN/TAP driver constants, taken from <linux/if_tun.h>
67 199b2053 Apollon Oikonomopoulos
# They are architecture-independent and already hardcoded in qemu-kvm source,
68 199b2053 Apollon Oikonomopoulos
# so we can safely include them here.
69 199b2053 Apollon Oikonomopoulos
TUNSETIFF = 0x400454ca
70 199b2053 Apollon Oikonomopoulos
TUNGETIFF = 0x800454d2
71 199b2053 Apollon Oikonomopoulos
TUNGETFEATURES = 0x800454cf
72 199b2053 Apollon Oikonomopoulos
IFF_TAP = 0x0002
73 199b2053 Apollon Oikonomopoulos
IFF_NO_PI = 0x1000
74 199b2053 Apollon Oikonomopoulos
IFF_VNET_HDR = 0x4000
75 199b2053 Apollon Oikonomopoulos
76 07788a0b Michael Hanselmann
#: SPICE parameters which depend on L{constants.HV_KVM_SPICE_BIND}
77 07788a0b Michael Hanselmann
_SPICE_ADDITIONAL_PARAMS = frozenset([
78 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_IP_VERSION,
79 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_PASSWORD_FILE,
80 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR,
81 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_JPEG_IMG_COMPR,
82 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR,
83 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION,
84 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_USE_TLS,
85 07788a0b Michael Hanselmann
  ])
86 07788a0b Michael Hanselmann
87 2615646c Dimitris Aragiorgis
# Constant bitarray that reflects to a free pci slot
88 2615646c Dimitris Aragiorgis
# Use it with bitarray.search()
89 2615646c Dimitris Aragiorgis
_AVAILABLE_PCI_SLOT = bitarray("0")
90 2615646c Dimitris Aragiorgis
91 0fe22ad2 Dimitris Aragiorgis
# below constants show the format of runtime file
92 0fe22ad2 Dimitris Aragiorgis
# the nics are in second possition, while the disks in 4th (last)
93 41a878b5 Dimitris Aragiorgis
# moreover disk entries are stored as a list of in tuples
94 41a878b5 Dimitris Aragiorgis
# (L{objects.Disk}, link_name, uri)
95 0fe22ad2 Dimitris Aragiorgis
_KVM_NICS_RUNTIME_INDEX = 1
96 0fe22ad2 Dimitris Aragiorgis
_KVM_DISKS_RUNTIME_INDEX = 3
97 0fe22ad2 Dimitris Aragiorgis
_DEVICE_RUNTIME_INDEX = {
98 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK: _KVM_DISKS_RUNTIME_INDEX,
99 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC: _KVM_NICS_RUNTIME_INDEX
100 0fe22ad2 Dimitris Aragiorgis
  }
101 0fe22ad2 Dimitris Aragiorgis
_FIND_RUNTIME_ENTRY = {
102 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC:
103 0fe22ad2 Dimitris Aragiorgis
    lambda nic, kvm_nics: [n for n in kvm_nics if n.uuid == nic.uuid],
104 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK:
105 0fe22ad2 Dimitris Aragiorgis
    lambda disk, kvm_disks: [(d, l, u) for (d, l, u) in kvm_disks
106 0fe22ad2 Dimitris Aragiorgis
                             if d.uuid == disk.uuid]
107 0fe22ad2 Dimitris Aragiorgis
  }
108 0fe22ad2 Dimitris Aragiorgis
_RUNTIME_DEVICE = {
109 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC: lambda d: d,
110 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK: lambda (d, e, _): d
111 0fe22ad2 Dimitris Aragiorgis
  }
112 0fe22ad2 Dimitris Aragiorgis
_RUNTIME_ENTRY = {
113 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_NIC: lambda d, e: d,
114 0fe22ad2 Dimitris Aragiorgis
  constants.HOTPLUG_TARGET_DISK: lambda d, e: (d, e, None)
115 0fe22ad2 Dimitris Aragiorgis
  }
116 0fe22ad2 Dimitris Aragiorgis
117 0fe22ad2 Dimitris Aragiorgis
118 2615646c Dimitris Aragiorgis
def _GenerateDeviceKVMId(dev_type, dev):
119 2615646c Dimitris Aragiorgis
  """Helper function to generate a unique device name used by KVM
120 2615646c Dimitris Aragiorgis

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

506 91c10532 Andrea Spadaccini
    Seeks for a QMP message in the given buf. If found, it parses it and
507 91c10532 Andrea Spadaccini
    returns it together with the rest of the characters in the buf.
508 91c10532 Andrea Spadaccini
    If no message is found, returns None and the whole buffer.
509 91c10532 Andrea Spadaccini

510 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
511 91c10532 Andrea Spadaccini

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

529 91c10532 Andrea Spadaccini
    @rtype: QmpMessage
530 91c10532 Andrea Spadaccini
    @return: the received message
531 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
532 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
533 91c10532 Andrea Spadaccini

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

565 91c10532 Andrea Spadaccini
    @type message: QmpMessage
566 91c10532 Andrea Spadaccini
    @param message: message to send to KVM
567 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
568 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
569 91c10532 Andrea Spadaccini

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

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

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

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

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

818 7548396c Guido Trotter
    """
819 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
820 7548396c Guido Trotter
821 7548396c Guido Trotter
  @classmethod
822 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
823 263b8de6 Guido Trotter
    """Check pid file for instance information.
824 263b8de6 Guido Trotter

825 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
826 263b8de6 Guido Trotter
    information from its command line.
827 263b8de6 Guido Trotter

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

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

870 263b8de6 Guido Trotter
    @type instance_name: string
871 263b8de6 Guido Trotter
    @param instance_name: instance name
872 263b8de6 Guido Trotter
    @rtype: tuple
873 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
874 1f8b3a27 Guido Trotter

875 1f8b3a27 Guido Trotter
    """
876 70f25a49 Jose A. Lopes
    pidfile = cls._InstancePidFile(instance_name)
877 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
878 263b8de6 Guido Trotter
879 263b8de6 Guido Trotter
    alive = False
880 263b8de6 Guido Trotter
    try:
881 70f25a49 Jose A. Lopes
      cmd_instance = cls._InstancePidInfo(pid)[0]
882 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
883 263b8de6 Guido Trotter
    except errors.HypervisorError:
884 263b8de6 Guido Trotter
      pass
885 1f8b3a27 Guido Trotter
886 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
887 1f8b3a27 Guido Trotter
888 70f25a49 Jose A. Lopes
  @classmethod
889 70f25a49 Jose A. Lopes
  def _CheckDown(cls, instance_name):
890 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
891 5905901c Iustin Pop

892 5905901c Iustin Pop
    """
893 70f25a49 Jose A. Lopes
    alive = cls._InstancePidAlive(instance_name)[2]
894 5905901c Iustin Pop
    if alive:
895 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
896 5905901c Iustin Pop
                                   (instance_name, "already running"))
897 5905901c Iustin Pop
898 0df4d98a Guido Trotter
  @classmethod
899 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
900 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
901 c4fbefc8 Guido Trotter

902 c4fbefc8 Guido Trotter
    """
903 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
904 c4fbefc8 Guido Trotter
905 0df4d98a Guido Trotter
  @classmethod
906 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
907 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
908 c4fbefc8 Guido Trotter

909 c4fbefc8 Guido Trotter
    """
910 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
911 c4fbefc8 Guido Trotter
912 91c10532 Andrea Spadaccini
  @classmethod
913 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
914 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
915 91c10532 Andrea Spadaccini

916 91c10532 Andrea Spadaccini
    """
917 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
918 91c10532 Andrea Spadaccini
919 95d70148 Jose A. Lopes
  @classmethod
920 95d70148 Jose A. Lopes
  def _InstanceShutdownMonitor(cls, instance_name):
921 95d70148 Jose A. Lopes
    """Returns the instance QMP output filename
922 95d70148 Jose A. Lopes

923 95d70148 Jose A. Lopes
    """
924 95d70148 Jose A. Lopes
    return utils.PathJoin(cls._CTRL_DIR, "%s.shutdown" % instance_name)
925 95d70148 Jose A. Lopes
926 86d6bc2a Guido Trotter
  @staticmethod
927 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
928 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
929 86d6bc2a Guido Trotter

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

932 86d6bc2a Guido Trotter
    """
933 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
934 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
935 86d6bc2a Guido Trotter
    else:
936 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
937 86d6bc2a Guido Trotter
938 0df4d98a Guido Trotter
  @classmethod
939 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
940 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
941 38e250ba Guido Trotter

942 38e250ba Guido Trotter
    """
943 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
944 38e250ba Guido Trotter
945 7e66c35b Guido Trotter
  @classmethod
946 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
947 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
948 547a63b7 Balazs Lecz

949 547a63b7 Balazs Lecz
    """
950 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
951 547a63b7 Balazs Lecz
952 547a63b7 Balazs Lecz
  @classmethod
953 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
954 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
955 5d9bfd87 Apollon Oikonomopoulos
    given instance.
956 5d9bfd87 Apollon Oikonomopoulos

957 5d9bfd87 Apollon Oikonomopoulos
    """
958 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
959 5d9bfd87 Apollon Oikonomopoulos
960 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
961 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
962 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
963 5d9bfd87 Apollon Oikonomopoulos

964 5d9bfd87 Apollon Oikonomopoulos
    """
965 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
966 5d9bfd87 Apollon Oikonomopoulos
967 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
968 4f580fef Sรฉbastien Bocahu
  def _InstanceKeymapFile(cls, instance_name):
969 4f580fef Sรฉbastien Bocahu
    """Returns the name of the file containing the keymap for a given instance
970 4f580fef Sรฉbastien Bocahu

971 4f580fef Sรฉbastien Bocahu
    """
972 4f580fef Sรฉbastien Bocahu
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
973 4f580fef Sรฉbastien Bocahu
974 4f580fef Sรฉbastien Bocahu
  @classmethod
975 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
976 7548396c Guido Trotter
    """Try to read a uid file
977 7548396c Guido Trotter

978 7548396c Guido Trotter
    """
979 7548396c Guido Trotter
    if os.path.exists(uid_file):
980 7548396c Guido Trotter
      try:
981 682f7601 Guido Trotter
        uid = int(utils.ReadOneLineFile(uid_file))
982 aa0b600b Guido Trotter
        return uid
983 7548396c Guido Trotter
      except EnvironmentError:
984 7548396c Guido Trotter
        logging.warning("Can't read uid file", exc_info=True)
985 7548396c Guido Trotter
      except (TypeError, ValueError):
986 7548396c Guido Trotter
        logging.warning("Can't parse uid file contents", exc_info=True)
987 aa0b600b Guido Trotter
    return None
988 7548396c Guido Trotter
989 7548396c Guido Trotter
  @classmethod
990 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
991 547a63b7 Balazs Lecz
    """Removes an instance's rutime sockets/files/dirs.
992 7e66c35b Guido Trotter

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

1033 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
1034 eb58f9b1 Guido Trotter
    @type instance: instance object
1035 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
1036 eb58f9b1 Guido Trotter
    @type seq: int
1037 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
1038 eb58f9b1 Guido Trotter
    @type nic: nic object
1039 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
1040 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
1041 eb58f9b1 Guido Trotter

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

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

1090 b693125f Tsachy Shacham
    @type cpu_list: list of int
1091 b693125f Tsachy Shacham
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
1092 b693125f Tsachy Shacham
    @rtype: int
1093 b693125f Tsachy Shacham
    @return: a bit mask of CPU affinities
1094 b693125f Tsachy Shacham

1095 b693125f Tsachy Shacham
    """
1096 b693125f Tsachy Shacham
    if cpu_list == constants.CPU_PINNING_OFF:
1097 b693125f Tsachy Shacham
      return constants.CPU_PINNING_ALL_KVM
1098 b693125f Tsachy Shacham
    else:
1099 b693125f Tsachy Shacham
      return sum(2 ** cpu for cpu in cpu_list)
1100 b693125f Tsachy Shacham
1101 b693125f Tsachy Shacham
  @classmethod
1102 b693125f Tsachy Shacham
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
1103 b693125f Tsachy Shacham
    """Change CPU affinity for running VM according to given CPU mask.
1104 b693125f Tsachy Shacham

1105 b693125f Tsachy Shacham
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
1106 b693125f Tsachy Shacham
    @type cpu_mask: string
1107 b693125f Tsachy Shacham
    @param process_id: process ID of KVM process. Used to pin entire VM
1108 b693125f Tsachy Shacham
                       to physical CPUs.
1109 b693125f Tsachy Shacham
    @type process_id: int
1110 b693125f Tsachy Shacham
    @param thread_dict: map of virtual CPUs to KVM thread IDs
1111 b693125f Tsachy Shacham
    @type thread_dict: dict int:int
1112 b693125f Tsachy Shacham

1113 b693125f Tsachy Shacham
    """
1114 b693125f Tsachy Shacham
    # Convert the string CPU mask to a list of list of int's
1115 b693125f Tsachy Shacham
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
1116 b693125f Tsachy Shacham
1117 b693125f Tsachy Shacham
    if len(cpu_list) == 1:
1118 b693125f Tsachy Shacham
      all_cpu_mapping = cpu_list[0]
1119 b693125f Tsachy Shacham
      if all_cpu_mapping == constants.CPU_PINNING_OFF:
1120 b693125f Tsachy Shacham
        # If CPU pinning has 1 entry that's "all", then do nothing
1121 b693125f Tsachy Shacham
        pass
1122 b693125f Tsachy Shacham
      else:
1123 b693125f Tsachy Shacham
        # If CPU pinning has one non-all entry, map the entire VM to
1124 b693125f Tsachy Shacham
        # one set of physical CPUs
1125 b693125f Tsachy Shacham
        cls._VerifyAffinityPackage()
1126 5ae4945a Iustin Pop
        affinity.set_process_affinity_mask(
1127 5ae4945a Iustin Pop
          process_id, cls._BuildAffinityCpuMask(all_cpu_mapping))
1128 b693125f Tsachy Shacham
    else:
1129 b693125f Tsachy Shacham
      # The number of vCPUs mapped should match the number of vCPUs
1130 b693125f Tsachy Shacham
      # reported by KVM. This was already verified earlier, so
1131 b693125f Tsachy Shacham
      # here only as a sanity check.
1132 b693125f Tsachy Shacham
      assert len(thread_dict) == len(cpu_list)
1133 b693125f Tsachy Shacham
      cls._VerifyAffinityPackage()
1134 b693125f Tsachy Shacham
1135 b693125f Tsachy Shacham
      # For each vCPU, map it to the proper list of physical CPUs
1136 b693125f Tsachy Shacham
      for vcpu, i in zip(cpu_list, range(len(cpu_list))):
1137 b693125f Tsachy Shacham
        affinity.set_process_affinity_mask(thread_dict[i],
1138 5ae4945a Iustin Pop
                                           cls._BuildAffinityCpuMask(vcpu))
1139 b693125f Tsachy Shacham
1140 b693125f Tsachy Shacham
  def _GetVcpuThreadIds(self, instance_name):
1141 b693125f Tsachy Shacham
    """Get a mapping of vCPU no. to thread IDs for the instance
1142 b693125f Tsachy Shacham

1143 b693125f Tsachy Shacham
    @type instance_name: string
1144 b693125f Tsachy Shacham
    @param instance_name: instance in question
1145 b693125f Tsachy Shacham
    @rtype: dictionary of int:int
1146 b693125f Tsachy Shacham
    @return: a dictionary mapping vCPU numbers to thread IDs
1147 b693125f Tsachy Shacham

1148 b693125f Tsachy Shacham
    """
1149 b693125f Tsachy Shacham
    result = {}
1150 b693125f Tsachy Shacham
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
1151 b693125f Tsachy Shacham
    for line in output.stdout.splitlines():
1152 b693125f Tsachy Shacham
      match = self._CPU_INFO_RE.search(line)
1153 b693125f Tsachy Shacham
      if not match:
1154 b693125f Tsachy Shacham
        continue
1155 b693125f Tsachy Shacham
      grp = map(int, match.groups())
1156 b693125f Tsachy Shacham
      result[grp[0]] = grp[1]
1157 b693125f Tsachy Shacham
1158 b693125f Tsachy Shacham
    return result
1159 b693125f Tsachy Shacham
1160 1d8a7812 Andrea Spadaccini
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
1161 1d8a7812 Andrea Spadaccini
    """Complete CPU pinning.
1162 b693125f Tsachy Shacham

1163 b693125f Tsachy Shacham
    @type instance_name: string
1164 b693125f Tsachy Shacham
    @param instance_name: name of instance
1165 b693125f Tsachy Shacham
    @type cpu_mask: string
1166 b693125f Tsachy Shacham
    @param cpu_mask: CPU pinning mask as entered by user
1167 b693125f Tsachy Shacham

1168 b693125f Tsachy Shacham
    """
1169 1d8a7812 Andrea Spadaccini
    # Get KVM process ID, to be used if need to pin entire VM
1170 1d8a7812 Andrea Spadaccini
    _, pid, _ = self._InstancePidAlive(instance_name)
1171 1d8a7812 Andrea Spadaccini
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
1172 1d8a7812 Andrea Spadaccini
    thread_dict = self._GetVcpuThreadIds(instance_name)
1173 1d8a7812 Andrea Spadaccini
    # Run CPU pinning, based on configured mask
1174 1d8a7812 Andrea Spadaccini
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
1175 b693125f Tsachy Shacham
1176 58e356a9 Helga Velroyen
  def ListInstances(self, hvparams=None):
1177 eb58f9b1 Guido Trotter
    """Get the list of running instances.
1178 eb58f9b1 Guido Trotter

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

1182 eb58f9b1 Guido Trotter
    """
1183 eb58f9b1 Guido Trotter
    result = []
1184 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1185 95d70148 Jose A. Lopes
      if self._InstancePidAlive(name)[2] or self._IsUserShutdown(name):
1186 eb58f9b1 Guido Trotter
        result.append(name)
1187 eb58f9b1 Guido Trotter
    return result
1188 eb58f9b1 Guido Trotter
1189 95d70148 Jose A. Lopes
  @classmethod
1190 95d70148 Jose A. Lopes
  def _IsUserShutdown(cls, instance_name):
1191 95d70148 Jose A. Lopes
    return os.path.exists(cls._InstanceShutdownMonitor(instance_name))
1192 95d70148 Jose A. Lopes
1193 95d70148 Jose A. Lopes
  @classmethod
1194 95d70148 Jose A. Lopes
  def _ClearUserShutdown(cls, instance_name):
1195 95d70148 Jose A. Lopes
    utils.RemoveFile(cls._InstanceShutdownMonitor(instance_name))
1196 95d70148 Jose A. Lopes
1197 0bbec3af Helga Velroyen
  def GetInstanceInfo(self, instance_name, hvparams=None):
1198 eb58f9b1 Guido Trotter
    """Get instance properties.
1199 eb58f9b1 Guido Trotter

1200 4fbb3c60 Guido Trotter
    @type instance_name: string
1201 c41eea6e Iustin Pop
    @param instance_name: the instance name
1202 0bbec3af Helga Velroyen
    @type hvparams: dict of strings
1203 0bbec3af Helga Velroyen
    @param hvparams: hvparams to be used with this instance
1204 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
1205 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
1206 eb58f9b1 Guido Trotter

1207 eb58f9b1 Guido Trotter
    """
1208 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
1209 1f8b3a27 Guido Trotter
    if not alive:
1210 95d70148 Jose A. Lopes
      if self._IsUserShutdown(instance_name):
1211 95d70148 Jose A. Lopes
        return (instance_name, -1, 0, 0, hv_base.HvInstanceState.SHUTDOWN, 0)
1212 95d70148 Jose A. Lopes
      else:
1213 95d70148 Jose A. Lopes
        return None
1214 eb58f9b1 Guido Trotter
1215 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
1216 a3f0f306 Jose A. Lopes
    istat = hv_base.HvInstanceState.RUNNING
1217 697e573c Hrvoje Ribicic
    times = 0
1218 eb58f9b1 Guido Trotter
1219 89da2ff3 Guido Trotter
    try:
1220 89da2ff3 Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
1221 89da2ff3 Guido Trotter
      qmp.connect()
1222 89da2ff3 Guido Trotter
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
1223 89da2ff3 Guido Trotter
      # Will fail if ballooning is not enabled, but we can then just resort to
1224 89da2ff3 Guido Trotter
      # the value above.
1225 89da2ff3 Guido Trotter
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
1226 89da2ff3 Guido Trotter
      memory = mem_bytes / 1048576
1227 89da2ff3 Guido Trotter
    except errors.HypervisorError:
1228 89da2ff3 Guido Trotter
      pass
1229 89da2ff3 Guido Trotter
1230 fc84cd5d Guido Trotter
    return (instance_name, pid, memory, vcpus, istat, times)
1231 eb58f9b1 Guido Trotter
1232 0200a1af Helga Velroyen
  def GetAllInstancesInfo(self, hvparams=None):
1233 eb58f9b1 Guido Trotter
    """Get properties of all instances.
1234 eb58f9b1 Guido Trotter

1235 0200a1af Helga Velroyen
    @type hvparams: dict of strings
1236 0200a1af Helga Velroyen
    @param hvparams: hypervisor parameter
1237 c41eea6e Iustin Pop
    @return: list of tuples (name, id, memory, vcpus, stat, times)
1238 c41eea6e Iustin Pop

1239 eb58f9b1 Guido Trotter
    """
1240 eb58f9b1 Guido Trotter
    data = []
1241 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1242 263b8de6 Guido Trotter
      try:
1243 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
1244 263b8de6 Guido Trotter
      except errors.HypervisorError:
1245 3bc145d8 Bernardo Dal Seno
        # Ignore exceptions due to instances being shut down
1246 263b8de6 Guido Trotter
        continue
1247 263b8de6 Guido Trotter
      if info:
1248 263b8de6 Guido Trotter
        data.append(info)
1249 eb58f9b1 Guido Trotter
    return data
1250 eb58f9b1 Guido Trotter
1251 41a878b5 Dimitris Aragiorgis
  def _GenerateKVMBlockDevicesOptions(self, instance, kvm_disks,
1252 43c6e76f Dimitris Aragiorgis
                                      kvmhelp, devlist):
1253 43c6e76f Dimitris Aragiorgis
    """Generate KVM options regarding instance's block devices.
1254 43c6e76f Dimitris Aragiorgis

1255 43c6e76f Dimitris Aragiorgis
    @type instance: L{objects.Instance}
1256 43c6e76f Dimitris Aragiorgis
    @param instance: the instance object
1257 41a878b5 Dimitris Aragiorgis
    @type kvm_disks: list of tuples
1258 41a878b5 Dimitris Aragiorgis
    @param kvm_disks: list of tuples [(disk, link_name, uri)..]
1259 43c6e76f Dimitris Aragiorgis
    @type kvmhelp: string
1260 43c6e76f Dimitris Aragiorgis
    @param kvmhelp: output of kvm --help
1261 43c6e76f Dimitris Aragiorgis
    @type devlist: string
1262 43c6e76f Dimitris Aragiorgis
    @param devlist: output of kvm -device ?
1263 43c6e76f Dimitris Aragiorgis
    @rtype: list
1264 43c6e76f Dimitris Aragiorgis
    @return: list of command line options eventually used by kvm executable
1265 af5db30c Dimitris Aragiorgis

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

1347 b73f1c59 Guido Trotter
    @type kvmhelp: string
1348 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1349 839642c2 Iustin Pop
    @attention: this function must not have any side-effects; for
1350 839642c2 Iustin Pop
        example, it must not write to the filesystem, or read values
1351 839642c2 Iustin Pop
        from the current system the are expected to differ between
1352 839642c2 Iustin Pop
        nodes, since it is only run once at instance startup;
1353 839642c2 Iustin Pop
        actions/kvm arguments that can vary between systems should be
1354 839642c2 Iustin Pop
        done in L{_ExecuteKVMRuntime}
1355 839642c2 Iustin Pop

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

1709 38e250ba Guido Trotter
    """
1710 38e250ba Guido Trotter
    try:
1711 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1712 38e250ba Guido Trotter
                      data=data)
1713 90c024f6 Guido Trotter
    except EnvironmentError, err:
1714 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1715 38e250ba Guido Trotter
1716 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
1717 38e250ba Guido Trotter
    """Read an instance's KVM runtime
1718 38e250ba Guido Trotter

1719 38e250ba Guido Trotter
    """
1720 38e250ba Guido Trotter
    try:
1721 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1722 90c024f6 Guido Trotter
    except EnvironmentError, err:
1723 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1724 38e250ba Guido Trotter
    return file_content
1725 38e250ba Guido Trotter
1726 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1727 38e250ba Guido Trotter
    """Save an instance's KVM runtime
1728 38e250ba Guido Trotter

1729 38e250ba Guido Trotter
    """
1730 41a878b5 Dimitris Aragiorgis
    kvm_cmd, kvm_nics, hvparams, kvm_disks = kvm_runtime
1731 0fe22ad2 Dimitris Aragiorgis
1732 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1733 41a878b5 Dimitris Aragiorgis
    serialized_disks = [(blk.ToDict(), link, uri)
1734 41a878b5 Dimitris Aragiorgis
                        for blk, link, uri in kvm_disks]
1735 0fe22ad2 Dimitris Aragiorgis
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams,
1736 41a878b5 Dimitris Aragiorgis
                                      serialized_disks))
1737 0fe22ad2 Dimitris Aragiorgis
1738 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
1739 38e250ba Guido Trotter
1740 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1741 38e250ba Guido Trotter
    """Load an instance's KVM runtime
1742 38e250ba Guido Trotter

1743 38e250ba Guido Trotter
    """
1744 30e42c4e Guido Trotter
    if not serialized_runtime:
1745 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1746 0fe22ad2 Dimitris Aragiorgis
1747 0fe22ad2 Dimitris Aragiorgis
    return _AnalyzeSerializedRuntime(serialized_runtime)
1748 38e250ba Guido Trotter
1749 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1750 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
1751 76431533 Guido Trotter

1752 76431533 Guido Trotter
    @type name: string
1753 76431533 Guido Trotter
    @param name: instance name
1754 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1755 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1756 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1757 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1758 76431533 Guido Trotter

1759 76431533 Guido Trotter
    """
1760 5d9bfd87 Apollon Oikonomopoulos
    try:
1761 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1762 5d9bfd87 Apollon Oikonomopoulos
    finally:
1763 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
1764 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
1765 5d9bfd87 Apollon Oikonomopoulos
1766 76431533 Guido Trotter
    if result.failed:
1767 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1768 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
1769 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
1770 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
1771 76431533 Guido Trotter
1772 41a878b5 Dimitris Aragiorgis
  # too many local variables
1773 0fe22ad2 Dimitris Aragiorgis
  # pylint: disable=R0914
1774 b73f1c59 Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1775 839642c2 Iustin Pop
    """Execute a KVM cmd, after completing it with some last minute data.
1776 ee5f20b0 Guido Trotter

1777 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1778 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1779 b73f1c59 Guido Trotter
    @type kvmhelp: string
1780 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1781 30e42c4e Guido Trotter

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

2004 95d70148 Jose A. Lopes
    """
2005 95d70148 Jose A. Lopes
    if hvparams is None \
2006 95d70148 Jose A. Lopes
          or not hvparams[constants.HV_KVM_USER_SHUTDOWN] \
2007 95d70148 Jose A. Lopes
          or utils.IsDaemonAlive(constants.KVMD):
2008 95d70148 Jose A. Lopes
      return
2009 95d70148 Jose A. Lopes
2010 95d70148 Jose A. Lopes
    result = utils.RunCmd(constants.KVMD)
2011 95d70148 Jose A. Lopes
2012 95d70148 Jose A. Lopes
    if result.failed:
2013 95d70148 Jose A. Lopes
      raise errors.HypervisorError("Failed to start KVM daemon")
2014 95d70148 Jose A. Lopes
2015 323f9095 Stephen Shirley
  def StartInstance(self, instance, block_devices, startup_paused):
2016 ee5f20b0 Guido Trotter
    """Start an instance.
2017 ee5f20b0 Guido Trotter

2018 ee5f20b0 Guido Trotter
    """
2019 5905901c Iustin Pop
    self._CheckDown(instance.name)
2020 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2021 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2022 7238edb5 Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
2023 b73f1c59 Guido Trotter
                                           startup_paused, kvmhelp)
2024 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
2025 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
2026 ee5f20b0 Guido Trotter
2027 70f25a49 Jose A. Lopes
  @classmethod
2028 70f25a49 Jose A. Lopes
  def _CallMonitorCommand(cls, instance_name, command):
2029 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
2030 6567aff3 Guido Trotter

2031 6567aff3 Guido Trotter
    """
2032 eace6157 Michael Hanselmann
    # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
2033 eace6157 Michael Hanselmann
    # version. The monitor protocol is designed for human consumption, whereas
2034 eace6157 Michael Hanselmann
    # QMP is made for programmatic usage. In the worst case QMP can also
2035 eace6157 Michael Hanselmann
    # execute monitor commands. As it is, all calls to socat take at least
2036 eace6157 Michael Hanselmann
    # 500ms and likely more: socat can't detect the end of the reply and waits
2037 eace6157 Michael Hanselmann
    # for 500ms of no data received before exiting (500 ms is the default for
2038 eace6157 Michael Hanselmann
    # the "-t" parameter).
2039 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
2040 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
2041 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
2042 70f25a49 Jose A. Lopes
              utils.ShellQuote(cls._InstanceMonitor(instance_name))))
2043 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
2044 6567aff3 Guido Trotter
    if result.failed:
2045 afa9bb2e Michael Hanselmann
      msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
2046 afa9bb2e Michael Hanselmann
             " output: %s" %
2047 afa9bb2e Michael Hanselmann
             (command, instance_name, result.fail_reason, result.output))
2048 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
2049 6567aff3 Guido Trotter
2050 6567aff3 Guido Trotter
    return result
2051 6567aff3 Guido Trotter
2052 2615646c Dimitris Aragiorgis
  def _GetFreePCISlot(self, instance, dev):
2053 2615646c Dimitris Aragiorgis
    """Get the first available pci slot of a runnung instance.
2054 2615646c Dimitris Aragiorgis

2055 2615646c Dimitris Aragiorgis
    """
2056 2615646c Dimitris Aragiorgis
    slots = bitarray(32)
2057 2615646c Dimitris Aragiorgis
    slots.setall(False) # pylint: disable=E1101
2058 2615646c Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance.name, self._INFO_PCI_CMD)
2059 2615646c Dimitris Aragiorgis
    for line in output.stdout.splitlines():
2060 2615646c Dimitris Aragiorgis
      match = self._INFO_PCI_RE.search(line)
2061 2615646c Dimitris Aragiorgis
      if match:
2062 2615646c Dimitris Aragiorgis
        slot = int(match.group(1))
2063 2615646c Dimitris Aragiorgis
        slots[slot] = True
2064 2615646c Dimitris Aragiorgis
2065 2615646c Dimitris Aragiorgis
    [free] = slots.search(_AVAILABLE_PCI_SLOT, 1) # pylint: disable=E1101
2066 2615646c Dimitris Aragiorgis
    if not free:
2067 2615646c Dimitris Aragiorgis
      raise errors.HypervisorError("All PCI slots occupied")
2068 2615646c Dimitris Aragiorgis
2069 2615646c Dimitris Aragiorgis
    dev.pci = int(free)
2070 2615646c Dimitris Aragiorgis
2071 50e0f1d9 Dimitris Aragiorgis
  def VerifyHotplugSupport(self, instance, action, dev_type):
2072 50e0f1d9 Dimitris Aragiorgis
    """Verifies that hotplug is supported.
2073 97cd9092 Dimitris Aragiorgis

2074 97cd9092 Dimitris Aragiorgis
    Hotplug is *not* supported in case of:
2075 97cd9092 Dimitris Aragiorgis
     - security models and chroot (disk hotplug)
2076 97cd9092 Dimitris Aragiorgis
     - fdsend module is missing (nic hot-add)
2077 97cd9092 Dimitris Aragiorgis

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

2080 97cd9092 Dimitris Aragiorgis
    """
2081 97cd9092 Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2082 97cd9092 Dimitris Aragiorgis
      hvp = instance.hvparams
2083 97cd9092 Dimitris Aragiorgis
      security_model = hvp[constants.HV_SECURITY_MODEL]
2084 97cd9092 Dimitris Aragiorgis
      use_chroot = hvp[constants.HV_KVM_USE_CHROOT]
2085 97cd9092 Dimitris Aragiorgis
      if use_chroot:
2086 97cd9092 Dimitris Aragiorgis
        raise errors.HotplugError("Disk hotplug is not supported"
2087 97cd9092 Dimitris Aragiorgis
                                  " in case of chroot.")
2088 97cd9092 Dimitris Aragiorgis
      if security_model != constants.HT_SM_NONE:
2089 97cd9092 Dimitris Aragiorgis
        raise errors.HotplugError("Disk Hotplug is not supported in case"
2090 97cd9092 Dimitris Aragiorgis
                                  " security models are used.")
2091 97cd9092 Dimitris Aragiorgis
2092 97cd9092 Dimitris Aragiorgis
    if (dev_type == constants.HOTPLUG_TARGET_NIC and
2093 97cd9092 Dimitris Aragiorgis
        action == constants.HOTPLUG_ACTION_ADD and not fdsend):
2094 97cd9092 Dimitris Aragiorgis
      raise errors.HotplugError("Cannot hot-add NIC."
2095 97cd9092 Dimitris Aragiorgis
                                " fdsend python module is missing.")
2096 97cd9092 Dimitris Aragiorgis
2097 24711492 Dimitris Aragiorgis
  def HotplugSupported(self, instance):
2098 24711492 Dimitris Aragiorgis
    """Checks if hotplug is generally supported.
2099 24711492 Dimitris Aragiorgis

2100 24711492 Dimitris Aragiorgis
    Hotplug is *not* supported in case of:
2101 24711492 Dimitris Aragiorgis
     - qemu versions < 1.0
2102 24711492 Dimitris Aragiorgis
     - for stopped instances
2103 24711492 Dimitris Aragiorgis

2104 24711492 Dimitris Aragiorgis
    @raise errors.HypervisorError: in one of the previous cases
2105 24711492 Dimitris Aragiorgis

2106 24711492 Dimitris Aragiorgis
    """
2107 96ed3a3e Dimitris Aragiorgis
    try:
2108 96ed3a3e Dimitris Aragiorgis
      output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD)
2109 96ed3a3e Dimitris Aragiorgis
    except errors.HypervisorError:
2110 96ed3a3e Dimitris Aragiorgis
      raise errors.HotplugError("Instance is probably down")
2111 96ed3a3e Dimitris Aragiorgis
2112 24711492 Dimitris Aragiorgis
    # TODO: search for netdev_add, drive_add, device_add.....
2113 24711492 Dimitris Aragiorgis
    match = self._INFO_VERSION_RE.search(output.stdout)
2114 24711492 Dimitris Aragiorgis
    if not match:
2115 96ed3a3e Dimitris Aragiorgis
      raise errors.HotplugError("Cannot parse qemu version via monitor")
2116 96ed3a3e Dimitris Aragiorgis
2117 24711492 Dimitris Aragiorgis
    v_major, v_min, _, _ = match.groups()
2118 24711492 Dimitris Aragiorgis
    if (int(v_major), int(v_min)) < (1, 0):
2119 24711492 Dimitris Aragiorgis
      raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0")
2120 24711492 Dimitris Aragiorgis
2121 89c10241 Dimitris Aragiorgis
  def _CallHotplugCommands(self, name, cmds):
2122 89c10241 Dimitris Aragiorgis
    for c in cmds:
2123 066f16b0 Dimitris Aragiorgis
      self._CallMonitorCommand(name, c)
2124 89c10241 Dimitris Aragiorgis
      time.sleep(1)
2125 97cd9092 Dimitris Aragiorgis
2126 066f16b0 Dimitris Aragiorgis
  def _VerifyHotplugCommand(self, instance_name, device, dev_type,
2127 066f16b0 Dimitris Aragiorgis
                            should_exist):
2128 066f16b0 Dimitris Aragiorgis
    """Checks if a previous hotplug command has succeeded.
2129 066f16b0 Dimitris Aragiorgis

2130 066f16b0 Dimitris Aragiorgis
    It issues info pci monitor command and checks depending on should_exist
2131 066f16b0 Dimitris Aragiorgis
    value if an entry with PCI slot and device ID is found or not.
2132 066f16b0 Dimitris Aragiorgis

2133 066f16b0 Dimitris Aragiorgis
    @raise errors.HypervisorError: if result is not the expected one
2134 066f16b0 Dimitris Aragiorgis

2135 066f16b0 Dimitris Aragiorgis
    """
2136 066f16b0 Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance_name, self._INFO_PCI_CMD)
2137 066f16b0 Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, device)
2138 066f16b0 Dimitris Aragiorgis
    match = \
2139 066f16b0 Dimitris Aragiorgis
      self._FIND_PCI_DEVICE_RE(device.pci, kvm_devid).search(output.stdout)
2140 066f16b0 Dimitris Aragiorgis
    if match and not should_exist:
2141 066f16b0 Dimitris Aragiorgis
      msg = "Device %s should have been removed but is still there" % kvm_devid
2142 066f16b0 Dimitris Aragiorgis
      raise errors.HypervisorError(msg)
2143 066f16b0 Dimitris Aragiorgis
2144 066f16b0 Dimitris Aragiorgis
    if not match and should_exist:
2145 066f16b0 Dimitris Aragiorgis
      msg = "Device %s should have been added but is missing" % kvm_devid
2146 066f16b0 Dimitris Aragiorgis
      raise errors.HypervisorError(msg)
2147 066f16b0 Dimitris Aragiorgis
2148 066f16b0 Dimitris Aragiorgis
    logging.info("Device %s has been correctly hot-plugged", kvm_devid)
2149 97cd9092 Dimitris Aragiorgis
2150 4b82125b Dimitris Aragiorgis
  def HotAddDevice(self, instance, dev_type, device, extra, seq):
2151 4b82125b Dimitris Aragiorgis
    """ Helper method to hot-add a new device
2152 4b82125b Dimitris Aragiorgis

2153 4b82125b Dimitris Aragiorgis
    It gets free pci slot generates the device name and invokes the
2154 4b82125b Dimitris Aragiorgis
    device specific method.
2155 4b82125b Dimitris Aragiorgis

2156 4b82125b Dimitris Aragiorgis
    """
2157 4b82125b Dimitris Aragiorgis
    # in case of hot-mod this is given
2158 4b82125b Dimitris Aragiorgis
    if device.pci is None:
2159 4b82125b Dimitris Aragiorgis
      self._GetFreePCISlot(instance, device)
2160 4b82125b Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, device)
2161 4b82125b Dimitris Aragiorgis
    runtime = self._LoadKVMRuntime(instance)
2162 4b82125b Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2163 89c10241 Dimitris Aragiorgis
      cmds = ["drive_add dummy file=%s,if=none,id=%s,format=raw" %
2164 89c10241 Dimitris Aragiorgis
                (extra, kvm_devid)]
2165 89c10241 Dimitris Aragiorgis
      cmds += ["device_add virtio-blk-pci,bus=pci.0,addr=%s,drive=%s,id=%s" %
2166 89c10241 Dimitris Aragiorgis
                (hex(device.pci), kvm_devid, kvm_devid)]
2167 4b82125b Dimitris Aragiorgis
    elif dev_type == constants.HOTPLUG_TARGET_NIC:
2168 4b82125b Dimitris Aragiorgis
      (tap, fd) = _OpenTap()
2169 4b82125b Dimitris Aragiorgis
      self._ConfigureNIC(instance, seq, device, tap)
2170 4b82125b Dimitris Aragiorgis
      self._PassTapFd(instance, fd, device)
2171 89c10241 Dimitris Aragiorgis
      cmds = ["netdev_add tap,id=%s,fd=%s" % (kvm_devid, kvm_devid)]
2172 4b82125b Dimitris Aragiorgis
      args = "virtio-net-pci,bus=pci.0,addr=%s,mac=%s,netdev=%s,id=%s" % \
2173 4b82125b Dimitris Aragiorgis
               (hex(device.pci), device.mac, kvm_devid, kvm_devid)
2174 89c10241 Dimitris Aragiorgis
      cmds += ["device_add %s" % args]
2175 4b82125b Dimitris Aragiorgis
      utils.WriteFile(self._InstanceNICFile(instance.name, seq), data=tap)
2176 4b82125b Dimitris Aragiorgis
2177 89c10241 Dimitris Aragiorgis
    self._CallHotplugCommands(instance.name, cmds)
2178 066f16b0 Dimitris Aragiorgis
    self._VerifyHotplugCommand(instance.name, device, dev_type, True)
2179 4b82125b Dimitris Aragiorgis
    # update relevant entries in runtime file
2180 4b82125b Dimitris Aragiorgis
    index = _DEVICE_RUNTIME_INDEX[dev_type]
2181 4b82125b Dimitris Aragiorgis
    entry = _RUNTIME_ENTRY[dev_type](device, extra)
2182 4b82125b Dimitris Aragiorgis
    runtime[index].append(entry)
2183 4b82125b Dimitris Aragiorgis
    self._SaveKVMRuntime(instance, runtime)
2184 4b82125b Dimitris Aragiorgis
2185 4b82125b Dimitris Aragiorgis
  def HotDelDevice(self, instance, dev_type, device, _, seq):
2186 4b82125b Dimitris Aragiorgis
    """ Helper method for hot-del device
2187 4b82125b Dimitris Aragiorgis

2188 4b82125b Dimitris Aragiorgis
    It gets device info from runtime file, generates the device name and
2189 4b82125b Dimitris Aragiorgis
    invokes the device specific method.
2190 4b82125b Dimitris Aragiorgis

2191 4b82125b Dimitris Aragiorgis
    """
2192 4b82125b Dimitris Aragiorgis
    runtime = self._LoadKVMRuntime(instance)
2193 4b82125b Dimitris Aragiorgis
    entry = _GetExistingDeviceInfo(dev_type, device, runtime)
2194 4b82125b Dimitris Aragiorgis
    kvm_device = _RUNTIME_DEVICE[dev_type](entry)
2195 4b82125b Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, kvm_device)
2196 4b82125b Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2197 89c10241 Dimitris Aragiorgis
      cmds = ["device_del %s" % kvm_devid]
2198 89c10241 Dimitris Aragiorgis
      cmds += ["drive_del %s" % kvm_devid]
2199 4b82125b Dimitris Aragiorgis
    elif dev_type == constants.HOTPLUG_TARGET_NIC:
2200 89c10241 Dimitris Aragiorgis
      cmds = ["device_del %s" % kvm_devid]
2201 89c10241 Dimitris Aragiorgis
      cmds += ["netdev_del %s" % kvm_devid]
2202 4b82125b Dimitris Aragiorgis
      utils.RemoveFile(self._InstanceNICFile(instance.name, seq))
2203 89c10241 Dimitris Aragiorgis
    self._CallHotplugCommands(instance.name, cmds)
2204 066f16b0 Dimitris Aragiorgis
    self._VerifyHotplugCommand(instance.name, kvm_device, dev_type, False)
2205 4b82125b Dimitris Aragiorgis
    index = _DEVICE_RUNTIME_INDEX[dev_type]
2206 4b82125b Dimitris Aragiorgis
    runtime[index].remove(entry)
2207 4b82125b Dimitris Aragiorgis
    self._SaveKVMRuntime(instance, runtime)
2208 4b82125b Dimitris Aragiorgis
2209 4b82125b Dimitris Aragiorgis
    return kvm_device.pci
2210 4b82125b Dimitris Aragiorgis
2211 4b82125b Dimitris Aragiorgis
  def HotModDevice(self, instance, dev_type, device, _, seq):
2212 4b82125b Dimitris Aragiorgis
    """ Helper method for hot-mod device
2213 4b82125b Dimitris Aragiorgis

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

2217 4b82125b Dimitris Aragiorgis
    """
2218 4b82125b Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_NIC:
2219 4b82125b Dimitris Aragiorgis
      # putting it back in the same pci slot
2220 4b82125b Dimitris Aragiorgis
      device.pci = self.HotDelDevice(instance, dev_type, device, _, seq)
2221 4b82125b Dimitris Aragiorgis
      self.HotAddDevice(instance, dev_type, device, _, seq)
2222 4b82125b Dimitris Aragiorgis
2223 4b82125b Dimitris Aragiorgis
  def _PassTapFd(self, instance, fd, nic):
2224 4b82125b Dimitris Aragiorgis
    """Pass file descriptor to kvm process via monitor socket using SCM_RIGHTS
2225 4b82125b Dimitris Aragiorgis

2226 4b82125b Dimitris Aragiorgis
    """
2227 4b82125b Dimitris Aragiorgis
    # TODO: factor out code related to unix sockets.
2228 4b82125b Dimitris Aragiorgis
    #       squash common parts between monitor and qmp
2229 4b82125b Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_NIC, nic)
2230 4b82125b Dimitris Aragiorgis
    command = "getfd %s\n" % kvm_devid
2231 4b82125b Dimitris Aragiorgis
    fds = [fd]
2232 4b82125b Dimitris Aragiorgis
    logging.info("%s", fds)
2233 4b82125b Dimitris Aragiorgis
    try:
2234 4b82125b Dimitris Aragiorgis
      monsock = MonitorSocket(self._InstanceMonitor(instance.name))
2235 4b82125b Dimitris Aragiorgis
      monsock.connect()
2236 4b82125b Dimitris Aragiorgis
      fdsend.sendfds(monsock.sock, command, fds=fds)
2237 4b82125b Dimitris Aragiorgis
    finally:
2238 4b82125b Dimitris Aragiorgis
      monsock.close()
2239 4b82125b Dimitris Aragiorgis
2240 b52d85c1 Guido Trotter
  @classmethod
2241 585c8187 Guido Trotter
  def _ParseKVMVersion(cls, text):
2242 585c8187 Guido Trotter
    """Parse the KVM version from the --help output.
2243 585c8187 Guido Trotter

2244 585c8187 Guido Trotter
    @type text: string
2245 585c8187 Guido Trotter
    @param text: output of kvm --help
2246 585c8187 Guido Trotter
    @return: (version, v_maj, v_min, v_rev)
2247 5c3d5dfd Iustin Pop
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
2248 585c8187 Guido Trotter

2249 585c8187 Guido Trotter
    """
2250 585c8187 Guido Trotter
    match = cls._VERSION_RE.search(text.splitlines()[0])
2251 585c8187 Guido Trotter
    if not match:
2252 585c8187 Guido Trotter
      raise errors.HypervisorError("Unable to get KVM version")
2253 585c8187 Guido Trotter
2254 585c8187 Guido Trotter
    v_all = match.group(0)
2255 585c8187 Guido Trotter
    v_maj = int(match.group(1))
2256 585c8187 Guido Trotter
    v_min = int(match.group(2))
2257 585c8187 Guido Trotter
    if match.group(4):
2258 585c8187 Guido Trotter
      v_rev = int(match.group(4))
2259 585c8187 Guido Trotter
    else:
2260 585c8187 Guido Trotter
      v_rev = 0
2261 585c8187 Guido Trotter
    return (v_all, v_maj, v_min, v_rev)
2262 585c8187 Guido Trotter
2263 585c8187 Guido Trotter
  @classmethod
2264 6e043e60 Guido Trotter
  def _GetKVMOutput(cls, kvm_path, option):
2265 6e043e60 Guido Trotter
    """Return the output of a kvm invocation
2266 e3b89628 Guido Trotter

2267 bc0fed4b Guido Trotter
    @type kvm_path: string
2268 bc0fed4b Guido Trotter
    @param kvm_path: path to the kvm executable
2269 bc0fed4b Guido Trotter
    @type option: a key of _KVMOPTS_CMDS
2270 bc0fed4b Guido Trotter
    @param option: kvm option to fetch the output from
2271 6e043e60 Guido Trotter
    @return: output a supported kvm invocation
2272 e3b89628 Guido Trotter
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
2273 e3b89628 Guido Trotter

2274 e3b89628 Guido Trotter
    """
2275 6e043e60 Guido Trotter
    assert option in cls._KVMOPTS_CMDS, "Invalid output option"
2276 6e043e60 Guido Trotter
2277 bc0fed4b Guido Trotter
    optlist, can_fail = cls._KVMOPTS_CMDS[option]
2278 bc0fed4b Guido Trotter
2279 bc0fed4b Guido Trotter
    result = utils.RunCmd([kvm_path] + optlist)
2280 bc0fed4b Guido Trotter
    if result.failed and not can_fail:
2281 af89fa76 Helga Velroyen
      raise errors.HypervisorError("Unable to get KVM %s output" %
2282 3ddc7650 Jose A. Lopes
                                    " ".join(optlist))
2283 e3b89628 Guido Trotter
    return result.output
2284 e3b89628 Guido Trotter
2285 e3b89628 Guido Trotter
  @classmethod
2286 3b59ec02 Guido Trotter
  def _GetKVMVersion(cls, kvm_path):
2287 d7e4a2b1 Andrea Spadaccini
    """Return the installed KVM version.
2288 b52d85c1 Guido Trotter

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

2292 b52d85c1 Guido Trotter
    """
2293 6e043e60 Guido Trotter
    return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
2294 82e3bf85 Dimitris Aragiorgis
2295 82e3bf85 Dimitris Aragiorgis
  @classmethod
2296 82e3bf85 Dimitris Aragiorgis
  def _GetDefaultMachineVersion(cls, kvm_path):
2297 82e3bf85 Dimitris Aragiorgis
    """Return the default hardware revision (e.g. pc-1.1)
2298 82e3bf85 Dimitris Aragiorgis

2299 82e3bf85 Dimitris Aragiorgis
    """
2300 6e043e60 Guido Trotter
    output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2301 82e3bf85 Dimitris Aragiorgis
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
2302 82e3bf85 Dimitris Aragiorgis
    if match:
2303 82e3bf85 Dimitris Aragiorgis
      return match.group(1)
2304 82e3bf85 Dimitris Aragiorgis
    else:
2305 82e3bf85 Dimitris Aragiorgis
      return "pc"
2306 82e3bf85 Dimitris Aragiorgis
2307 70f25a49 Jose A. Lopes
  @classmethod
2308 70f25a49 Jose A. Lopes
  def _StopInstance(cls, instance, force=False, name=None):
2309 eb58f9b1 Guido Trotter
    """Stop an instance.
2310 eb58f9b1 Guido Trotter

2311 eb58f9b1 Guido Trotter
    """
2312 bbcf7ad0 Iustin Pop
    if name is not None and not force:
2313 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
2314 bbcf7ad0 Iustin Pop
    if name is None:
2315 bbcf7ad0 Iustin Pop
      name = instance.name
2316 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
2317 bbcf7ad0 Iustin Pop
    else:
2318 bbcf7ad0 Iustin Pop
      acpi = False
2319 70f25a49 Jose A. Lopes
    _, pid, alive = cls._InstancePidAlive(name)
2320 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
2321 bbcf7ad0 Iustin Pop
      if force or not acpi:
2322 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
2323 eb58f9b1 Guido Trotter
      else:
2324 70f25a49 Jose A. Lopes
        cls._CallMonitorCommand(name, "system_powerdown")
2325 95d70148 Jose A. Lopes
    cls._ClearUserShutdown(instance.name)
2326 70f25a49 Jose A. Lopes
2327 70f25a49 Jose A. Lopes
  def StopInstance(self, instance, force=False, retry=False, name=None):
2328 70f25a49 Jose A. Lopes
    """Stop an instance.
2329 70f25a49 Jose A. Lopes

2330 70f25a49 Jose A. Lopes
    """
2331 70f25a49 Jose A. Lopes
    self._StopInstance(instance, force, name)
2332 eb58f9b1 Guido Trotter
2333 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
2334 8904b35c Guido Trotter
    """Cleanup after a stopped instance
2335 8904b35c Guido Trotter

2336 8904b35c Guido Trotter
    """
2337 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
2338 8904b35c Guido Trotter
    if pid > 0 and alive:
2339 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
2340 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
2341 95d70148 Jose A. Lopes
    self._ClearUserShutdown(instance_name)
2342 eb58f9b1 Guido Trotter
2343 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
2344 eb58f9b1 Guido Trotter
    """Reboot an instance.
2345 eb58f9b1 Guido Trotter

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

2369 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2370 30e42c4e Guido Trotter
    @param instance: instance to be migrated
2371 30e42c4e Guido Trotter
    @rtype: string
2372 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
2373 30e42c4e Guido Trotter

2374 30e42c4e Guido Trotter
    """
2375 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
2376 30e42c4e Guido Trotter
2377 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
2378 30e42c4e Guido Trotter
    """Prepare to accept an instance.
2379 30e42c4e Guido Trotter

2380 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2381 30e42c4e Guido Trotter
    @param instance: instance to be accepted
2382 30e42c4e Guido Trotter
    @type info: string
2383 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
2384 30e42c4e Guido Trotter
    @type target: string
2385 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
2386 30e42c4e Guido Trotter

2387 30e42c4e Guido Trotter
    """
2388 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2389 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
2390 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2391 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2392 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
2393 b73f1c59 Guido Trotter
                            incoming=incoming_address)
2394 30e42c4e Guido Trotter
2395 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
2396 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
2397 30e42c4e Guido Trotter

2398 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
2399 30e42c4e Guido Trotter

2400 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2401 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
2402 30e42c4e Guido Trotter

2403 30e42c4e Guido Trotter
    """
2404 30e42c4e Guido Trotter
    if success:
2405 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2406 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
2407 5d9bfd87 Apollon Oikonomopoulos
2408 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
2409 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
2410 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
2411 cc8a8ed7 Apollon Oikonomopoulos
          continue
2412 5d9bfd87 Apollon Oikonomopoulos
        try:
2413 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
2414 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
2415 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
2416 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
2417 5d9bfd87 Apollon Oikonomopoulos
          continue
2418 5d9bfd87 Apollon Oikonomopoulos
        try:
2419 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
2420 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
2421 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
2422 5d9bfd87 Apollon Oikonomopoulos
2423 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
2424 30e42c4e Guido Trotter
    else:
2425 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
2426 30e42c4e Guido Trotter
2427 bc0a2284 Helga Velroyen
  def MigrateInstance(self, cluster_name, instance, target, live):
2428 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
2429 30e42c4e Guido Trotter

2430 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
2431 30e42c4e Guido Trotter
    currently running.
2432 30e42c4e Guido Trotter

2433 bc0a2284 Helga Velroyen
    @type cluster_name: string
2434 bc0a2284 Helga Velroyen
    @param cluster_name: name of the cluster
2435 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
2436 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
2437 30e42c4e Guido Trotter
    @type target: string
2438 30e42c4e Guido Trotter
    @param target: ip address of the target node
2439 30e42c4e Guido Trotter
    @type live: boolean
2440 30e42c4e Guido Trotter
    @param live: perform a live migration
2441 30e42c4e Guido Trotter

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

2466 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2467 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
2468 6a1434d7 Andrea Spadaccini
    @type success: bool
2469 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
2470 6a1434d7 Andrea Spadaccini
    @type live: bool
2471 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
2472 6a1434d7 Andrea Spadaccini

2473 6a1434d7 Andrea Spadaccini
    """
2474 6a1434d7 Andrea Spadaccini
    if success:
2475 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
2476 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
2477 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
2478 6a1434d7 Andrea Spadaccini
    elif live:
2479 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
2480 95d70148 Jose A. Lopes
    self._ClearUserShutdown(instance.name)
2481 6a1434d7 Andrea Spadaccini
2482 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
2483 6a1434d7 Andrea Spadaccini
    """Get the migration status
2484 6a1434d7 Andrea Spadaccini

2485 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2486 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
2487 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
2488 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
2489 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
2490 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
2491 6a1434d7 Andrea Spadaccini

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

2523 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
2524 3d836750 Guido Trotter
    @param instance: instance to be accepted
2525 3d836750 Guido Trotter
    @type mem: int
2526 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
2527 3d836750 Guido Trotter

2528 3d836750 Guido Trotter
    """
2529 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2530 3d836750 Guido Trotter
2531 fac489a5 Helga Velroyen
  def GetNodeInfo(self, hvparams=None):
2532 eb58f9b1 Guido Trotter
    """Return information about the node.
2533 eb58f9b1 Guido Trotter

2534 fac489a5 Helga Velroyen
    @type hvparams: dict of strings
2535 fac489a5 Helga Velroyen
    @param hvparams: hypervisor parameters, not used in this class
2536 fac489a5 Helga Velroyen

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

2542 eb58f9b1 Guido Trotter
    """
2543 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
2544 25bce647 Santi Raffa
    kvmpath = constants.KVM_PATH
2545 25bce647 Santi Raffa
    if hvparams is not None:
2546 25bce647 Santi Raffa
      kvmpath = hvparams.get(constants.HV_KVM_PATH, constants.KVM_PATH)
2547 25bce647 Santi Raffa
    _, v_major, v_min, v_rev = self._GetKVMVersion(kvmpath)
2548 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2549 34fbc862 Andrea Spadaccini
    return result
2550 eb58f9b1 Guido Trotter
2551 637ce7f9 Guido Trotter
  @classmethod
2552 c42be2c0 Petr Pudlak
  def GetInstanceConsole(cls, instance, primary_node, node_group,
2553 c42be2c0 Petr Pudlak
                         hvparams, beparams):
2554 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
2555 eb58f9b1 Guido Trotter

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

2595 cd04dfd2 Michael Hanselmann
    Check that the required binaries exist.
2596 cd04dfd2 Michael Hanselmann

2597 75bf3149 Helga Velroyen
    @type hvparams: dict of strings
2598 75bf3149 Helga Velroyen
    @param hvparams: hypervisor parameters to be verified against, not used here
2599 75bf3149 Helga Velroyen

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

2602 eb58f9b1 Guido Trotter
    """
2603 1f4b9d39 Iustin Pop
    msgs = []
2604 25bce647 Santi Raffa
    kvmpath = constants.KVM_PATH
2605 25bce647 Santi Raffa
    if hvparams is not None:
2606 25bce647 Santi Raffa
      kvmpath = hvparams.get(constants.HV_KVM_PATH, constants.KVM_PATH)
2607 25bce647 Santi Raffa
    if not os.path.exists(kvmpath):
2608 25bce647 Santi Raffa
      msgs.append("The KVM binary ('%s') does not exist" % kvmpath)
2609 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2610 1f4b9d39 Iustin Pop
      msgs.append("The socat binary ('%s') does not exist" %
2611 1f4b9d39 Iustin Pop
                  constants.SOCAT_PATH)
2612 1f4b9d39 Iustin Pop
2613 1f4b9d39 Iustin Pop
    return self._FormatVerifyResults(msgs)
2614 14aa53cb Guido Trotter
2615 6b5605e8 Iustin Pop
  @classmethod
2616 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2617 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2618 6b5605e8 Iustin Pop

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

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

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

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

2753 8ef418bb Helga Velroyen
    @type hvparams: dict of strings
2754 8ef418bb Helga Velroyen
    @param hvparams: hypervisor params to be used on this node
2755 8ef418bb Helga Velroyen

2756 f5118ade Iustin Pop
    """
2757 f5118ade Iustin Pop
    cls.LinuxPowercycle()