Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 6b614440

History | View | Annotate | Download (93.5 kB)

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

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

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

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

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

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

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

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

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

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

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

193 ea2bcb82 Michael Hanselmann
  @see: L{_ProbeTapVnetHdr}
194 ea2bcb82 Michael Hanselmann

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

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

220 199b2053 Apollon Oikonomopoulos
   @type fd: int
221 199b2053 Apollon Oikonomopoulos
   @param fd: the file descriptor of /dev/net/tun
222 199b2053 Apollon Oikonomopoulos

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

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

244 199b2053 Apollon Oikonomopoulos
  @type vnet_hdr: boolean
245 199b2053 Apollon Oikonomopoulos
  @param vnet_hdr: Enable the VNET Header
246 199b2053 Apollon Oikonomopoulos
  @return: (ifname, tapfd)
247 199b2053 Apollon Oikonomopoulos
  @rtype: tuple
248 199b2053 Apollon Oikonomopoulos

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

277 91c10532 Andrea Spadaccini
  """
278 91c10532 Andrea Spadaccini
  def __init__(self, data):
279 91c10532 Andrea Spadaccini
    """Creates a new QMP message based on the passed data.
280 91c10532 Andrea Spadaccini

281 91c10532 Andrea Spadaccini
    """
282 91c10532 Andrea Spadaccini
    if not isinstance(data, dict):
283 91c10532 Andrea Spadaccini
      raise TypeError("QmpMessage must be initialized with a dict")
284 91c10532 Andrea Spadaccini
285 91c10532 Andrea Spadaccini
    self.data = data
286 91c10532 Andrea Spadaccini
287 91c10532 Andrea Spadaccini
  def __getitem__(self, field_name):
288 91c10532 Andrea Spadaccini
    """Get the value of the required field if present, or None.
289 91c10532 Andrea Spadaccini

290 91c10532 Andrea Spadaccini
    Overrides the [] operator to provide access to the message data,
291 91c10532 Andrea Spadaccini
    returning None if the required item is not in the message
292 91c10532 Andrea Spadaccini
    @return: the value of the field_name field, or None if field_name
293 91c10532 Andrea Spadaccini
             is not contained in the message
294 91c10532 Andrea Spadaccini

295 91c10532 Andrea Spadaccini
    """
296 9b87c2cf Michael Hanselmann
    return self.data.get(field_name, None)
297 91c10532 Andrea Spadaccini
298 91c10532 Andrea Spadaccini
  def __setitem__(self, field_name, field_value):
299 91c10532 Andrea Spadaccini
    """Set the value of the required field_name to field_value.
300 91c10532 Andrea Spadaccini

301 91c10532 Andrea Spadaccini
    """
302 91c10532 Andrea Spadaccini
    self.data[field_name] = field_value
303 91c10532 Andrea Spadaccini
304 91c10532 Andrea Spadaccini
  @staticmethod
305 91c10532 Andrea Spadaccini
  def BuildFromJsonString(json_string):
306 91c10532 Andrea Spadaccini
    """Build a QmpMessage from a JSON encoded string.
307 91c10532 Andrea Spadaccini

308 91c10532 Andrea Spadaccini
    @type json_string: str
309 91c10532 Andrea Spadaccini
    @param json_string: JSON string representing the message
310 91c10532 Andrea Spadaccini
    @rtype: L{QmpMessage}
311 91c10532 Andrea Spadaccini
    @return: a L{QmpMessage} built from json_string
312 91c10532 Andrea Spadaccini

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

334 91c10532 Andrea Spadaccini
    @type monitor_filename: string
335 91c10532 Andrea Spadaccini
    @param monitor_filename: the filename of the UNIX raw socket on which the
336 f028b2bf Dimitris Aragiorgis
                             monitor (QMP or simple one) is listening
337 91c10532 Andrea Spadaccini

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

362 91c10532 Andrea Spadaccini
    """
363 91c10532 Andrea Spadaccini
    if not self._connected:
364 f028b2bf Dimitris Aragiorgis
      raise errors.ProgrammerError("To use a MonitorSocket you need to first"
365 91c10532 Andrea Spadaccini
                                   " invoke connect() on it")
366 91c10532 Andrea Spadaccini
367 91c10532 Andrea Spadaccini
  def connect(self):
368 f028b2bf Dimitris Aragiorgis
    """Connects to the monitor.
369 91c10532 Andrea Spadaccini

370 f028b2bf Dimitris Aragiorgis
    Connects to the UNIX socket
371 91c10532 Andrea Spadaccini

372 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
373 91c10532 Andrea Spadaccini

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

390 f028b2bf Dimitris Aragiorgis
    It cannot be used after this call.
391 f028b2bf Dimitris Aragiorgis

392 f028b2bf Dimitris Aragiorgis
    """
393 f028b2bf Dimitris Aragiorgis
    self.sock.close()
394 f028b2bf Dimitris Aragiorgis
395 f028b2bf Dimitris Aragiorgis
396 f028b2bf Dimitris Aragiorgis
class QmpConnection(MonitorSocket):
397 f028b2bf Dimitris Aragiorgis
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
398 f028b2bf Dimitris Aragiorgis

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

420 f028b2bf Dimitris Aragiorgis
    Connects to the UNIX socket and makes sure that we can actually send and
421 f028b2bf Dimitris Aragiorgis
    receive data to the kvm instance via QMP.
422 f028b2bf Dimitris Aragiorgis

423 f028b2bf Dimitris Aragiorgis
    @raise errors.HypervisorError: when there are communication errors
424 f028b2bf Dimitris Aragiorgis
    @raise errors.ProgrammerError: when there are data serialization errors
425 f028b2bf Dimitris Aragiorgis

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

444 91c10532 Andrea Spadaccini
    Seeks for a QMP message in the given buf. If found, it parses it and
445 91c10532 Andrea Spadaccini
    returns it together with the rest of the characters in the buf.
446 91c10532 Andrea Spadaccini
    If no message is found, returns None and the whole buffer.
447 91c10532 Andrea Spadaccini

448 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
449 91c10532 Andrea Spadaccini

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

467 91c10532 Andrea Spadaccini
    @rtype: QmpMessage
468 91c10532 Andrea Spadaccini
    @return: the received message
469 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
470 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
471 91c10532 Andrea Spadaccini

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

503 91c10532 Andrea Spadaccini
    @type message: QmpMessage
504 91c10532 Andrea Spadaccini
    @param message: message to send to KVM
505 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
506 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
507 91c10532 Andrea Spadaccini

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

527 91c10532 Andrea Spadaccini
    @type command: str
528 91c10532 Andrea Spadaccini
    @param command: the command to execute
529 91c10532 Andrea Spadaccini
    @type arguments: dict
530 91c10532 Andrea Spadaccini
    @param arguments: dictionary of arguments to be passed to the command
531 91c10532 Andrea Spadaccini
    @rtype: dict
532 91c10532 Andrea Spadaccini
    @return: dictionary representing the received JSON object
533 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
534 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
535 91c10532 Andrea Spadaccini

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

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

747 98ec75d6 Iustin Pop
    """
748 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
749 98ec75d6 Iustin Pop
750 263b8de6 Guido Trotter
  @classmethod
751 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
752 7548396c Guido Trotter
    """Returns the instance uidfile.
753 7548396c Guido Trotter

754 7548396c Guido Trotter
    """
755 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
756 7548396c Guido Trotter
757 7548396c Guido Trotter
  @classmethod
758 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
759 263b8de6 Guido Trotter
    """Check pid file for instance information.
760 263b8de6 Guido Trotter

761 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
762 263b8de6 Guido Trotter
    information from its command line.
763 263b8de6 Guido Trotter

764 263b8de6 Guido Trotter
    @type pid: string or int
765 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
766 263b8de6 Guido Trotter
    @rtype: tuple
767 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
768 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
769 263b8de6 Guido Trotter

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

805 263b8de6 Guido Trotter
    @type instance_name: string
806 263b8de6 Guido Trotter
    @param instance_name: instance name
807 263b8de6 Guido Trotter
    @rtype: tuple
808 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
809 1f8b3a27 Guido Trotter

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

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

836 c4fbefc8 Guido Trotter
    """
837 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
838 c4fbefc8 Guido Trotter
839 0df4d98a Guido Trotter
  @classmethod
840 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
841 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
842 c4fbefc8 Guido Trotter

843 c4fbefc8 Guido Trotter
    """
844 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
845 c4fbefc8 Guido Trotter
846 91c10532 Andrea Spadaccini
  @classmethod
847 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
848 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
849 91c10532 Andrea Spadaccini

850 91c10532 Andrea Spadaccini
    """
851 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
852 91c10532 Andrea Spadaccini
853 86d6bc2a Guido Trotter
  @staticmethod
854 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
855 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
856 86d6bc2a Guido Trotter

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

859 86d6bc2a Guido Trotter
    """
860 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
861 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
862 86d6bc2a Guido Trotter
    else:
863 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
864 86d6bc2a Guido Trotter
865 0df4d98a Guido Trotter
  @classmethod
866 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
867 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
868 38e250ba Guido Trotter

869 38e250ba Guido Trotter
    """
870 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
871 38e250ba Guido Trotter
872 7e66c35b Guido Trotter
  @classmethod
873 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
874 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
875 547a63b7 Balazs Lecz

876 547a63b7 Balazs Lecz
    """
877 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
878 547a63b7 Balazs Lecz
879 547a63b7 Balazs Lecz
  @classmethod
880 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
881 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
882 5d9bfd87 Apollon Oikonomopoulos
    given instance.
883 5d9bfd87 Apollon Oikonomopoulos

884 5d9bfd87 Apollon Oikonomopoulos
    """
885 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
886 5d9bfd87 Apollon Oikonomopoulos
887 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
888 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
889 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
890 5d9bfd87 Apollon Oikonomopoulos

891 5d9bfd87 Apollon Oikonomopoulos
    """
892 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
893 5d9bfd87 Apollon Oikonomopoulos
894 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
895 4f580fef Sรฉbastien Bocahu
  def _InstanceKeymapFile(cls, instance_name):
896 4f580fef Sรฉbastien Bocahu
    """Returns the name of the file containing the keymap for a given instance
897 4f580fef Sรฉbastien Bocahu

898 4f580fef Sรฉbastien Bocahu
    """
899 4f580fef Sรฉbastien Bocahu
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
900 4f580fef Sรฉbastien Bocahu
901 4f580fef Sรฉbastien Bocahu
  @classmethod
902 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
903 7548396c Guido Trotter
    """Try to read a uid file
904 7548396c Guido Trotter

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

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

960 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
961 eb58f9b1 Guido Trotter
    @type instance: instance object
962 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
963 eb58f9b1 Guido Trotter
    @type seq: int
964 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
965 eb58f9b1 Guido Trotter
    @type nic: nic object
966 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
967 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
968 eb58f9b1 Guido Trotter

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

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

1018 b693125f Tsachy Shacham
    @type cpu_list: list of int
1019 b693125f Tsachy Shacham
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
1020 b693125f Tsachy Shacham
    @rtype: int
1021 b693125f Tsachy Shacham
    @return: a bit mask of CPU affinities
1022 b693125f Tsachy Shacham

1023 b693125f Tsachy Shacham
    """
1024 b693125f Tsachy Shacham
    if cpu_list == constants.CPU_PINNING_OFF:
1025 b693125f Tsachy Shacham
      return constants.CPU_PINNING_ALL_KVM
1026 b693125f Tsachy Shacham
    else:
1027 b693125f Tsachy Shacham
      return sum(2 ** cpu for cpu in cpu_list)
1028 b693125f Tsachy Shacham
1029 b693125f Tsachy Shacham
  @classmethod
1030 b693125f Tsachy Shacham
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
1031 b693125f Tsachy Shacham
    """Change CPU affinity for running VM according to given CPU mask.
1032 b693125f Tsachy Shacham

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

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

1071 b693125f Tsachy Shacham
    @type instance_name: string
1072 b693125f Tsachy Shacham
    @param instance_name: instance in question
1073 b693125f Tsachy Shacham
    @rtype: dictionary of int:int
1074 b693125f Tsachy Shacham
    @return: a dictionary mapping vCPU numbers to thread IDs
1075 b693125f Tsachy Shacham

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

1091 b693125f Tsachy Shacham
    @type instance_name: string
1092 b693125f Tsachy Shacham
    @param instance_name: name of instance
1093 b693125f Tsachy Shacham
    @type cpu_mask: string
1094 b693125f Tsachy Shacham
    @param cpu_mask: CPU pinning mask as entered by user
1095 b693125f Tsachy Shacham

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

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

1110 eb58f9b1 Guido Trotter
    """
1111 eb58f9b1 Guido Trotter
    result = []
1112 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1113 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
1114 eb58f9b1 Guido Trotter
        result.append(name)
1115 eb58f9b1 Guido Trotter
    return result
1116 eb58f9b1 Guido Trotter
1117 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
1118 eb58f9b1 Guido Trotter
    """Get instance properties.
1119 eb58f9b1 Guido Trotter

1120 4fbb3c60 Guido Trotter
    @type instance_name: string
1121 c41eea6e Iustin Pop
    @param instance_name: the instance name
1122 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
1123 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
1124 eb58f9b1 Guido Trotter

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

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

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

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

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

1252 b73f1c59 Guido Trotter
    @type kvmhelp: string
1253 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1254 839642c2 Iustin Pop
    @attention: this function must not have any side-effects; for
1255 839642c2 Iustin Pop
        example, it must not write to the filesystem, or read values
1256 839642c2 Iustin Pop
        from the current system the are expected to differ between
1257 839642c2 Iustin Pop
        nodes, since it is only run once at instance startup;
1258 839642c2 Iustin Pop
        actions/kvm arguments that can vary between systems should be
1259 839642c2 Iustin Pop
        done in L{_ExecuteKVMRuntime}
1260 839642c2 Iustin Pop

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

1602 38e250ba Guido Trotter
    """
1603 38e250ba Guido Trotter
    try:
1604 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1605 38e250ba Guido Trotter
                      data=data)
1606 90c024f6 Guido Trotter
    except EnvironmentError, err:
1607 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1608 38e250ba Guido Trotter
1609 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
1610 38e250ba Guido Trotter
    """Read an instance's KVM runtime
1611 38e250ba Guido Trotter

1612 38e250ba Guido Trotter
    """
1613 38e250ba Guido Trotter
    try:
1614 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1615 90c024f6 Guido Trotter
    except EnvironmentError, err:
1616 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1617 38e250ba Guido Trotter
    return file_content
1618 38e250ba Guido Trotter
1619 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1620 38e250ba Guido Trotter
    """Save an instance's KVM runtime
1621 38e250ba Guido Trotter

1622 38e250ba Guido Trotter
    """
1623 8bbcbb9e Dimitris Aragiorgis
    kvm_cmd, kvm_nics, hvparams, block_devices = kvm_runtime
1624 8bbcbb9e Dimitris Aragiorgis
1625 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1626 8bbcbb9e Dimitris Aragiorgis
    serialized_blockdevs = [(blk.ToDict(), link) for blk, link in block_devices]
1627 8bbcbb9e Dimitris Aragiorgis
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams,
1628 8bbcbb9e Dimitris Aragiorgis
                                      serialized_blockdevs))
1629 8bbcbb9e Dimitris Aragiorgis
1630 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
1631 38e250ba Guido Trotter
1632 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1633 38e250ba Guido Trotter
    """Load an instance's KVM runtime
1634 38e250ba Guido Trotter

1635 38e250ba Guido Trotter
    """
1636 30e42c4e Guido Trotter
    if not serialized_runtime:
1637 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1638 8bbcbb9e Dimitris Aragiorgis
1639 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
1640 8bbcbb9e Dimitris Aragiorgis
    if len(loaded_runtime) == 3:
1641 8bbcbb9e Dimitris Aragiorgis
      serialized_blockdevs = []
1642 8bbcbb9e Dimitris Aragiorgis
      kvm_cmd, serialized_nics, hvparams = loaded_runtime
1643 8bbcbb9e Dimitris Aragiorgis
    else:
1644 8bbcbb9e Dimitris Aragiorgis
      kvm_cmd, serialized_nics, hvparams, serialized_blockdevs = loaded_runtime
1645 8bbcbb9e Dimitris Aragiorgis
1646 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
1647 8bbcbb9e Dimitris Aragiorgis
    block_devices = [(objects.Disk.FromDict(sdisk), link)
1648 8bbcbb9e Dimitris Aragiorgis
                     for sdisk, link in serialized_blockdevs]
1649 8bbcbb9e Dimitris Aragiorgis
1650 8bbcbb9e Dimitris Aragiorgis
    return (kvm_cmd, kvm_nics, hvparams, block_devices)
1651 38e250ba Guido Trotter
1652 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1653 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
1654 76431533 Guido Trotter

1655 76431533 Guido Trotter
    @type name: string
1656 76431533 Guido Trotter
    @param name: instance name
1657 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1658 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1659 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1660 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1661 76431533 Guido Trotter

1662 76431533 Guido Trotter
    """
1663 5d9bfd87 Apollon Oikonomopoulos
    try:
1664 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1665 5d9bfd87 Apollon Oikonomopoulos
    finally:
1666 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
1667 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
1668 5d9bfd87 Apollon Oikonomopoulos
1669 76431533 Guido Trotter
    if result.failed:
1670 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1671 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
1672 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
1673 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
1674 76431533 Guido Trotter
1675 8bbcbb9e Dimitris Aragiorgis
  # 52/50 local variables
1676 8bbcbb9e Dimitris Aragiorgis
  # pylint: disable=R0914
1677 b73f1c59 Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1678 839642c2 Iustin Pop
    """Execute a KVM cmd, after completing it with some last minute data.
1679 ee5f20b0 Guido Trotter

1680 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1681 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1682 b73f1c59 Guido Trotter
    @type kvmhelp: string
1683 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1684 30e42c4e Guido Trotter

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

1903 ee5f20b0 Guido Trotter
    """
1904 5905901c Iustin Pop
    self._CheckDown(instance.name)
1905 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1906 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1907 7238edb5 Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1908 b73f1c59 Guido Trotter
                                           startup_paused, kvmhelp)
1909 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1910 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1911 ee5f20b0 Guido Trotter
1912 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
1913 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
1914 6567aff3 Guido Trotter

1915 6567aff3 Guido Trotter
    """
1916 eace6157 Michael Hanselmann
    # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
1917 eace6157 Michael Hanselmann
    # version. The monitor protocol is designed for human consumption, whereas
1918 eace6157 Michael Hanselmann
    # QMP is made for programmatic usage. In the worst case QMP can also
1919 eace6157 Michael Hanselmann
    # execute monitor commands. As it is, all calls to socat take at least
1920 eace6157 Michael Hanselmann
    # 500ms and likely more: socat can't detect the end of the reply and waits
1921 eace6157 Michael Hanselmann
    # for 500ms of no data received before exiting (500 ms is the default for
1922 eace6157 Michael Hanselmann
    # the "-t" parameter).
1923 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1924 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
1925 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
1926 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1927 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
1928 6567aff3 Guido Trotter
    if result.failed:
1929 afa9bb2e Michael Hanselmann
      msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
1930 afa9bb2e Michael Hanselmann
             " output: %s" %
1931 afa9bb2e Michael Hanselmann
             (command, instance_name, result.fail_reason, result.output))
1932 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
1933 6567aff3 Guido Trotter
1934 6567aff3 Guido Trotter
    return result
1935 6567aff3 Guido Trotter
1936 0745fe0e Dimitris Aragiorgis
  def _GetFreePCISlot(self, instance, dev):
1937 0745fe0e Dimitris Aragiorgis
    """Get the first available pci slot of a runnung instance.
1938 0745fe0e Dimitris Aragiorgis

1939 0745fe0e Dimitris Aragiorgis
    """
1940 0745fe0e Dimitris Aragiorgis
    slots = bitarray(32)
1941 0745fe0e Dimitris Aragiorgis
    slots.setall(False) # pylint: disable=E1101
1942 0745fe0e Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance.name, self._INFO_PCI_CMD)
1943 0745fe0e Dimitris Aragiorgis
    for line in output.stdout.splitlines():
1944 0745fe0e Dimitris Aragiorgis
      match = self._INFO_PCI_RE.search(line)
1945 0745fe0e Dimitris Aragiorgis
      if match:
1946 0745fe0e Dimitris Aragiorgis
        slot = int(match.group(1))
1947 0745fe0e Dimitris Aragiorgis
        slots[slot] = True
1948 0745fe0e Dimitris Aragiorgis
1949 0745fe0e Dimitris Aragiorgis
    [free] = slots.search(_AVAILABLE_PCI_SLOT, 1) # pylint: disable=E1101
1950 0745fe0e Dimitris Aragiorgis
    if not free:
1951 0745fe0e Dimitris Aragiorgis
      raise errors.HypervisorError("All PCI slots occupied")
1952 0745fe0e Dimitris Aragiorgis
1953 0745fe0e Dimitris Aragiorgis
    dev.pci = int(free)
1954 0745fe0e Dimitris Aragiorgis
1955 e506cce0 Dimitris Aragiorgis
  def HotplugSupported(self, instance, action, dev_type):
1956 e506cce0 Dimitris Aragiorgis
    """Check if hotplug is supported.
1957 e506cce0 Dimitris Aragiorgis

1958 e506cce0 Dimitris Aragiorgis
    Hotplug is *not* supported in case of:
1959 e506cce0 Dimitris Aragiorgis
     - qemu versions < 1.0
1960 e506cce0 Dimitris Aragiorgis
     - security models and chroot (disk hotplug)
1961 e506cce0 Dimitris Aragiorgis
     - fdsend module is missing (nic hot-add)
1962 e506cce0 Dimitris Aragiorgis

1963 e506cce0 Dimitris Aragiorgis
    @raise errors.HypervisorError: in previous cases
1964 e506cce0 Dimitris Aragiorgis

1965 e506cce0 Dimitris Aragiorgis
    """
1966 e506cce0 Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD)
1967 e506cce0 Dimitris Aragiorgis
    # TODO: search for netdev_add, drive_add, device_add.....
1968 e506cce0 Dimitris Aragiorgis
    match = self._INFO_VERSION_RE.search(output.stdout)
1969 e506cce0 Dimitris Aragiorgis
    if not match:
1970 e506cce0 Dimitris Aragiorgis
      raise errors.HotplugError("Try hotplug only in running instances.")
1971 e506cce0 Dimitris Aragiorgis
    v_major, v_min, _, _ = match.groups()
1972 e506cce0 Dimitris Aragiorgis
    if (v_major, v_min) <= (1, 0):
1973 e506cce0 Dimitris Aragiorgis
      raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0")
1974 e506cce0 Dimitris Aragiorgis
1975 e506cce0 Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
1976 e506cce0 Dimitris Aragiorgis
      hvp = instance.hvparams
1977 e506cce0 Dimitris Aragiorgis
      security_model = hvp[constants.HV_SECURITY_MODEL]
1978 e506cce0 Dimitris Aragiorgis
      use_chroot = hvp[constants.HV_KVM_USE_CHROOT]
1979 e506cce0 Dimitris Aragiorgis
      if use_chroot:
1980 e506cce0 Dimitris Aragiorgis
        raise errors.HotplugError("Disk hotplug is not supported"
1981 e506cce0 Dimitris Aragiorgis
                                  " in case of chroot.")
1982 e506cce0 Dimitris Aragiorgis
      if security_model != constants.HT_SM_NONE:
1983 e506cce0 Dimitris Aragiorgis
        raise errors.HotplugError("Disk Hotplug is not supported in case"
1984 e506cce0 Dimitris Aragiorgis
                                  " security models are used.")
1985 e506cce0 Dimitris Aragiorgis
1986 e506cce0 Dimitris Aragiorgis
    if (dev_type == constants.HOTPLUG_TARGET_NIC and
1987 e506cce0 Dimitris Aragiorgis
        action == constants.HOTPLUG_ACTION_ADD and not fdsend):
1988 e506cce0 Dimitris Aragiorgis
      raise errors.HotplugError("Cannot hot-add NIC."
1989 e506cce0 Dimitris Aragiorgis
                                " fdsend python module is missing.")
1990 e506cce0 Dimitris Aragiorgis
    return True
1991 e506cce0 Dimitris Aragiorgis
1992 e506cce0 Dimitris Aragiorgis
  def _CallHotplugCommand(self, name, cmd):
1993 e506cce0 Dimitris Aragiorgis
    output = self._CallMonitorCommand(name, cmd)
1994 e506cce0 Dimitris Aragiorgis
    # TODO: parse output and check if succeeded
1995 e506cce0 Dimitris Aragiorgis
    for line in output.stdout.splitlines():
1996 e506cce0 Dimitris Aragiorgis
      logging.info("%s", line)
1997 e506cce0 Dimitris Aragiorgis
1998 6283c5e3 Dimitris Aragiorgis
  def HotAddDevice(self, instance, dev_type, device, extra, seq):
1999 6283c5e3 Dimitris Aragiorgis
    """ Helper method to hot-add a new device
2000 6283c5e3 Dimitris Aragiorgis

2001 6283c5e3 Dimitris Aragiorgis
    It gets free pci slot generates the device name and invokes the
2002 6283c5e3 Dimitris Aragiorgis
    device specific method.
2003 6283c5e3 Dimitris Aragiorgis

2004 6283c5e3 Dimitris Aragiorgis
    """
2005 6283c5e3 Dimitris Aragiorgis
    # in case of hot-mod this is given
2006 6283c5e3 Dimitris Aragiorgis
    if device.pci is None:
2007 6283c5e3 Dimitris Aragiorgis
      self._GetFreePCISlot(instance, device)
2008 6283c5e3 Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, device)
2009 6283c5e3 Dimitris Aragiorgis
    runtime = self._LoadKVMRuntime(instance)
2010 6283c5e3 Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2011 6283c5e3 Dimitris Aragiorgis
      command = "drive_add dummy file=%s,if=none,id=%s,format=raw\n" % \
2012 6283c5e3 Dimitris Aragiorgis
                 (extra, kvm_devid)
2013 6283c5e3 Dimitris Aragiorgis
      command += ("device_add virtio-blk-pci,bus=pci.0,addr=%s,drive=%s,id=%s" %
2014 6283c5e3 Dimitris Aragiorgis
                  (hex(device.pci), kvm_devid, kvm_devid))
2015 6283c5e3 Dimitris Aragiorgis
    elif dev_type == constants.HOTPLUG_TARGET_NIC:
2016 6283c5e3 Dimitris Aragiorgis
      (tap, fd) = _OpenTap()
2017 6283c5e3 Dimitris Aragiorgis
      self._ConfigureNIC(instance, seq, device, tap)
2018 6283c5e3 Dimitris Aragiorgis
      self._PassTapFd(instance, fd, device)
2019 6283c5e3 Dimitris Aragiorgis
      command = "netdev_add tap,id=%s,fd=%s\n" % (kvm_devid, kvm_devid)
2020 6283c5e3 Dimitris Aragiorgis
      args = "virtio-net-pci,bus=pci.0,addr=%s,mac=%s,netdev=%s,id=%s" % \
2021 6283c5e3 Dimitris Aragiorgis
               (hex(device.pci), device.mac, kvm_devid, kvm_devid)
2022 6283c5e3 Dimitris Aragiorgis
      command += "device_add %s" % args
2023 6283c5e3 Dimitris Aragiorgis
      utils.WriteFile(self._InstanceNICFile(instance.name, seq), data=tap)
2024 6283c5e3 Dimitris Aragiorgis
2025 6283c5e3 Dimitris Aragiorgis
    self._CallHotplugCommand(instance.name, command)
2026 6283c5e3 Dimitris Aragiorgis
    # update relevant entries in runtime file
2027 6283c5e3 Dimitris Aragiorgis
    index = _DEVICE_RUNTIME_INDEX[dev_type]
2028 6283c5e3 Dimitris Aragiorgis
    entry = _RUNTIME_ENTRY[dev_type](device, extra)
2029 6283c5e3 Dimitris Aragiorgis
    runtime[index].append(entry)
2030 6283c5e3 Dimitris Aragiorgis
    self._SaveKVMRuntime(instance, runtime)
2031 6283c5e3 Dimitris Aragiorgis
2032 6283c5e3 Dimitris Aragiorgis
  def HotDelDevice(self, instance, dev_type, device, _, seq):
2033 6283c5e3 Dimitris Aragiorgis
    """ Helper method for hot-del device
2034 6283c5e3 Dimitris Aragiorgis

2035 6283c5e3 Dimitris Aragiorgis
    It gets device info from runtime file, generates the device name and
2036 6283c5e3 Dimitris Aragiorgis
    invokes the device specific method.
2037 6283c5e3 Dimitris Aragiorgis

2038 6283c5e3 Dimitris Aragiorgis
    """
2039 6283c5e3 Dimitris Aragiorgis
    runtime = self._LoadKVMRuntime(instance)
2040 6283c5e3 Dimitris Aragiorgis
    entry = _GetExistingDeviceInfo(dev_type, device, runtime)
2041 6283c5e3 Dimitris Aragiorgis
    kvm_device = _RUNTIME_DEVICE[dev_type](entry)
2042 6283c5e3 Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(dev_type, kvm_device)
2043 6283c5e3 Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_DISK:
2044 6b614440 Dimitris Aragiorgis
      command = "device_del %s\n" % kvm_devid
2045 6b614440 Dimitris Aragiorgis
      command += "drive_del %s" % kvm_devid
2046 6283c5e3 Dimitris Aragiorgis
    elif dev_type == constants.HOTPLUG_TARGET_NIC:
2047 6283c5e3 Dimitris Aragiorgis
      command = "device_del %s\n" % kvm_devid
2048 6283c5e3 Dimitris Aragiorgis
      command += "netdev_del %s" % kvm_devid
2049 6283c5e3 Dimitris Aragiorgis
      utils.RemoveFile(self._InstanceNICFile(instance.name, seq))
2050 6283c5e3 Dimitris Aragiorgis
    self._CallHotplugCommand(instance.name, command)
2051 6283c5e3 Dimitris Aragiorgis
    index = _DEVICE_RUNTIME_INDEX[dev_type]
2052 6283c5e3 Dimitris Aragiorgis
    runtime[index].remove(entry)
2053 6283c5e3 Dimitris Aragiorgis
    self._SaveKVMRuntime(instance, runtime)
2054 6283c5e3 Dimitris Aragiorgis
2055 6283c5e3 Dimitris Aragiorgis
    return kvm_device.pci
2056 6283c5e3 Dimitris Aragiorgis
2057 6283c5e3 Dimitris Aragiorgis
  def HotModDevice(self, instance, dev_type, device, _, seq):
2058 6283c5e3 Dimitris Aragiorgis
    """ Helper method for hot-mod device
2059 6283c5e3 Dimitris Aragiorgis

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

2063 6283c5e3 Dimitris Aragiorgis
    """
2064 6283c5e3 Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_TARGET_NIC:
2065 6283c5e3 Dimitris Aragiorgis
      # putting it back in the same pci slot
2066 6283c5e3 Dimitris Aragiorgis
      device.pci = self.HotDelDevice(instance, dev_type, device, _, seq)
2067 6283c5e3 Dimitris Aragiorgis
      # TODO: remove sleep when socat gets removed
2068 6283c5e3 Dimitris Aragiorgis
      time.sleep(2)
2069 6283c5e3 Dimitris Aragiorgis
      self.HotAddDevice(instance, dev_type, device, _, seq)
2070 6283c5e3 Dimitris Aragiorgis
2071 6283c5e3 Dimitris Aragiorgis
  def _PassTapFd(self, instance, fd, nic):
2072 6283c5e3 Dimitris Aragiorgis
    """Pass file descriptor to kvm process via monitor socket using SCM_RIGHTS
2073 6283c5e3 Dimitris Aragiorgis

2074 6283c5e3 Dimitris Aragiorgis
    """
2075 6283c5e3 Dimitris Aragiorgis
    # TODO: factor out code related to unix sockets.
2076 6283c5e3 Dimitris Aragiorgis
    #       squash common parts between monitor and qmp
2077 6283c5e3 Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId(constants.HOTPLUG_TARGET_NIC, nic)
2078 6283c5e3 Dimitris Aragiorgis
    command = "getfd %s\n" % kvm_devid
2079 6283c5e3 Dimitris Aragiorgis
    fds = [fd]
2080 6283c5e3 Dimitris Aragiorgis
    logging.info("%s", fds)
2081 139c240c Dimitris Aragiorgis
    try:
2082 139c240c Dimitris Aragiorgis
      monsock = MonitorSocket(self._InstanceMonitor(instance.name))
2083 139c240c Dimitris Aragiorgis
      monsock.connect()
2084 139c240c Dimitris Aragiorgis
      fdsend.sendfds(monsock.sock, command, fds=fds)
2085 139c240c Dimitris Aragiorgis
    finally:
2086 139c240c Dimitris Aragiorgis
      monsock.close()
2087 6283c5e3 Dimitris Aragiorgis
2088 b52d85c1 Guido Trotter
  @classmethod
2089 585c8187 Guido Trotter
  def _ParseKVMVersion(cls, text):
2090 585c8187 Guido Trotter
    """Parse the KVM version from the --help output.
2091 585c8187 Guido Trotter

2092 585c8187 Guido Trotter
    @type text: string
2093 585c8187 Guido Trotter
    @param text: output of kvm --help
2094 585c8187 Guido Trotter
    @return: (version, v_maj, v_min, v_rev)
2095 5c3d5dfd Iustin Pop
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
2096 585c8187 Guido Trotter

2097 585c8187 Guido Trotter
    """
2098 585c8187 Guido Trotter
    match = cls._VERSION_RE.search(text.splitlines()[0])
2099 585c8187 Guido Trotter
    if not match:
2100 585c8187 Guido Trotter
      raise errors.HypervisorError("Unable to get KVM version")
2101 585c8187 Guido Trotter
2102 585c8187 Guido Trotter
    v_all = match.group(0)
2103 585c8187 Guido Trotter
    v_maj = int(match.group(1))
2104 585c8187 Guido Trotter
    v_min = int(match.group(2))
2105 585c8187 Guido Trotter
    if match.group(4):
2106 585c8187 Guido Trotter
      v_rev = int(match.group(4))
2107 585c8187 Guido Trotter
    else:
2108 585c8187 Guido Trotter
      v_rev = 0
2109 585c8187 Guido Trotter
    return (v_all, v_maj, v_min, v_rev)
2110 585c8187 Guido Trotter
2111 585c8187 Guido Trotter
  @classmethod
2112 6e043e60 Guido Trotter
  def _GetKVMOutput(cls, kvm_path, option):
2113 6e043e60 Guido Trotter
    """Return the output of a kvm invocation
2114 e3b89628 Guido Trotter

2115 bc0fed4b Guido Trotter
    @type kvm_path: string
2116 bc0fed4b Guido Trotter
    @param kvm_path: path to the kvm executable
2117 bc0fed4b Guido Trotter
    @type option: a key of _KVMOPTS_CMDS
2118 bc0fed4b Guido Trotter
    @param option: kvm option to fetch the output from
2119 6e043e60 Guido Trotter
    @return: output a supported kvm invocation
2120 e3b89628 Guido Trotter
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
2121 e3b89628 Guido Trotter

2122 e3b89628 Guido Trotter
    """
2123 6e043e60 Guido Trotter
    assert option in cls._KVMOPTS_CMDS, "Invalid output option"
2124 6e043e60 Guido Trotter
2125 bc0fed4b Guido Trotter
    optlist, can_fail = cls._KVMOPTS_CMDS[option]
2126 bc0fed4b Guido Trotter
2127 bc0fed4b Guido Trotter
    result = utils.RunCmd([kvm_path] + optlist)
2128 bc0fed4b Guido Trotter
    if result.failed and not can_fail:
2129 af89fa76 Helga Velroyen
      raise errors.HypervisorError("Unable to get KVM %s output" %
2130 af89fa76 Helga Velroyen
                                    " ".join(cls._KVMOPTS_CMDS[option]))
2131 e3b89628 Guido Trotter
    return result.output
2132 e3b89628 Guido Trotter
2133 e3b89628 Guido Trotter
  @classmethod
2134 3b59ec02 Guido Trotter
  def _GetKVMVersion(cls, kvm_path):
2135 d7e4a2b1 Andrea Spadaccini
    """Return the installed KVM version.
2136 b52d85c1 Guido Trotter

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

2140 b52d85c1 Guido Trotter
    """
2141 6e043e60 Guido Trotter
    return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
2142 82e3bf85 Dimitris Aragiorgis
2143 82e3bf85 Dimitris Aragiorgis
  @classmethod
2144 82e3bf85 Dimitris Aragiorgis
  def _GetDefaultMachineVersion(cls, kvm_path):
2145 82e3bf85 Dimitris Aragiorgis
    """Return the default hardware revision (e.g. pc-1.1)
2146 82e3bf85 Dimitris Aragiorgis

2147 82e3bf85 Dimitris Aragiorgis
    """
2148 6e043e60 Guido Trotter
    output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2149 82e3bf85 Dimitris Aragiorgis
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
2150 82e3bf85 Dimitris Aragiorgis
    if match:
2151 82e3bf85 Dimitris Aragiorgis
      return match.group(1)
2152 82e3bf85 Dimitris Aragiorgis
    else:
2153 82e3bf85 Dimitris Aragiorgis
      return "pc"
2154 82e3bf85 Dimitris Aragiorgis
2155 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
2156 eb58f9b1 Guido Trotter
    """Stop an instance.
2157 eb58f9b1 Guido Trotter

2158 eb58f9b1 Guido Trotter
    """
2159 bbcf7ad0 Iustin Pop
    if name is not None and not force:
2160 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
2161 bbcf7ad0 Iustin Pop
    if name is None:
2162 bbcf7ad0 Iustin Pop
      name = instance.name
2163 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
2164 bbcf7ad0 Iustin Pop
    else:
2165 bbcf7ad0 Iustin Pop
      acpi = False
2166 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
2167 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
2168 bbcf7ad0 Iustin Pop
      if force or not acpi:
2169 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
2170 eb58f9b1 Guido Trotter
      else:
2171 d0c8c01d Iustin Pop
        self._CallMonitorCommand(name, "system_powerdown")
2172 eb58f9b1 Guido Trotter
2173 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
2174 8904b35c Guido Trotter
    """Cleanup after a stopped instance
2175 8904b35c Guido Trotter

2176 8904b35c Guido Trotter
    """
2177 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
2178 8904b35c Guido Trotter
    if pid > 0 and alive:
2179 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
2180 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
2181 eb58f9b1 Guido Trotter
2182 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
2183 eb58f9b1 Guido Trotter
    """Reboot an instance.
2184 eb58f9b1 Guido Trotter

2185 eb58f9b1 Guido Trotter
    """
2186 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
2187 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
2188 eb58f9b1 Guido Trotter
    # to shutdown and restart.
2189 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
2190 1f8b3a27 Guido Trotter
    if not alive:
2191 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
2192 78411c60 Iustin Pop
                                   " not running" % instance.name)
2193 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
2194 f02881e0 Guido Trotter
    # ...first load it...
2195 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
2196 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
2197 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
2198 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
2199 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
2200 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
2201 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2202 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2203 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
2204 eb58f9b1 Guido Trotter
2205 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
2206 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
2207 30e42c4e Guido Trotter

2208 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2209 30e42c4e Guido Trotter
    @param instance: instance to be migrated
2210 30e42c4e Guido Trotter
    @rtype: string
2211 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
2212 30e42c4e Guido Trotter

2213 30e42c4e Guido Trotter
    """
2214 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
2215 30e42c4e Guido Trotter
2216 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
2217 30e42c4e Guido Trotter
    """Prepare to accept an instance.
2218 30e42c4e Guido Trotter

2219 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2220 30e42c4e Guido Trotter
    @param instance: instance to be accepted
2221 30e42c4e Guido Trotter
    @type info: string
2222 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
2223 30e42c4e Guido Trotter
    @type target: string
2224 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
2225 30e42c4e Guido Trotter

2226 30e42c4e Guido Trotter
    """
2227 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2228 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
2229 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2230 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2231 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
2232 b73f1c59 Guido Trotter
                            incoming=incoming_address)
2233 30e42c4e Guido Trotter
2234 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
2235 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
2236 30e42c4e Guido Trotter

2237 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
2238 30e42c4e Guido Trotter

2239 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2240 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
2241 30e42c4e Guido Trotter

2242 30e42c4e Guido Trotter
    """
2243 30e42c4e Guido Trotter
    if success:
2244 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2245 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
2246 5d9bfd87 Apollon Oikonomopoulos
2247 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
2248 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
2249 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
2250 cc8a8ed7 Apollon Oikonomopoulos
          continue
2251 5d9bfd87 Apollon Oikonomopoulos
        try:
2252 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
2253 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
2254 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
2255 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
2256 5d9bfd87 Apollon Oikonomopoulos
          continue
2257 5d9bfd87 Apollon Oikonomopoulos
        try:
2258 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
2259 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
2260 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
2261 5d9bfd87 Apollon Oikonomopoulos
2262 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
2263 30e42c4e Guido Trotter
    else:
2264 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
2265 30e42c4e Guido Trotter
2266 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
2267 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
2268 30e42c4e Guido Trotter

2269 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
2270 30e42c4e Guido Trotter
    currently running.
2271 30e42c4e Guido Trotter

2272 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
2273 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
2274 30e42c4e Guido Trotter
    @type target: string
2275 30e42c4e Guido Trotter
    @param target: ip address of the target node
2276 30e42c4e Guido Trotter
    @type live: boolean
2277 30e42c4e Guido Trotter
    @param live: perform a live migration
2278 30e42c4e Guido Trotter

2279 30e42c4e Guido Trotter
    """
2280 58d38b02 Iustin Pop
    instance_name = instance.name
2281 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
2282 6a1434d7 Andrea Spadaccini
    _, _, alive = self._InstancePidAlive(instance_name)
2283 30e42c4e Guido Trotter
    if not alive:
2284 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
2285 30e42c4e Guido Trotter
2286 30e42c4e Guido Trotter
    if not live:
2287 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
2288 30e42c4e Guido Trotter
2289 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
2290 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
2291 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2292 e43d4f9f Apollon Oikonomopoulos
2293 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
2294 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
2295 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2296 e43d4f9f Apollon Oikonomopoulos
2297 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
2298 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
2299 30e42c4e Guido Trotter
2300 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
2301 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
2302 6a1434d7 Andrea Spadaccini

2303 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2304 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
2305 6a1434d7 Andrea Spadaccini
    @type success: bool
2306 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
2307 6a1434d7 Andrea Spadaccini
    @type live: bool
2308 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
2309 6a1434d7 Andrea Spadaccini

2310 6a1434d7 Andrea Spadaccini
    """
2311 6a1434d7 Andrea Spadaccini
    if success:
2312 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
2313 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
2314 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
2315 6a1434d7 Andrea Spadaccini
    elif live:
2316 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
2317 6a1434d7 Andrea Spadaccini
2318 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
2319 6a1434d7 Andrea Spadaccini
    """Get the migration status
2320 6a1434d7 Andrea Spadaccini

2321 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2322 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
2323 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
2324 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
2325 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
2326 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
2327 6a1434d7 Andrea Spadaccini

2328 6a1434d7 Andrea Spadaccini
    """
2329 d0c8c01d Iustin Pop
    info_command = "info migrate"
2330 6a1434d7 Andrea Spadaccini
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
2331 6a1434d7 Andrea Spadaccini
      result = self._CallMonitorCommand(instance.name, info_command)
2332 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
2333 30e42c4e Guido Trotter
      if not match:
2334 c4e388a5 Guido Trotter
        if not result.stdout:
2335 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
2336 c4e388a5 Guido Trotter
        else:
2337 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
2338 c4e388a5 Guido Trotter
                          result.stdout)
2339 30e42c4e Guido Trotter
      else:
2340 30e42c4e Guido Trotter
        status = match.group(1)
2341 6a1434d7 Andrea Spadaccini
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
2342 6a1434d7 Andrea Spadaccini
          migration_status = objects.MigrationStatus(status=status)
2343 61643226 Andrea Spadaccini
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
2344 61643226 Andrea Spadaccini
          if match:
2345 61643226 Andrea Spadaccini
            migration_status.transferred_ram = match.group("transferred")
2346 61643226 Andrea Spadaccini
            migration_status.total_ram = match.group("total")
2347 61643226 Andrea Spadaccini
2348 6a1434d7 Andrea Spadaccini
          return migration_status
2349 30e42c4e Guido Trotter
2350 6a1434d7 Andrea Spadaccini
        logging.warning("KVM: unknown migration status '%s'", status)
2351 6a1434d7 Andrea Spadaccini
2352 6a1434d7 Andrea Spadaccini
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
2353 6a1434d7 Andrea Spadaccini
2354 62457f51 Iustin Pop
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
2355 30e42c4e Guido Trotter
2356 3d836750 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
2357 3d836750 Guido Trotter
    """Balloon an instance memory to a certain value.
2358 3d836750 Guido Trotter

2359 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
2360 3d836750 Guido Trotter
    @param instance: instance to be accepted
2361 3d836750 Guido Trotter
    @type mem: int
2362 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
2363 3d836750 Guido Trotter

2364 3d836750 Guido Trotter
    """
2365 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2366 3d836750 Guido Trotter
2367 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
2368 eb58f9b1 Guido Trotter
    """Return information about the node.
2369 eb58f9b1 Guido Trotter

2370 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
2371 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
2372 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
2373 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
2374 34fbc862 Andrea Spadaccini
          - hv_version: the hypervisor version in the form (major, minor,
2375 34fbc862 Andrea Spadaccini
                        revision)
2376 eb58f9b1 Guido Trotter

2377 eb58f9b1 Guido Trotter
    """
2378 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
2379 4b9638dc Guido Trotter
    # FIXME: this is the global kvm version, but the actual version can be
2380 4b9638dc Guido Trotter
    # customized as an hv parameter. we should use the nodegroup's default kvm
2381 4b9638dc Guido Trotter
    # path parameter here.
2382 3b59ec02 Guido Trotter
    _, v_major, v_min, v_rev = self._GetKVMVersion(constants.KVM_PATH)
2383 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2384 34fbc862 Andrea Spadaccini
    return result
2385 eb58f9b1 Guido Trotter
2386 637ce7f9 Guido Trotter
  @classmethod
2387 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
2388 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
2389 eb58f9b1 Guido Trotter

2390 eb58f9b1 Guido Trotter
    """
2391 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2392 9d9bded1 Michael Hanselmann
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2393 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2394 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2395 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
2396 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2397 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2398 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
2399 55cc0a44 Michael Hanselmann
                                     host=instance.primary_node,
2400 052783ff Michael Hanselmann
                                     user=constants.SSH_CONSOLE_USER,
2401 55cc0a44 Michael Hanselmann
                                     command=cmd)
2402 3be34f57 Guido Trotter
2403 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2404 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2405 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
2406 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2407 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
2408 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
2409 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
2410 55cc0a44 Michael Hanselmann
                                     display=display)
2411 55cc0a44 Michael Hanselmann
2412 4d2cdb5a Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2413 4d2cdb5a Andrea Spadaccini
    if spice_bind:
2414 4d2cdb5a Andrea Spadaccini
      return objects.InstanceConsole(instance=instance.name,
2415 4d2cdb5a Andrea Spadaccini
                                     kind=constants.CONS_SPICE,
2416 4d2cdb5a Andrea Spadaccini
                                     host=spice_bind,
2417 4d2cdb5a Andrea Spadaccini
                                     port=instance.network_port)
2418 4d2cdb5a Andrea Spadaccini
2419 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
2420 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
2421 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
2422 55cc0a44 Michael Hanselmann
                                            instance.name))
2423 eb58f9b1 Guido Trotter
2424 eb58f9b1 Guido Trotter
  def Verify(self):
2425 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
2426 eb58f9b1 Guido Trotter

2427 cd04dfd2 Michael Hanselmann
    Check that the required binaries exist.
2428 cd04dfd2 Michael Hanselmann

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

2431 eb58f9b1 Guido Trotter
    """
2432 1f4b9d39 Iustin Pop
    msgs = []
2433 1f4b9d39 Iustin Pop
    # FIXME: this is the global kvm binary, but the actual path can be
2434 1f4b9d39 Iustin Pop
    # customized as an hv parameter; we should use the nodegroup's
2435 1f4b9d39 Iustin Pop
    # default kvm path parameter here.
2436 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
2437 1f4b9d39 Iustin Pop
      msgs.append("The KVM binary ('%s') does not exist" % constants.KVM_PATH)
2438 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2439 1f4b9d39 Iustin Pop
      msgs.append("The socat binary ('%s') does not exist" %
2440 1f4b9d39 Iustin Pop
                  constants.SOCAT_PATH)
2441 1f4b9d39 Iustin Pop
2442 1f4b9d39 Iustin Pop
    return self._FormatVerifyResults(msgs)
2443 14aa53cb Guido Trotter
2444 6b5605e8 Iustin Pop
  @classmethod
2445 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2446 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2447 6b5605e8 Iustin Pop

2448 6b5605e8 Iustin Pop
    @type hvparams:  dict
2449 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2450 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2451 6b5605e8 Iustin Pop

2452 6b5605e8 Iustin Pop
    """
2453 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2454 6b5605e8 Iustin Pop
2455 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
2456 df5ab9f0 Guido Trotter
    if kernel_path:
2457 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
2458 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
2459 205ab586 Iustin Pop
                                     " if a kernel is defined")
2460 6b5605e8 Iustin Pop
2461 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
2462 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
2463 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
2464 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
2465 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
2466 66d5dbef Guido Trotter
2467 14fd6c81 Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2468 14fd6c81 Guido Trotter
      serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2469 14fd6c81 Guido Trotter
      valid_speeds = constants.VALID_SERIAL_SPEEDS
2470 14fd6c81 Guido Trotter
      if not serial_speed or serial_speed not in valid_speeds:
2471 14fd6c81 Guido Trotter
        raise errors.HypervisorError("Invalid serial console speed, must be"
2472 14fd6c81 Guido Trotter
                                     " one of: %s" %
2473 14fd6c81 Guido Trotter
                                     utils.CommaJoin(valid_speeds))
2474 14fd6c81 Guido Trotter
2475 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2476 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
2477 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2478 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2479 835528af Iustin Pop
                                   " ISO path")
2480 f5118ade Iustin Pop
2481 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2482 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2483 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
2484 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
2485 d19d94db Guido Trotter
                                     " must be specified")
2486 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
2487 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
2488 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
2489 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
2490 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
2491 d19d94db Guido Trotter
2492 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2493 b451c4c7 Andrea Spadaccini
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2494 b1cb62bd Andrea Spadaccini
    if spice_bind:
2495 b1cb62bd Andrea Spadaccini
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2496 b1cb62bd Andrea Spadaccini
        # if an IP version is specified, the spice_bind parameter must be an
2497 b1cb62bd Andrea Spadaccini
        # IP of that family
2498 b1cb62bd Andrea Spadaccini
        if (netutils.IP4Address.IsValid(spice_bind) and
2499 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP4_VERSION):
2500 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv4 address (%s), but"
2501 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2502 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2503 b1cb62bd Andrea Spadaccini
2504 b1cb62bd Andrea Spadaccini
        if (netutils.IP6Address.IsValid(spice_bind) and
2505 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP6_VERSION):
2506 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv6 address (%s), but"
2507 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2508 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2509 b451c4c7 Andrea Spadaccini
    else:
2510 0e1b03b9 Andrea Spadaccini
      # All the other SPICE parameters depend on spice_bind being set. Raise an
2511 0e1b03b9 Andrea Spadaccini
      # error if any of them is set without it.
2512 07788a0b Michael Hanselmann
      for param in _SPICE_ADDITIONAL_PARAMS:
2513 0e1b03b9 Andrea Spadaccini
        if hvparams[param]:
2514 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: %s requires %s to be set" %
2515 0e1b03b9 Andrea Spadaccini
                                       (param, constants.HV_KVM_SPICE_BIND))
2516 b1cb62bd Andrea Spadaccini
2517 d19d94db Guido Trotter
  @classmethod
2518 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
2519 d19d94db Guido Trotter
    """Check the given parameters for validity.
2520 d19d94db Guido Trotter

2521 d19d94db Guido Trotter
    @type hvparams:  dict
2522 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2523 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2524 d19d94db Guido Trotter

2525 d19d94db Guido Trotter
    """
2526 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2527 d19d94db Guido Trotter
2528 82e3bf85 Dimitris Aragiorgis
    kvm_path = hvparams[constants.HV_KVM_PATH]
2529 82e3bf85 Dimitris Aragiorgis
2530 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2531 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2532 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2533 d19d94db Guido Trotter
      try:
2534 1feb39ec Guido Trotter
        pwd.getpwnam(username)
2535 d19d94db Guido Trotter
      except KeyError:
2536 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
2537 d19d94db Guido Trotter
                                     % username)
2538 d19d94db Guido Trotter
2539 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2540 b1cb62bd Andrea Spadaccini
    if spice_bind:
2541 b1cb62bd Andrea Spadaccini
      # only one of VNC and SPICE can be used currently.
2542 b1cb62bd Andrea Spadaccini
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2543 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("Both SPICE and VNC are configured, but"
2544 b1cb62bd Andrea Spadaccini
                                     " only one of them can be used at a"
2545 afa9bb2e Michael Hanselmann
                                     " given time")
2546 b1cb62bd Andrea Spadaccini
2547 3b59ec02 Guido Trotter
      # check that KVM supports SPICE
2548 6e043e60 Guido Trotter
      kvmhelp = cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP)
2549 0ad7f5d8 Guido Trotter
      if not cls._SPICE_RE.search(kvmhelp):
2550 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE is configured, but it is not"
2551 afa9bb2e Michael Hanselmann
                                     " supported according to 'kvm --help'")
2552 b1cb62bd Andrea Spadaccini
2553 b1cb62bd Andrea Spadaccini
      # if spice_bind is not an IP address, it must be a valid interface
2554 afa9bb2e Michael Hanselmann
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind) or
2555 afa9bb2e Michael Hanselmann
                       netutils.IP6Address.IsValid(spice_bind))
2556 b1cb62bd Andrea Spadaccini
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2557 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE: The %s parameter must be either"
2558 b1cb62bd Andrea Spadaccini
                                     " a valid IP address or interface name" %
2559 b1cb62bd Andrea Spadaccini
                                     constants.HV_KVM_SPICE_BIND)
2560 b1cb62bd Andrea Spadaccini
2561 82e3bf85 Dimitris Aragiorgis
    machine_version = hvparams[constants.HV_KVM_MACHINE_VERSION]
2562 82e3bf85 Dimitris Aragiorgis
    if machine_version:
2563 6e043e60 Guido Trotter
      output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2564 82e3bf85 Dimitris Aragiorgis
      if not cls._CHECK_MACHINE_VERSION_RE(machine_version).search(output):
2565 82e3bf85 Dimitris Aragiorgis
        raise errors.HypervisorError("Unsupported machine version: %s" %
2566 82e3bf85 Dimitris Aragiorgis
                                     machine_version)
2567 82e3bf85 Dimitris Aragiorgis
2568 f5118ade Iustin Pop
  @classmethod
2569 f5118ade Iustin Pop
  def PowercycleNode(cls):
2570 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
2571 f5118ade Iustin Pop

2572 f5118ade Iustin Pop
    """
2573 f5118ade Iustin Pop
    cls.LinuxPowercycle()