Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (91 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 6bf6870b Dimitris Aragiorgis
import copy
41 6bf6870b Dimitris Aragiorgis
from bitarray import bitarray
42 b693125f Tsachy Shacham
try:
43 471a31b6 Andrea Spadaccini
  import affinity   # pylint: disable=F0401
44 b693125f Tsachy Shacham
except ImportError:
45 b693125f Tsachy Shacham
  affinity = None
46 6bf6870b Dimitris Aragiorgis
try:
47 6bf6870b Dimitris Aragiorgis
  import fdsend   # pylint: disable=F0401
48 6bf6870b Dimitris Aragiorgis
except ImportError:
49 6bf6870b Dimitris Aragiorgis
  fdsend = None
50 eb58f9b1 Guido Trotter
51 eb58f9b1 Guido Trotter
from ganeti import utils
52 eb58f9b1 Guido Trotter
from ganeti import constants
53 eb58f9b1 Guido Trotter
from ganeti import errors
54 38e250ba Guido Trotter
from ganeti import serializer
55 38e250ba Guido Trotter
from ganeti import objects
56 76431533 Guido Trotter
from ganeti import uidpool
57 76431533 Guido Trotter
from ganeti import ssconf
58 a744b676 Manuel Franceschini
from ganeti import netutils
59 9d9bded1 Michael Hanselmann
from ganeti import pathutils
60 9d9bded1 Michael Hanselmann
from ganeti.hypervisor import hv_base
61 5d9bfd87 Apollon Oikonomopoulos
from ganeti.utils import wrapper as utils_wrapper
62 eb58f9b1 Guido Trotter
63 eb58f9b1 Guido Trotter
64 0e1e0b6a Michael Hanselmann
_KVM_NETWORK_SCRIPT = pathutils.CONF_DIR + "/kvm-vif-bridge"
65 b693125f Tsachy Shacham
_KVM_START_PAUSED_FLAG = "-S"
66 748e4b5a Michael Hanselmann
67 199b2053 Apollon Oikonomopoulos
# TUN/TAP driver constants, taken from <linux/if_tun.h>
68 199b2053 Apollon Oikonomopoulos
# They are architecture-independent and already hardcoded in qemu-kvm source,
69 199b2053 Apollon Oikonomopoulos
# so we can safely include them here.
70 199b2053 Apollon Oikonomopoulos
TUNSETIFF = 0x400454ca
71 199b2053 Apollon Oikonomopoulos
TUNGETIFF = 0x800454d2
72 199b2053 Apollon Oikonomopoulos
TUNGETFEATURES = 0x800454cf
73 199b2053 Apollon Oikonomopoulos
IFF_TAP = 0x0002
74 199b2053 Apollon Oikonomopoulos
IFF_NO_PI = 0x1000
75 199b2053 Apollon Oikonomopoulos
IFF_VNET_HDR = 0x4000
76 199b2053 Apollon Oikonomopoulos
77 07788a0b Michael Hanselmann
#: SPICE parameters which depend on L{constants.HV_KVM_SPICE_BIND}
78 07788a0b Michael Hanselmann
_SPICE_ADDITIONAL_PARAMS = frozenset([
79 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_IP_VERSION,
80 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_PASSWORD_FILE,
81 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR,
82 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_JPEG_IMG_COMPR,
83 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR,
84 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION,
85 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_USE_TLS,
86 07788a0b Michael Hanselmann
  ])
87 07788a0b Michael Hanselmann
88 6bf6870b Dimitris Aragiorgis
FREE = bitarray("0")
89 6bf6870b Dimitris Aragiorgis
90 6bf6870b Dimitris Aragiorgis
def _GenerateDeviceKVMId(dev_type, dev):
91 6bf6870b Dimitris Aragiorgis
92 6bf6870b Dimitris Aragiorgis
  if not dev or not dev.pci:
93 6bf6870b Dimitris Aragiorgis
    return None
94 6bf6870b Dimitris Aragiorgis
95 6bf6870b Dimitris Aragiorgis
  return "%s-%s-pci-%d" % (dev_type.lower(), dev.uuid.split("-")[0], dev.pci)
96 6bf6870b Dimitris Aragiorgis
97 6bf6870b Dimitris Aragiorgis
98 6bf6870b Dimitris Aragiorgis
def _UpdatePCISlots(dev, pci_reservations):
99 6bf6870b Dimitris Aragiorgis
  """Update pci configuration for a stopped instance
100 6bf6870b Dimitris Aragiorgis

101 6bf6870b Dimitris Aragiorgis
  If dev has a pci slot the reserve it, else find first available.
102 6bf6870b Dimitris Aragiorgis

103 6bf6870b Dimitris Aragiorgis
  """
104 6bf6870b Dimitris Aragiorgis
  if dev.pci:
105 6bf6870b Dimitris Aragiorgis
    free = dev.pci
106 6bf6870b Dimitris Aragiorgis
  else:
107 6bf6870b Dimitris Aragiorgis
    [free] = pci_reservations.search(FREE, 1) # pylint: disable=E1103
108 6bf6870b Dimitris Aragiorgis
    if not free:
109 6bf6870b Dimitris Aragiorgis
      raise errors.HypervisorError("All PCI slots occupied")
110 6bf6870b Dimitris Aragiorgis
    dev.pci = int(free)
111 6bf6870b Dimitris Aragiorgis
112 6bf6870b Dimitris Aragiorgis
  pci_reservations[free] = True
113 6bf6870b Dimitris Aragiorgis
114 6bf6870b Dimitris Aragiorgis
115 6bf6870b Dimitris Aragiorgis
def _RemoveFromRuntimeEntry(devices, device, fn):
116 6bf6870b Dimitris Aragiorgis
  try:
117 6bf6870b Dimitris Aragiorgis
    [rem] = [x for x in fn(devices) if x.uuid == device.uuid]
118 6bf6870b Dimitris Aragiorgis
    devices.remove(rem)
119 6bf6870b Dimitris Aragiorgis
  except (ValueError, IndexError):
120 6bf6870b Dimitris Aragiorgis
    logging.info("No device with uuid %s in runtime file", device.uuid)
121 6bf6870b Dimitris Aragiorgis
122 199b2053 Apollon Oikonomopoulos
123 ea2bcb82 Michael Hanselmann
def _GetTunFeatures(fd, _ioctl=fcntl.ioctl):
124 ea2bcb82 Michael Hanselmann
  """Retrieves supported TUN features from file descriptor.
125 ea2bcb82 Michael Hanselmann

126 ea2bcb82 Michael Hanselmann
  @see: L{_ProbeTapVnetHdr}
127 ea2bcb82 Michael Hanselmann

128 ea2bcb82 Michael Hanselmann
  """
129 ea2bcb82 Michael Hanselmann
  req = struct.pack("I", 0)
130 ea2bcb82 Michael Hanselmann
  try:
131 ea2bcb82 Michael Hanselmann
    buf = _ioctl(fd, TUNGETFEATURES, req)
132 ea2bcb82 Michael Hanselmann
  except EnvironmentError, err:
133 cfc24646 Iustin Pop
    logging.warning("ioctl(TUNGETFEATURES) failed: %s", err)
134 ea2bcb82 Michael Hanselmann
    return None
135 ea2bcb82 Michael Hanselmann
  else:
136 ea2bcb82 Michael Hanselmann
    (flags, ) = struct.unpack("I", buf)
137 ea2bcb82 Michael Hanselmann
    return flags
138 ea2bcb82 Michael Hanselmann
139 ea2bcb82 Michael Hanselmann
140 ea2bcb82 Michael Hanselmann
def _ProbeTapVnetHdr(fd, _features_fn=_GetTunFeatures):
141 199b2053 Apollon Oikonomopoulos
  """Check whether to enable the IFF_VNET_HDR flag.
142 199b2053 Apollon Oikonomopoulos

143 199b2053 Apollon Oikonomopoulos
  To do this, _all_ of the following conditions must be met:
144 199b2053 Apollon Oikonomopoulos
   1. TUNGETFEATURES ioctl() *must* be implemented
145 199b2053 Apollon Oikonomopoulos
   2. TUNGETFEATURES ioctl() result *must* contain the IFF_VNET_HDR flag
146 199b2053 Apollon Oikonomopoulos
   3. TUNGETIFF ioctl() *must* be implemented; reading the kernel code in
147 199b2053 Apollon Oikonomopoulos
      drivers/net/tun.c there is no way to test this until after the tap device
148 199b2053 Apollon Oikonomopoulos
      has been created using TUNSETIFF, and there is no way to change the
149 199b2053 Apollon Oikonomopoulos
      IFF_VNET_HDR flag after creating the interface, catch-22! However both
150 199b2053 Apollon Oikonomopoulos
      TUNGETIFF and TUNGETFEATURES were introduced in kernel version 2.6.27,
151 199b2053 Apollon Oikonomopoulos
      thus we can expect TUNGETIFF to be present if TUNGETFEATURES is.
152 199b2053 Apollon Oikonomopoulos

153 199b2053 Apollon Oikonomopoulos
   @type fd: int
154 199b2053 Apollon Oikonomopoulos
   @param fd: the file descriptor of /dev/net/tun
155 199b2053 Apollon Oikonomopoulos

156 199b2053 Apollon Oikonomopoulos
  """
157 ea2bcb82 Michael Hanselmann
  flags = _features_fn(fd)
158 199b2053 Apollon Oikonomopoulos
159 ea2bcb82 Michael Hanselmann
  if flags is None:
160 ea2bcb82 Michael Hanselmann
    # Not supported
161 199b2053 Apollon Oikonomopoulos
    return False
162 199b2053 Apollon Oikonomopoulos
163 ea2bcb82 Michael Hanselmann
  result = bool(flags & IFF_VNET_HDR)
164 ea2bcb82 Michael Hanselmann
165 ea2bcb82 Michael Hanselmann
  if not result:
166 ea2bcb82 Michael Hanselmann
    logging.warning("Kernel does not support IFF_VNET_HDR, not enabling")
167 ea2bcb82 Michael Hanselmann
168 ea2bcb82 Michael Hanselmann
  return result
169 ea2bcb82 Michael Hanselmann
170 199b2053 Apollon Oikonomopoulos
171 199b2053 Apollon Oikonomopoulos
def _OpenTap(vnet_hdr=True):
172 199b2053 Apollon Oikonomopoulos
  """Open a new tap device and return its file descriptor.
173 199b2053 Apollon Oikonomopoulos

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

177 199b2053 Apollon Oikonomopoulos
  @type vnet_hdr: boolean
178 199b2053 Apollon Oikonomopoulos
  @param vnet_hdr: Enable the VNET Header
179 199b2053 Apollon Oikonomopoulos
  @return: (ifname, tapfd)
180 199b2053 Apollon Oikonomopoulos
  @rtype: tuple
181 199b2053 Apollon Oikonomopoulos

182 199b2053 Apollon Oikonomopoulos
  """
183 199b2053 Apollon Oikonomopoulos
  try:
184 199b2053 Apollon Oikonomopoulos
    tapfd = os.open("/dev/net/tun", os.O_RDWR)
185 199b2053 Apollon Oikonomopoulos
  except EnvironmentError:
186 199b2053 Apollon Oikonomopoulos
    raise errors.HypervisorError("Failed to open /dev/net/tun")
187 199b2053 Apollon Oikonomopoulos
188 199b2053 Apollon Oikonomopoulos
  flags = IFF_TAP | IFF_NO_PI
189 199b2053 Apollon Oikonomopoulos
190 199b2053 Apollon Oikonomopoulos
  if vnet_hdr and _ProbeTapVnetHdr(tapfd):
191 199b2053 Apollon Oikonomopoulos
    flags |= IFF_VNET_HDR
192 199b2053 Apollon Oikonomopoulos
193 199b2053 Apollon Oikonomopoulos
  # The struct ifreq ioctl request (see netdevice(7))
194 199b2053 Apollon Oikonomopoulos
  ifr = struct.pack("16sh", "", flags)
195 199b2053 Apollon Oikonomopoulos
196 199b2053 Apollon Oikonomopoulos
  try:
197 199b2053 Apollon Oikonomopoulos
    res = fcntl.ioctl(tapfd, TUNSETIFF, ifr)
198 6f1e1921 Michael Hanselmann
  except EnvironmentError, err:
199 6f1e1921 Michael Hanselmann
    raise errors.HypervisorError("Failed to allocate a new TAP device: %s" %
200 6f1e1921 Michael Hanselmann
                                 err)
201 199b2053 Apollon Oikonomopoulos
202 199b2053 Apollon Oikonomopoulos
  # Get the interface name from the ioctl
203 199b2053 Apollon Oikonomopoulos
  ifname = struct.unpack("16sh", res)[0].strip("\x00")
204 199b2053 Apollon Oikonomopoulos
  return (ifname, tapfd)
205 199b2053 Apollon Oikonomopoulos
206 748e4b5a Michael Hanselmann
207 91c10532 Andrea Spadaccini
class QmpMessage:
208 91c10532 Andrea Spadaccini
  """QEMU Messaging Protocol (QMP) message.
209 91c10532 Andrea Spadaccini

210 91c10532 Andrea Spadaccini
  """
211 91c10532 Andrea Spadaccini
  def __init__(self, data):
212 91c10532 Andrea Spadaccini
    """Creates a new QMP message based on the passed data.
213 91c10532 Andrea Spadaccini

214 91c10532 Andrea Spadaccini
    """
215 91c10532 Andrea Spadaccini
    if not isinstance(data, dict):
216 91c10532 Andrea Spadaccini
      raise TypeError("QmpMessage must be initialized with a dict")
217 91c10532 Andrea Spadaccini
218 91c10532 Andrea Spadaccini
    self.data = data
219 91c10532 Andrea Spadaccini
220 91c10532 Andrea Spadaccini
  def __getitem__(self, field_name):
221 91c10532 Andrea Spadaccini
    """Get the value of the required field if present, or None.
222 91c10532 Andrea Spadaccini

223 91c10532 Andrea Spadaccini
    Overrides the [] operator to provide access to the message data,
224 91c10532 Andrea Spadaccini
    returning None if the required item is not in the message
225 91c10532 Andrea Spadaccini
    @return: the value of the field_name field, or None if field_name
226 91c10532 Andrea Spadaccini
             is not contained in the message
227 91c10532 Andrea Spadaccini

228 91c10532 Andrea Spadaccini
    """
229 9b87c2cf Michael Hanselmann
    return self.data.get(field_name, None)
230 91c10532 Andrea Spadaccini
231 91c10532 Andrea Spadaccini
  def __setitem__(self, field_name, field_value):
232 91c10532 Andrea Spadaccini
    """Set the value of the required field_name to field_value.
233 91c10532 Andrea Spadaccini

234 91c10532 Andrea Spadaccini
    """
235 91c10532 Andrea Spadaccini
    self.data[field_name] = field_value
236 91c10532 Andrea Spadaccini
237 91c10532 Andrea Spadaccini
  @staticmethod
238 91c10532 Andrea Spadaccini
  def BuildFromJsonString(json_string):
239 91c10532 Andrea Spadaccini
    """Build a QmpMessage from a JSON encoded string.
240 91c10532 Andrea Spadaccini

241 91c10532 Andrea Spadaccini
    @type json_string: str
242 91c10532 Andrea Spadaccini
    @param json_string: JSON string representing the message
243 91c10532 Andrea Spadaccini
    @rtype: L{QmpMessage}
244 91c10532 Andrea Spadaccini
    @return: a L{QmpMessage} built from json_string
245 91c10532 Andrea Spadaccini

246 91c10532 Andrea Spadaccini
    """
247 91c10532 Andrea Spadaccini
    # Parse the string
248 91c10532 Andrea Spadaccini
    data = serializer.LoadJson(json_string)
249 91c10532 Andrea Spadaccini
    return QmpMessage(data)
250 91c10532 Andrea Spadaccini
251 91c10532 Andrea Spadaccini
  def __str__(self):
252 a182a3ed Michael Hanselmann
    # The protocol expects the JSON object to be sent as a single line.
253 a182a3ed Michael Hanselmann
    return serializer.DumpJson(self.data)
254 91c10532 Andrea Spadaccini
255 91c10532 Andrea Spadaccini
  def __eq__(self, other):
256 91c10532 Andrea Spadaccini
    # When comparing two QmpMessages, we are interested in comparing
257 91c10532 Andrea Spadaccini
    # their internal representation of the message data
258 91c10532 Andrea Spadaccini
    return self.data == other.data
259 91c10532 Andrea Spadaccini
260 91c10532 Andrea Spadaccini
261 91c10532 Andrea Spadaccini
class QmpConnection:
262 91c10532 Andrea Spadaccini
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
263 91c10532 Andrea Spadaccini

264 91c10532 Andrea Spadaccini
  """
265 91c10532 Andrea Spadaccini
  _FIRST_MESSAGE_KEY = "QMP"
266 91c10532 Andrea Spadaccini
  _EVENT_KEY = "event"
267 91c10532 Andrea Spadaccini
  _ERROR_KEY = "error"
268 89da2ff3 Guido Trotter
  _RETURN_KEY = RETURN_KEY = "return"
269 89da2ff3 Guido Trotter
  _ACTUAL_KEY = ACTUAL_KEY = "actual"
270 91c10532 Andrea Spadaccini
  _ERROR_CLASS_KEY = "class"
271 91c10532 Andrea Spadaccini
  _ERROR_DATA_KEY = "data"
272 91c10532 Andrea Spadaccini
  _ERROR_DESC_KEY = "desc"
273 91c10532 Andrea Spadaccini
  _EXECUTE_KEY = "execute"
274 91c10532 Andrea Spadaccini
  _ARGUMENTS_KEY = "arguments"
275 91c10532 Andrea Spadaccini
  _CAPABILITIES_COMMAND = "qmp_capabilities"
276 91c10532 Andrea Spadaccini
  _MESSAGE_END_TOKEN = "\r\n"
277 91c10532 Andrea Spadaccini
  _SOCKET_TIMEOUT = 5
278 91c10532 Andrea Spadaccini
279 91c10532 Andrea Spadaccini
  def __init__(self, monitor_filename):
280 91c10532 Andrea Spadaccini
    """Instantiates the QmpConnection object.
281 91c10532 Andrea Spadaccini

282 91c10532 Andrea Spadaccini
    @type monitor_filename: string
283 91c10532 Andrea Spadaccini
    @param monitor_filename: the filename of the UNIX raw socket on which the
284 91c10532 Andrea Spadaccini
                             QMP monitor is listening
285 91c10532 Andrea Spadaccini

286 91c10532 Andrea Spadaccini
    """
287 91c10532 Andrea Spadaccini
    self.monitor_filename = monitor_filename
288 91c10532 Andrea Spadaccini
    self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
289 91c10532 Andrea Spadaccini
    # We want to fail if the server doesn't send a complete message
290 91c10532 Andrea Spadaccini
    # in a reasonable amount of time
291 91c10532 Andrea Spadaccini
    self.sock.settimeout(self._SOCKET_TIMEOUT)
292 91c10532 Andrea Spadaccini
    self._connected = False
293 91c10532 Andrea Spadaccini
    self._buf = ""
294 91c10532 Andrea Spadaccini
295 fc84cd5d Guido Trotter
  def _check_socket(self):
296 fc84cd5d Guido Trotter
    sock_stat = None
297 fc84cd5d Guido Trotter
    try:
298 fc84cd5d Guido Trotter
      sock_stat = os.stat(self.monitor_filename)
299 fc84cd5d Guido Trotter
    except EnvironmentError, err:
300 fc84cd5d Guido Trotter
      if err.errno == errno.ENOENT:
301 fc84cd5d Guido Trotter
        raise errors.HypervisorError("No qmp socket found")
302 fc84cd5d Guido Trotter
      else:
303 fc84cd5d Guido Trotter
        raise errors.HypervisorError("Error checking qmp socket: %s",
304 fc84cd5d Guido Trotter
                                     utils.ErrnoOrStr(err))
305 fc84cd5d Guido Trotter
    if not stat.S_ISSOCK(sock_stat.st_mode):
306 fc84cd5d Guido Trotter
      raise errors.HypervisorError("Qmp socket is not a socket")
307 fc84cd5d Guido Trotter
308 91c10532 Andrea Spadaccini
  def _check_connection(self):
309 91c10532 Andrea Spadaccini
    """Make sure that the connection is established.
310 91c10532 Andrea Spadaccini

311 91c10532 Andrea Spadaccini
    """
312 91c10532 Andrea Spadaccini
    if not self._connected:
313 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("To use a QmpConnection you need to first"
314 91c10532 Andrea Spadaccini
                                   " invoke connect() on it")
315 91c10532 Andrea Spadaccini
316 91c10532 Andrea Spadaccini
  def connect(self):
317 91c10532 Andrea Spadaccini
    """Connects to the QMP monitor.
318 91c10532 Andrea Spadaccini

319 91c10532 Andrea Spadaccini
    Connects to the UNIX socket and makes sure that we can actually send and
320 91c10532 Andrea Spadaccini
    receive data to the kvm instance via QMP.
321 91c10532 Andrea Spadaccini

322 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
323 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
324 91c10532 Andrea Spadaccini

325 91c10532 Andrea Spadaccini
    """
326 fc84cd5d Guido Trotter
    if self._connected:
327 fc84cd5d Guido Trotter
      raise errors.ProgrammerError("Cannot connect twice")
328 fc84cd5d Guido Trotter
329 fc84cd5d Guido Trotter
    self._check_socket()
330 fc84cd5d Guido Trotter
331 fc84cd5d Guido Trotter
    # Check file existance/stuff
332 fc84cd5d Guido Trotter
    try:
333 fc84cd5d Guido Trotter
      self.sock.connect(self.monitor_filename)
334 fc84cd5d Guido Trotter
    except EnvironmentError:
335 fc84cd5d Guido Trotter
      raise errors.HypervisorError("Can't connect to qmp socket")
336 91c10532 Andrea Spadaccini
    self._connected = True
337 91c10532 Andrea Spadaccini
338 91c10532 Andrea Spadaccini
    # Check if we receive a correct greeting message from the server
339 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 2.2)
340 91c10532 Andrea Spadaccini
    greeting = self._Recv()
341 91c10532 Andrea Spadaccini
    if not greeting[self._FIRST_MESSAGE_KEY]:
342 91c10532 Andrea Spadaccini
      self._connected = False
343 afa9bb2e Michael Hanselmann
      raise errors.HypervisorError("kvm: QMP communication error (wrong"
344 91c10532 Andrea Spadaccini
                                   " server greeting")
345 91c10532 Andrea Spadaccini
346 91c10532 Andrea Spadaccini
    # Let's put the monitor in command mode using the qmp_capabilities
347 91c10532 Andrea Spadaccini
    # command, or else no command will be executable.
348 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 4)
349 91c10532 Andrea Spadaccini
    self.Execute(self._CAPABILITIES_COMMAND)
350 91c10532 Andrea Spadaccini
351 91c10532 Andrea Spadaccini
  def _ParseMessage(self, buf):
352 91c10532 Andrea Spadaccini
    """Extract and parse a QMP message from the given buffer.
353 91c10532 Andrea Spadaccini

354 91c10532 Andrea Spadaccini
    Seeks for a QMP message in the given buf. If found, it parses it and
355 91c10532 Andrea Spadaccini
    returns it together with the rest of the characters in the buf.
356 91c10532 Andrea Spadaccini
    If no message is found, returns None and the whole buffer.
357 91c10532 Andrea Spadaccini

358 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
359 91c10532 Andrea Spadaccini

360 91c10532 Andrea Spadaccini
    """
361 91c10532 Andrea Spadaccini
    message = None
362 91c10532 Andrea Spadaccini
    # Check if we got the message end token (CRLF, as per the QEMU Protocol
363 91c10532 Andrea Spadaccini
    # Specification 0.1 - Section 2.1.1)
364 91c10532 Andrea Spadaccini
    pos = buf.find(self._MESSAGE_END_TOKEN)
365 91c10532 Andrea Spadaccini
    if pos >= 0:
366 91c10532 Andrea Spadaccini
      try:
367 91c10532 Andrea Spadaccini
        message = QmpMessage.BuildFromJsonString(buf[:pos + 1])
368 91c10532 Andrea Spadaccini
      except Exception, err:
369 91c10532 Andrea Spadaccini
        raise errors.ProgrammerError("QMP data serialization error: %s" % err)
370 91c10532 Andrea Spadaccini
      buf = buf[pos + 1:]
371 91c10532 Andrea Spadaccini
372 91c10532 Andrea Spadaccini
    return (message, buf)
373 91c10532 Andrea Spadaccini
374 91c10532 Andrea Spadaccini
  def _Recv(self):
375 91c10532 Andrea Spadaccini
    """Receives a message from QMP and decodes the received JSON object.
376 91c10532 Andrea Spadaccini

377 91c10532 Andrea Spadaccini
    @rtype: QmpMessage
378 91c10532 Andrea Spadaccini
    @return: the received message
379 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
380 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
381 91c10532 Andrea Spadaccini

382 91c10532 Andrea Spadaccini
    """
383 91c10532 Andrea Spadaccini
    self._check_connection()
384 91c10532 Andrea Spadaccini
385 91c10532 Andrea Spadaccini
    # Check if there is already a message in the buffer
386 91c10532 Andrea Spadaccini
    (message, self._buf) = self._ParseMessage(self._buf)
387 91c10532 Andrea Spadaccini
    if message:
388 91c10532 Andrea Spadaccini
      return message
389 91c10532 Andrea Spadaccini
390 91c10532 Andrea Spadaccini
    recv_buffer = StringIO.StringIO(self._buf)
391 91c10532 Andrea Spadaccini
    recv_buffer.seek(len(self._buf))
392 91c10532 Andrea Spadaccini
    try:
393 91c10532 Andrea Spadaccini
      while True:
394 91c10532 Andrea Spadaccini
        data = self.sock.recv(4096)
395 91c10532 Andrea Spadaccini
        if not data:
396 91c10532 Andrea Spadaccini
          break
397 91c10532 Andrea Spadaccini
        recv_buffer.write(data)
398 91c10532 Andrea Spadaccini
399 91c10532 Andrea Spadaccini
        (message, self._buf) = self._ParseMessage(recv_buffer.getvalue())
400 91c10532 Andrea Spadaccini
        if message:
401 91c10532 Andrea Spadaccini
          return message
402 91c10532 Andrea Spadaccini
403 91c10532 Andrea Spadaccini
    except socket.timeout, err:
404 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while receiving a QMP message: "
405 91c10532 Andrea Spadaccini
                                   "%s" % (err))
406 91c10532 Andrea Spadaccini
    except socket.error, err:
407 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to receive data from KVM using the"
408 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
409 91c10532 Andrea Spadaccini
410 91c10532 Andrea Spadaccini
  def _Send(self, message):
411 91c10532 Andrea Spadaccini
    """Encodes and sends a message to KVM using QMP.
412 91c10532 Andrea Spadaccini

413 91c10532 Andrea Spadaccini
    @type message: QmpMessage
414 91c10532 Andrea Spadaccini
    @param message: message to send to KVM
415 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
416 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
417 91c10532 Andrea Spadaccini

418 91c10532 Andrea Spadaccini
    """
419 91c10532 Andrea Spadaccini
    self._check_connection()
420 91c10532 Andrea Spadaccini
    try:
421 91c10532 Andrea Spadaccini
      message_str = str(message)
422 91c10532 Andrea Spadaccini
    except Exception, err:
423 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("QMP data deserialization error: %s" % err)
424 91c10532 Andrea Spadaccini
425 91c10532 Andrea Spadaccini
    try:
426 91c10532 Andrea Spadaccini
      self.sock.sendall(message_str)
427 91c10532 Andrea Spadaccini
    except socket.timeout, err:
428 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while sending a QMP message: "
429 91c10532 Andrea Spadaccini
                                   "%s (%s)" % (err.string, err.errno))
430 91c10532 Andrea Spadaccini
    except socket.error, err:
431 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to send data from KVM using the"
432 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
433 91c10532 Andrea Spadaccini
434 91c10532 Andrea Spadaccini
  def Execute(self, command, arguments=None):
435 91c10532 Andrea Spadaccini
    """Executes a QMP command and returns the response of the server.
436 91c10532 Andrea Spadaccini

437 91c10532 Andrea Spadaccini
    @type command: str
438 91c10532 Andrea Spadaccini
    @param command: the command to execute
439 91c10532 Andrea Spadaccini
    @type arguments: dict
440 91c10532 Andrea Spadaccini
    @param arguments: dictionary of arguments to be passed to the command
441 91c10532 Andrea Spadaccini
    @rtype: dict
442 91c10532 Andrea Spadaccini
    @return: dictionary representing the received JSON object
443 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
444 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
445 91c10532 Andrea Spadaccini

446 91c10532 Andrea Spadaccini
    """
447 91c10532 Andrea Spadaccini
    self._check_connection()
448 91c10532 Andrea Spadaccini
    message = QmpMessage({self._EXECUTE_KEY: command})
449 91c10532 Andrea Spadaccini
    if arguments:
450 91c10532 Andrea Spadaccini
      message[self._ARGUMENTS_KEY] = arguments
451 91c10532 Andrea Spadaccini
    self._Send(message)
452 91c10532 Andrea Spadaccini
453 91c10532 Andrea Spadaccini
    # Events can occur between the sending of the command and the reception
454 91c10532 Andrea Spadaccini
    # of the response, so we need to filter out messages with the event key.
455 91c10532 Andrea Spadaccini
    while True:
456 91c10532 Andrea Spadaccini
      response = self._Recv()
457 91c10532 Andrea Spadaccini
      err = response[self._ERROR_KEY]
458 91c10532 Andrea Spadaccini
      if err:
459 91c10532 Andrea Spadaccini
        raise errors.HypervisorError("kvm: error executing the %s"
460 91c10532 Andrea Spadaccini
                                     " command: %s (%s, %s):" %
461 91c10532 Andrea Spadaccini
                                     (command,
462 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DESC_KEY],
463 91c10532 Andrea Spadaccini
                                      err[self._ERROR_CLASS_KEY],
464 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DATA_KEY]))
465 91c10532 Andrea Spadaccini
466 91c10532 Andrea Spadaccini
      elif not response[self._EVENT_KEY]:
467 91c10532 Andrea Spadaccini
        return response
468 91c10532 Andrea Spadaccini
469 91c10532 Andrea Spadaccini
470 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
471 65107a2f Michael Hanselmann
  """KVM hypervisor interface
472 65107a2f Michael Hanselmann

473 65107a2f Michael Hanselmann
  """
474 d271c6fd Iustin Pop
  CAN_MIGRATE = True
475 eb58f9b1 Guido Trotter
476 9d9bded1 Michael Hanselmann
  _ROOT_DIR = pathutils.RUN_DIR + "/kvm-hypervisor"
477 a1d79fc6 Guido Trotter
  _PIDS_DIR = _ROOT_DIR + "/pid" # contains live instances pids
478 7548396c Guido Trotter
  _UIDS_DIR = _ROOT_DIR + "/uid" # contains instances reserved uids
479 a1d79fc6 Guido Trotter
  _CTRL_DIR = _ROOT_DIR + "/ctrl" # contains instances control sockets
480 a1d79fc6 Guido Trotter
  _CONF_DIR = _ROOT_DIR + "/conf" # contains instances startup data
481 5d9bfd87 Apollon Oikonomopoulos
  _NICS_DIR = _ROOT_DIR + "/nic" # contains instances nic <-> tap associations
482 4f580fef Sébastien Bocahu
  _KEYMAP_DIR = _ROOT_DIR + "/keymap" # contains instances keymaps
483 547a63b7 Balazs Lecz
  # KVM instances with chroot enabled are started in empty chroot directories.
484 547a63b7 Balazs Lecz
  _CHROOT_DIR = _ROOT_DIR + "/chroot" # for empty chroot directories
485 547a63b7 Balazs Lecz
  # After an instance is stopped, its chroot directory is removed.
486 547a63b7 Balazs Lecz
  # If the chroot directory is not empty, it can't be removed.
487 547a63b7 Balazs Lecz
  # A non-empty chroot directory indicates a possible security incident.
488 547a63b7 Balazs Lecz
  # To support forensics, the non-empty chroot directory is quarantined in
489 547a63b7 Balazs Lecz
  # a separate directory, called 'chroot-quarantine'.
490 547a63b7 Balazs Lecz
  _CHROOT_QUARANTINE_DIR = _ROOT_DIR + "/chroot-quarantine"
491 5d9bfd87 Apollon Oikonomopoulos
  _DIRS = [_ROOT_DIR, _PIDS_DIR, _UIDS_DIR, _CTRL_DIR, _CONF_DIR, _NICS_DIR,
492 2911f46c Iustin Pop
           _CHROOT_DIR, _CHROOT_QUARANTINE_DIR, _KEYMAP_DIR]
493 eb58f9b1 Guido Trotter
494 205ab586 Iustin Pop
  PARAMETERS = {
495 4b9638dc Guido Trotter
    constants.HV_KVM_PATH: hv_base.REQ_FILE_CHECK,
496 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK,
497 205ab586 Iustin Pop
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
498 205ab586 Iustin Pop
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
499 205ab586 Iustin Pop
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
500 205ab586 Iustin Pop
    constants.HV_ACPI: hv_base.NO_CHECK,
501 205ab586 Iustin Pop
    constants.HV_SERIAL_CONSOLE: hv_base.NO_CHECK,
502 14fd6c81 Guido Trotter
    constants.HV_SERIAL_SPEED: hv_base.NO_CHECK,
503 d6e5767e Klaus Aehlig
    constants.HV_VNC_BIND_ADDRESS: hv_base.NO_CHECK, # will be checked later
504 205ab586 Iustin Pop
    constants.HV_VNC_TLS: hv_base.NO_CHECK,
505 205ab586 Iustin Pop
    constants.HV_VNC_X509: hv_base.OPT_DIR_CHECK,
506 205ab586 Iustin Pop
    constants.HV_VNC_X509_VERIFY: hv_base.NO_CHECK,
507 6e6bb8d5 Guido Trotter
    constants.HV_VNC_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
508 b1cb62bd Andrea Spadaccini
    constants.HV_KVM_SPICE_BIND: hv_base.NO_CHECK, # will be checked later
509 b1cb62bd Andrea Spadaccini
    constants.HV_KVM_SPICE_IP_VERSION:
510 b1cb62bd Andrea Spadaccini
      (False, lambda x: (x == constants.IFACE_NO_IP_VERSION_SPECIFIED or
511 b1cb62bd Andrea Spadaccini
                         x in constants.VALID_IP_VERSIONS),
512 afa9bb2e Michael Hanselmann
       "The SPICE IP version should be 4 or 6",
513 b1cb62bd Andrea Spadaccini
       None, None),
514 b451c4c7 Andrea Spadaccini
    constants.HV_KVM_SPICE_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
515 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR:
516 5ae4945a Iustin Pop
      hv_base.ParamInSet(
517 5ae4945a Iustin Pop
        False, constants.HT_KVM_SPICE_VALID_LOSSLESS_IMG_COMPR_OPTIONS),
518 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_JPEG_IMG_COMPR:
519 5ae4945a Iustin Pop
      hv_base.ParamInSet(
520 5ae4945a Iustin Pop
        False, constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
521 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR:
522 5ae4945a Iustin Pop
      hv_base.ParamInSet(
523 5ae4945a Iustin Pop
        False, constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
524 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION:
525 5ae4945a Iustin Pop
      hv_base.ParamInSet(
526 5ae4945a Iustin Pop
        False, constants.HT_KVM_SPICE_VALID_VIDEO_STREAM_DETECTION_OPTIONS),
527 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_AUDIO_COMPR: hv_base.NO_CHECK,
528 bfe86c76 Andrea Spadaccini
    constants.HV_KVM_SPICE_USE_TLS: hv_base.NO_CHECK,
529 3e40b587 Andrea Spadaccini
    constants.HV_KVM_SPICE_TLS_CIPHERS: hv_base.NO_CHECK,
530 3e40b587 Andrea Spadaccini
    constants.HV_KVM_SPICE_USE_VDAGENT: hv_base.NO_CHECK,
531 cc130cc7 Marco Casavecchia
    constants.HV_KVM_FLOPPY_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
532 205ab586 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
533 cc130cc7 Marco Casavecchia
    constants.HV_KVM_CDROM2_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
534 d73ef63f Michael Hanselmann
    constants.HV_BOOT_ORDER:
535 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
536 d73ef63f Michael Hanselmann
    constants.HV_NIC_TYPE:
537 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
538 d73ef63f Michael Hanselmann
    constants.HV_DISK_TYPE:
539 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
540 cc130cc7 Marco Casavecchia
    constants.HV_KVM_CDROM_DISK_TYPE:
541 cc130cc7 Marco Casavecchia
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_DISK_TYPES),
542 d73ef63f Michael Hanselmann
    constants.HV_USB_MOUSE:
543 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
544 4f580fef Sébastien Bocahu
    constants.HV_KEYMAP: hv_base.NO_CHECK,
545 e2d14329 Andrea Spadaccini
    constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
546 2c368f28 Guido Trotter
    constants.HV_MIGRATION_BANDWIDTH: hv_base.REQ_NONNEGATIVE_INT_CHECK,
547 2c368f28 Guido Trotter
    constants.HV_MIGRATION_DOWNTIME: hv_base.REQ_NONNEGATIVE_INT_CHECK,
548 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
549 6b970cef Jun Futagawa
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
550 19572932 Iustin Pop
    constants.HV_DISK_CACHE:
551 19572932 Iustin Pop
      hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
552 d19d94db Guido Trotter
    constants.HV_SECURITY_MODEL:
553 d19d94db Guido Trotter
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_SM_TYPES),
554 d19d94db Guido Trotter
    constants.HV_SECURITY_DOMAIN: hv_base.NO_CHECK,
555 7ba594c0 Guido Trotter
    constants.HV_KVM_FLAG:
556 7ba594c0 Guido Trotter
      hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES),
557 fbe27e2b Guido Trotter
    constants.HV_VHOST_NET: hv_base.NO_CHECK,
558 547a63b7 Balazs Lecz
    constants.HV_KVM_USE_CHROOT: hv_base.NO_CHECK,
559 4f958b0b Miguel Di Ciurcio Filho
    constants.HV_MEM_PATH: hv_base.OPT_DIR_CHECK,
560 990ade2d Stephen Shirley
    constants.HV_REBOOT_BEHAVIOR:
561 a7f884d3 Tsachy Shacham
      hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
562 a7f884d3 Tsachy Shacham
    constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
563 3c286190 Dimitris Aragiorgis
    constants.HV_CPU_TYPE: hv_base.NO_CHECK,
564 2c368f28 Guido Trotter
    constants.HV_CPU_CORES: hv_base.OPT_NONNEGATIVE_INT_CHECK,
565 2c368f28 Guido Trotter
    constants.HV_CPU_THREADS: hv_base.OPT_NONNEGATIVE_INT_CHECK,
566 2c368f28 Guido Trotter
    constants.HV_CPU_SOCKETS: hv_base.OPT_NONNEGATIVE_INT_CHECK,
567 2fddb144 Guido Trotter
    constants.HV_SOUNDHW: hv_base.NO_CHECK,
568 156681c1 Guido Trotter
    constants.HV_USB_DEVICES: hv_base.NO_CHECK,
569 7589346f Guido Trotter
    constants.HV_VGA: hv_base.NO_CHECK,
570 e6f24d89 Guido Trotter
    constants.HV_KVM_EXTRA: hv_base.NO_CHECK,
571 4ab75599 Dimitris Aragiorgis
    constants.HV_KVM_MACHINE_VERSION: hv_base.NO_CHECK,
572 205ab586 Iustin Pop
    }
573 6b5605e8 Iustin Pop
574 f0db563d Guido Trotter
  _VIRTIO = "virtio"
575 f0db563d Guido Trotter
  _VIRTIO_NET_PCI = "virtio-net-pci"
576 f0db563d Guido Trotter
577 d0c8c01d Iustin Pop
  _MIGRATION_STATUS_RE = re.compile("Migration\s+status:\s+(\w+)",
578 30e42c4e Guido Trotter
                                    re.M | re.I)
579 65107a2f Michael Hanselmann
  _MIGRATION_PROGRESS_RE = \
580 527c0cf7 Michael Hanselmann
    re.compile(r"\s*transferred\s+ram:\s+(?P<transferred>\d+)\s+kbytes\s*\n"
581 527c0cf7 Michael Hanselmann
               r"\s*remaining\s+ram:\s+(?P<remaining>\d+)\s+kbytes\s*\n"
582 527c0cf7 Michael Hanselmann
               r"\s*total\s+ram:\s+(?P<total>\d+)\s+kbytes\s*\n", re.I)
583 61643226 Andrea Spadaccini
584 c4e388a5 Guido Trotter
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
585 c4e388a5 Guido Trotter
  _MIGRATION_INFO_RETRY_DELAY = 2
586 30e42c4e Guido Trotter
587 585c8187 Guido Trotter
  _VERSION_RE = re.compile(r"\b(\d+)\.(\d+)(\.(\d+))?\b")
588 b52d85c1 Guido Trotter
589 b693125f Tsachy Shacham
  _CPU_INFO_RE = re.compile(r"cpu\s+\#(\d+).*thread_id\s*=\s*(\d+)", re.I)
590 b693125f Tsachy Shacham
  _CPU_INFO_CMD = "info cpus"
591 b693125f Tsachy Shacham
  _CONT_CMD = "cont"
592 b693125f Tsachy Shacham
593 7f83345f Guido Trotter
  _DEFAULT_MACHINE_VERSION_RE = re.compile(r"^(\S+).*\(default\)", re.M)
594 82e3bf85 Dimitris Aragiorgis
  _CHECK_MACHINE_VERSION_RE = \
595 82e3bf85 Dimitris Aragiorgis
    staticmethod(lambda x: re.compile(r"^(%s)[ ]+.*PC" % x, re.M))
596 e6ba3320 Dimitris Aragiorgis
597 0ad7f5d8 Guido Trotter
  _QMP_RE = re.compile(r"^-qmp\s", re.M)
598 0ad7f5d8 Guido Trotter
  _SPICE_RE = re.compile(r"^-spice\s", re.M)
599 0ad7f5d8 Guido Trotter
  _VHOST_RE = re.compile(r"^-net\s.*,vhost=on|off", re.M)
600 0ad7f5d8 Guido Trotter
  _ENABLE_KVM_RE = re.compile(r"^-enable-kvm\s", re.M)
601 0ad7f5d8 Guido Trotter
  _DISABLE_KVM_RE = re.compile(r"^-disable-kvm\s", re.M)
602 0ad7f5d8 Guido Trotter
  _NETDEV_RE = re.compile(r"^-netdev\s", re.M)
603 99c7cd5b Guido Trotter
  _DISPLAY_RE = re.compile(r"^-display\s", re.M)
604 8cb5634a Guido Trotter
  _MACHINE_RE = re.compile(r"^-machine\s", re.M)
605 f0db563d Guido Trotter
  _NEW_VIRTIO_RE = re.compile(r"^name \"%s\"" % _VIRTIO_NET_PCI, re.M)
606 0ad7f5d8 Guido Trotter
  # match  -drive.*boot=on|off on different lines, but in between accept only
607 0ad7f5d8 Guido Trotter
  # dashes not preceeded by a new line (which would mean another option
608 0ad7f5d8 Guido Trotter
  # different than -drive is starting)
609 0ad7f5d8 Guido Trotter
  _BOOT_RE = re.compile(r"^-drive\s([^-]|(?<!^)-)*,boot=on\|off", re.M | re.S)
610 8feeb253 Christos Stavrakakis
  _UUID_RE = re.compile(r"^-uuid\s", re.M)
611 0ad7f5d8 Guido Trotter
612 6bf6870b Dimitris Aragiorgis
  _INFO_PCI_RE = re.compile(r'Bus.*device[ ]*(\d+).*')
613 6bf6870b Dimitris Aragiorgis
  _INFO_PCI_CMD = "info pci"
614 6bf6870b Dimitris Aragiorgis
  _INFO_VERSION_RE = \
615 6bf6870b Dimitris Aragiorgis
    re.compile(r'^QEMU (\d+)\.(\d+)(\.(\d+))?.*monitor.*', re.M)
616 6bf6870b Dimitris Aragiorgis
  _INFO_VERSION_CMD = "info version"
617 6bf6870b Dimitris Aragiorgis
618 6bf6870b Dimitris Aragiorgis
  _DEFAULT_PCI_RESERVATIONS = "11110000000000000000000000000000"
619 6bf6870b Dimitris Aragiorgis
620 64bfbc08 Guido Trotter
  ANCILLARY_FILES = [
621 64bfbc08 Guido Trotter
    _KVM_NETWORK_SCRIPT,
622 64bfbc08 Guido Trotter
    ]
623 69ab2e12 Guido Trotter
  ANCILLARY_FILES_OPT = [
624 69ab2e12 Guido Trotter
    _KVM_NETWORK_SCRIPT,
625 69ab2e12 Guido Trotter
    ]
626 64bfbc08 Guido Trotter
627 6e043e60 Guido Trotter
  # Supported kvm options to get output from
628 6e043e60 Guido Trotter
  _KVMOPT_HELP = "help"
629 6e043e60 Guido Trotter
  _KVMOPT_MLIST = "mlist"
630 f0db563d Guido Trotter
  _KVMOPT_DEVICELIST = "devicelist"
631 bc0fed4b Guido Trotter
632 bc0fed4b Guido Trotter
  # Command to execute to get the output from kvm, and whether to
633 bc0fed4b Guido Trotter
  # accept the output even on failure.
634 6e043e60 Guido Trotter
  _KVMOPTS_CMDS = {
635 bc0fed4b Guido Trotter
    _KVMOPT_HELP: (["--help"], False),
636 bc0fed4b Guido Trotter
    _KVMOPT_MLIST: (["-M", "?"], False),
637 bc0fed4b Guido Trotter
    _KVMOPT_DEVICELIST: (["-device", "?"], True),
638 6e043e60 Guido Trotter
  }
639 6e043e60 Guido Trotter
640 eb58f9b1 Guido Trotter
  def __init__(self):
641 eb58f9b1 Guido Trotter
    hv_base.BaseHypervisor.__init__(self)
642 eb58f9b1 Guido Trotter
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
643 eb58f9b1 Guido Trotter
    # in a tmpfs filesystem or has been otherwise wiped out.
644 29921401 Iustin Pop
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
645 9afb67fe Guido Trotter
    utils.EnsureDirs(dirs)
646 eb58f9b1 Guido Trotter
647 30786fc9 Iustin Pop
  @classmethod
648 30786fc9 Iustin Pop
  def _InstancePidFile(cls, instance_name):
649 98ec75d6 Iustin Pop
    """Returns the instance pidfile.
650 98ec75d6 Iustin Pop

651 98ec75d6 Iustin Pop
    """
652 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
653 98ec75d6 Iustin Pop
654 263b8de6 Guido Trotter
  @classmethod
655 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
656 7548396c Guido Trotter
    """Returns the instance uidfile.
657 7548396c Guido Trotter

658 7548396c Guido Trotter
    """
659 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
660 7548396c Guido Trotter
661 7548396c Guido Trotter
  @classmethod
662 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
663 263b8de6 Guido Trotter
    """Check pid file for instance information.
664 263b8de6 Guido Trotter

665 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
666 263b8de6 Guido Trotter
    information from its command line.
667 263b8de6 Guido Trotter

668 263b8de6 Guido Trotter
    @type pid: string or int
669 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
670 263b8de6 Guido Trotter
    @rtype: tuple
671 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
672 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
673 263b8de6 Guido Trotter

674 263b8de6 Guido Trotter
    """
675 263b8de6 Guido Trotter
    alive = utils.IsProcessAlive(pid)
676 263b8de6 Guido Trotter
    if not alive:
677 263b8de6 Guido Trotter
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
678 263b8de6 Guido Trotter
679 263b8de6 Guido Trotter
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
680 263b8de6 Guido Trotter
    try:
681 263b8de6 Guido Trotter
      cmdline = utils.ReadFile(cmdline_file)
682 263b8de6 Guido Trotter
    except EnvironmentError, err:
683 263b8de6 Guido Trotter
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
684 263b8de6 Guido Trotter
                                   (pid, err))
685 263b8de6 Guido Trotter
686 263b8de6 Guido Trotter
    instance = None
687 263b8de6 Guido Trotter
    memory = 0
688 263b8de6 Guido Trotter
    vcpus = 0
689 263b8de6 Guido Trotter
690 d0c8c01d Iustin Pop
    arg_list = cmdline.split("\x00")
691 263b8de6 Guido Trotter
    while arg_list:
692 e687ec01 Michael Hanselmann
      arg = arg_list.pop(0)
693 263b8de6 Guido Trotter
      if arg == "-name":
694 263b8de6 Guido Trotter
        instance = arg_list.pop(0)
695 263b8de6 Guido Trotter
      elif arg == "-m":
696 263b8de6 Guido Trotter
        memory = int(arg_list.pop(0))
697 263b8de6 Guido Trotter
      elif arg == "-smp":
698 4888a609 Guido Trotter
        vcpus = int(arg_list.pop(0).split(",")[0])
699 263b8de6 Guido Trotter
700 263b8de6 Guido Trotter
    if instance is None:
701 263b8de6 Guido Trotter
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
702 263b8de6 Guido Trotter
                                   " instance" % pid)
703 263b8de6 Guido Trotter
704 263b8de6 Guido Trotter
    return (instance, memory, vcpus)
705 263b8de6 Guido Trotter
706 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
707 263b8de6 Guido Trotter
    """Returns the instance pidfile, pid, and liveness.
708 263b8de6 Guido Trotter

709 263b8de6 Guido Trotter
    @type instance_name: string
710 263b8de6 Guido Trotter
    @param instance_name: instance name
711 263b8de6 Guido Trotter
    @rtype: tuple
712 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
713 1f8b3a27 Guido Trotter

714 1f8b3a27 Guido Trotter
    """
715 98ec75d6 Iustin Pop
    pidfile = self._InstancePidFile(instance_name)
716 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
717 263b8de6 Guido Trotter
718 263b8de6 Guido Trotter
    alive = False
719 263b8de6 Guido Trotter
    try:
720 263b8de6 Guido Trotter
      cmd_instance = self._InstancePidInfo(pid)[0]
721 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
722 263b8de6 Guido Trotter
    except errors.HypervisorError:
723 263b8de6 Guido Trotter
      pass
724 1f8b3a27 Guido Trotter
725 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
726 1f8b3a27 Guido Trotter
727 5905901c Iustin Pop
  def _CheckDown(self, instance_name):
728 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
729 5905901c Iustin Pop

730 5905901c Iustin Pop
    """
731 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
732 5905901c Iustin Pop
    if alive:
733 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
734 5905901c Iustin Pop
                                   (instance_name, "already running"))
735 5905901c Iustin Pop
736 0df4d98a Guido Trotter
  @classmethod
737 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
738 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
739 c4fbefc8 Guido Trotter

740 c4fbefc8 Guido Trotter
    """
741 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
742 c4fbefc8 Guido Trotter
743 0df4d98a Guido Trotter
  @classmethod
744 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
745 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
746 c4fbefc8 Guido Trotter

747 c4fbefc8 Guido Trotter
    """
748 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
749 c4fbefc8 Guido Trotter
750 91c10532 Andrea Spadaccini
  @classmethod
751 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
752 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
753 91c10532 Andrea Spadaccini

754 91c10532 Andrea Spadaccini
    """
755 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
756 91c10532 Andrea Spadaccini
757 86d6bc2a Guido Trotter
  @staticmethod
758 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
759 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
760 86d6bc2a Guido Trotter

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

763 86d6bc2a Guido Trotter
    """
764 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
765 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
766 86d6bc2a Guido Trotter
    else:
767 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
768 86d6bc2a Guido Trotter
769 0df4d98a Guido Trotter
  @classmethod
770 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
771 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
772 38e250ba Guido Trotter

773 38e250ba Guido Trotter
    """
774 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
775 38e250ba Guido Trotter
776 7e66c35b Guido Trotter
  @classmethod
777 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
778 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
779 547a63b7 Balazs Lecz

780 547a63b7 Balazs Lecz
    """
781 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
782 547a63b7 Balazs Lecz
783 547a63b7 Balazs Lecz
  @classmethod
784 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
785 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
786 5d9bfd87 Apollon Oikonomopoulos
    given instance.
787 5d9bfd87 Apollon Oikonomopoulos

788 5d9bfd87 Apollon Oikonomopoulos
    """
789 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
790 5d9bfd87 Apollon Oikonomopoulos
791 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
792 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
793 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
794 5d9bfd87 Apollon Oikonomopoulos

795 5d9bfd87 Apollon Oikonomopoulos
    """
796 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
797 5d9bfd87 Apollon Oikonomopoulos
798 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
799 4f580fef Sébastien Bocahu
  def _InstanceKeymapFile(cls, instance_name):
800 4f580fef Sébastien Bocahu
    """Returns the name of the file containing the keymap for a given instance
801 4f580fef Sébastien Bocahu

802 4f580fef Sébastien Bocahu
    """
803 4f580fef Sébastien Bocahu
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
804 4f580fef Sébastien Bocahu
805 4f580fef Sébastien Bocahu
  @classmethod
806 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
807 7548396c Guido Trotter
    """Try to read a uid file
808 7548396c Guido Trotter

809 7548396c Guido Trotter
    """
810 7548396c Guido Trotter
    if os.path.exists(uid_file):
811 7548396c Guido Trotter
      try:
812 682f7601 Guido Trotter
        uid = int(utils.ReadOneLineFile(uid_file))
813 aa0b600b Guido Trotter
        return uid
814 7548396c Guido Trotter
      except EnvironmentError:
815 7548396c Guido Trotter
        logging.warning("Can't read uid file", exc_info=True)
816 7548396c Guido Trotter
      except (TypeError, ValueError):
817 7548396c Guido Trotter
        logging.warning("Can't parse uid file contents", exc_info=True)
818 aa0b600b Guido Trotter
    return None
819 7548396c Guido Trotter
820 7548396c Guido Trotter
  @classmethod
821 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
822 547a63b7 Balazs Lecz
    """Removes an instance's rutime sockets/files/dirs.
823 7e66c35b Guido Trotter

824 7e66c35b Guido Trotter
    """
825 7e66c35b Guido Trotter
    utils.RemoveFile(pidfile)
826 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
827 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceSerial(instance_name))
828 91c10532 Andrea Spadaccini
    utils.RemoveFile(cls._InstanceQmpMonitor(instance_name))
829 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
830 4f580fef Sébastien Bocahu
    utils.RemoveFile(cls._InstanceKeymapFile(instance_name))
831 7548396c Guido Trotter
    uid_file = cls._InstanceUidFile(instance_name)
832 7548396c Guido Trotter
    uid = cls._TryReadUidFile(uid_file)
833 7548396c Guido Trotter
    utils.RemoveFile(uid_file)
834 7548396c Guido Trotter
    if uid is not None:
835 7548396c Guido Trotter
      uidpool.ReleaseUid(uid)
836 7be85163 Guido Trotter
    try:
837 7be85163 Guido Trotter
      shutil.rmtree(cls._InstanceNICDir(instance_name))
838 7be85163 Guido Trotter
    except OSError, err:
839 7be85163 Guido Trotter
      if err.errno != errno.ENOENT:
840 7be85163 Guido Trotter
        raise
841 547a63b7 Balazs Lecz
    try:
842 547a63b7 Balazs Lecz
      chroot_dir = cls._InstanceChrootDir(instance_name)
843 547a63b7 Balazs Lecz
      utils.RemoveDir(chroot_dir)
844 547a63b7 Balazs Lecz
    except OSError, err:
845 547a63b7 Balazs Lecz
      if err.errno == errno.ENOTEMPTY:
846 547a63b7 Balazs Lecz
        # The chroot directory is expected to be empty, but it isn't.
847 547a63b7 Balazs Lecz
        new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
848 547a63b7 Balazs Lecz
                                          prefix="%s-%s-" %
849 547a63b7 Balazs Lecz
                                          (instance_name,
850 547a63b7 Balazs Lecz
                                           utils.TimestampForFilename()))
851 547a63b7 Balazs Lecz
        logging.warning("The chroot directory of instance %s can not be"
852 547a63b7 Balazs Lecz
                        " removed as it is not empty. Moving it to the"
853 547a63b7 Balazs Lecz
                        " quarantine instead. Please investigate the"
854 547a63b7 Balazs Lecz
                        " contents (%s) and clean up manually",
855 547a63b7 Balazs Lecz
                        instance_name, new_chroot_dir)
856 547a63b7 Balazs Lecz
        utils.RenameFile(chroot_dir, new_chroot_dir)
857 547a63b7 Balazs Lecz
      else:
858 547a63b7 Balazs Lecz
        raise
859 7e66c35b Guido Trotter
860 748e4b5a Michael Hanselmann
  @staticmethod
861 5d9bfd87 Apollon Oikonomopoulos
  def _ConfigureNIC(instance, seq, nic, tap):
862 5d9bfd87 Apollon Oikonomopoulos
    """Run the network configuration script for a specified NIC
863 eb58f9b1 Guido Trotter

864 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
865 eb58f9b1 Guido Trotter
    @type instance: instance object
866 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
867 eb58f9b1 Guido Trotter
    @type seq: int
868 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
869 eb58f9b1 Guido Trotter
    @type nic: nic object
870 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
871 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
872 eb58f9b1 Guido Trotter

873 eb58f9b1 Guido Trotter
    """
874 5d9bfd87 Apollon Oikonomopoulos
    if instance.tags:
875 5d9bfd87 Apollon Oikonomopoulos
      tags = " ".join(instance.tags)
876 5d9bfd87 Apollon Oikonomopoulos
    else:
877 5d9bfd87 Apollon Oikonomopoulos
      tags = ""
878 5d9bfd87 Apollon Oikonomopoulos
879 5d9bfd87 Apollon Oikonomopoulos
    env = {
880 5d9bfd87 Apollon Oikonomopoulos
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
881 5d9bfd87 Apollon Oikonomopoulos
      "INSTANCE": instance.name,
882 5d9bfd87 Apollon Oikonomopoulos
      "MAC": nic.mac,
883 5d9bfd87 Apollon Oikonomopoulos
      "MODE": nic.nicparams[constants.NIC_MODE],
884 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE": tap,
885 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE_INDEX": str(seq),
886 5d9bfd87 Apollon Oikonomopoulos
      "TAGS": tags,
887 5d9bfd87 Apollon Oikonomopoulos
    }
888 5d9bfd87 Apollon Oikonomopoulos
889 5d9bfd87 Apollon Oikonomopoulos
    if nic.ip:
890 5d9bfd87 Apollon Oikonomopoulos
      env["IP"] = nic.ip
891 5d9bfd87 Apollon Oikonomopoulos
892 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_LINK]:
893 5d9bfd87 Apollon Oikonomopoulos
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
894 5d9bfd87 Apollon Oikonomopoulos
895 a5ad5e58 Apollon Oikonomopoulos
    if nic.network:
896 cbe4a0a5 Dimitris Aragiorgis
      n = objects.Network.FromDict(nic.netinfo)
897 7e8f03e3 Dimitris Aragiorgis
      env.update(n.HooksDict())
898 a5ad5e58 Apollon Oikonomopoulos
899 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
900 5d9bfd87 Apollon Oikonomopoulos
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
901 5d9bfd87 Apollon Oikonomopoulos
902 9d9bded1 Michael Hanselmann
    result = utils.RunCmd([pathutils.KVM_IFUP, tap], env=env)
903 5d9bfd87 Apollon Oikonomopoulos
    if result.failed:
904 afa9bb2e Michael Hanselmann
      raise errors.HypervisorError("Failed to configure interface %s: %s;"
905 afa9bb2e Michael Hanselmann
                                   " network configuration script output: %s" %
906 5d9bfd87 Apollon Oikonomopoulos
                                   (tap, result.fail_reason, result.output))
907 eb58f9b1 Guido Trotter
908 b693125f Tsachy Shacham
  @staticmethod
909 b693125f Tsachy Shacham
  def _VerifyAffinityPackage():
910 b693125f Tsachy Shacham
    if affinity is None:
911 b693125f Tsachy Shacham
      raise errors.HypervisorError("affinity Python package not"
912 5ae4945a Iustin Pop
                                   " found; cannot use CPU pinning under KVM")
913 b693125f Tsachy Shacham
914 b693125f Tsachy Shacham
  @staticmethod
915 b693125f Tsachy Shacham
  def _BuildAffinityCpuMask(cpu_list):
916 b693125f Tsachy Shacham
    """Create a CPU mask suitable for sched_setaffinity from a list of
917 b693125f Tsachy Shacham
    CPUs.
918 b693125f Tsachy Shacham

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

922 b693125f Tsachy Shacham
    @type cpu_list: list of int
923 b693125f Tsachy Shacham
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
924 b693125f Tsachy Shacham
    @rtype: int
925 b693125f Tsachy Shacham
    @return: a bit mask of CPU affinities
926 b693125f Tsachy Shacham

927 b693125f Tsachy Shacham
    """
928 b693125f Tsachy Shacham
    if cpu_list == constants.CPU_PINNING_OFF:
929 b693125f Tsachy Shacham
      return constants.CPU_PINNING_ALL_KVM
930 b693125f Tsachy Shacham
    else:
931 b693125f Tsachy Shacham
      return sum(2 ** cpu for cpu in cpu_list)
932 b693125f Tsachy Shacham
933 b693125f Tsachy Shacham
  @classmethod
934 b693125f Tsachy Shacham
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
935 b693125f Tsachy Shacham
    """Change CPU affinity for running VM according to given CPU mask.
936 b693125f Tsachy Shacham

937 b693125f Tsachy Shacham
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
938 b693125f Tsachy Shacham
    @type cpu_mask: string
939 b693125f Tsachy Shacham
    @param process_id: process ID of KVM process. Used to pin entire VM
940 b693125f Tsachy Shacham
                       to physical CPUs.
941 b693125f Tsachy Shacham
    @type process_id: int
942 b693125f Tsachy Shacham
    @param thread_dict: map of virtual CPUs to KVM thread IDs
943 b693125f Tsachy Shacham
    @type thread_dict: dict int:int
944 b693125f Tsachy Shacham

945 b693125f Tsachy Shacham
    """
946 b693125f Tsachy Shacham
    # Convert the string CPU mask to a list of list of int's
947 b693125f Tsachy Shacham
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
948 b693125f Tsachy Shacham
949 b693125f Tsachy Shacham
    if len(cpu_list) == 1:
950 b693125f Tsachy Shacham
      all_cpu_mapping = cpu_list[0]
951 b693125f Tsachy Shacham
      if all_cpu_mapping == constants.CPU_PINNING_OFF:
952 b693125f Tsachy Shacham
        # If CPU pinning has 1 entry that's "all", then do nothing
953 b693125f Tsachy Shacham
        pass
954 b693125f Tsachy Shacham
      else:
955 b693125f Tsachy Shacham
        # If CPU pinning has one non-all entry, map the entire VM to
956 b693125f Tsachy Shacham
        # one set of physical CPUs
957 b693125f Tsachy Shacham
        cls._VerifyAffinityPackage()
958 5ae4945a Iustin Pop
        affinity.set_process_affinity_mask(
959 5ae4945a Iustin Pop
          process_id, cls._BuildAffinityCpuMask(all_cpu_mapping))
960 b693125f Tsachy Shacham
    else:
961 b693125f Tsachy Shacham
      # The number of vCPUs mapped should match the number of vCPUs
962 b693125f Tsachy Shacham
      # reported by KVM. This was already verified earlier, so
963 b693125f Tsachy Shacham
      # here only as a sanity check.
964 b693125f Tsachy Shacham
      assert len(thread_dict) == len(cpu_list)
965 b693125f Tsachy Shacham
      cls._VerifyAffinityPackage()
966 b693125f Tsachy Shacham
967 b693125f Tsachy Shacham
      # For each vCPU, map it to the proper list of physical CPUs
968 b693125f Tsachy Shacham
      for vcpu, i in zip(cpu_list, range(len(cpu_list))):
969 b693125f Tsachy Shacham
        affinity.set_process_affinity_mask(thread_dict[i],
970 5ae4945a Iustin Pop
                                           cls._BuildAffinityCpuMask(vcpu))
971 b693125f Tsachy Shacham
972 b693125f Tsachy Shacham
  def _GetVcpuThreadIds(self, instance_name):
973 b693125f Tsachy Shacham
    """Get a mapping of vCPU no. to thread IDs for the instance
974 b693125f Tsachy Shacham

975 b693125f Tsachy Shacham
    @type instance_name: string
976 b693125f Tsachy Shacham
    @param instance_name: instance in question
977 b693125f Tsachy Shacham
    @rtype: dictionary of int:int
978 b693125f Tsachy Shacham
    @return: a dictionary mapping vCPU numbers to thread IDs
979 b693125f Tsachy Shacham

980 b693125f Tsachy Shacham
    """
981 b693125f Tsachy Shacham
    result = {}
982 b693125f Tsachy Shacham
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
983 b693125f Tsachy Shacham
    for line in output.stdout.splitlines():
984 b693125f Tsachy Shacham
      match = self._CPU_INFO_RE.search(line)
985 b693125f Tsachy Shacham
      if not match:
986 b693125f Tsachy Shacham
        continue
987 b693125f Tsachy Shacham
      grp = map(int, match.groups())
988 b693125f Tsachy Shacham
      result[grp[0]] = grp[1]
989 b693125f Tsachy Shacham
990 b693125f Tsachy Shacham
    return result
991 b693125f Tsachy Shacham
992 1d8a7812 Andrea Spadaccini
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
993 1d8a7812 Andrea Spadaccini
    """Complete CPU pinning.
994 b693125f Tsachy Shacham

995 b693125f Tsachy Shacham
    @type instance_name: string
996 b693125f Tsachy Shacham
    @param instance_name: name of instance
997 b693125f Tsachy Shacham
    @type cpu_mask: string
998 b693125f Tsachy Shacham
    @param cpu_mask: CPU pinning mask as entered by user
999 b693125f Tsachy Shacham

1000 b693125f Tsachy Shacham
    """
1001 1d8a7812 Andrea Spadaccini
    # Get KVM process ID, to be used if need to pin entire VM
1002 1d8a7812 Andrea Spadaccini
    _, pid, _ = self._InstancePidAlive(instance_name)
1003 1d8a7812 Andrea Spadaccini
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
1004 1d8a7812 Andrea Spadaccini
    thread_dict = self._GetVcpuThreadIds(instance_name)
1005 1d8a7812 Andrea Spadaccini
    # Run CPU pinning, based on configured mask
1006 1d8a7812 Andrea Spadaccini
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
1007 b693125f Tsachy Shacham
1008 58e356a9 Helga Velroyen
  def ListInstances(self, hvparams=None):
1009 eb58f9b1 Guido Trotter
    """Get the list of running instances.
1010 eb58f9b1 Guido Trotter

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

1014 eb58f9b1 Guido Trotter
    """
1015 eb58f9b1 Guido Trotter
    result = []
1016 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1017 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
1018 eb58f9b1 Guido Trotter
        result.append(name)
1019 eb58f9b1 Guido Trotter
    return result
1020 eb58f9b1 Guido Trotter
1021 0bbec3af Helga Velroyen
  def GetInstanceInfo(self, instance_name, hvparams=None):
1022 eb58f9b1 Guido Trotter
    """Get instance properties.
1023 eb58f9b1 Guido Trotter

1024 4fbb3c60 Guido Trotter
    @type instance_name: string
1025 c41eea6e Iustin Pop
    @param instance_name: the instance name
1026 0bbec3af Helga Velroyen
    @type hvparams: dict of strings
1027 0bbec3af Helga Velroyen
    @param hvparams: hvparams to be used with this instance
1028 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
1029 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
1030 eb58f9b1 Guido Trotter

1031 eb58f9b1 Guido Trotter
    """
1032 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
1033 1f8b3a27 Guido Trotter
    if not alive:
1034 eb58f9b1 Guido Trotter
      return None
1035 eb58f9b1 Guido Trotter
1036 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
1037 fc84cd5d Guido Trotter
    istat = "---b-"
1038 eb58f9b1 Guido Trotter
    times = "0"
1039 eb58f9b1 Guido Trotter
1040 89da2ff3 Guido Trotter
    try:
1041 89da2ff3 Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
1042 89da2ff3 Guido Trotter
      qmp.connect()
1043 89da2ff3 Guido Trotter
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
1044 89da2ff3 Guido Trotter
      # Will fail if ballooning is not enabled, but we can then just resort to
1045 89da2ff3 Guido Trotter
      # the value above.
1046 89da2ff3 Guido Trotter
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
1047 89da2ff3 Guido Trotter
      memory = mem_bytes / 1048576
1048 89da2ff3 Guido Trotter
    except errors.HypervisorError:
1049 89da2ff3 Guido Trotter
      pass
1050 89da2ff3 Guido Trotter
1051 fc84cd5d Guido Trotter
    return (instance_name, pid, memory, vcpus, istat, times)
1052 eb58f9b1 Guido Trotter
1053 0200a1af Helga Velroyen
  def GetAllInstancesInfo(self, hvparams=None):
1054 eb58f9b1 Guido Trotter
    """Get properties of all instances.
1055 eb58f9b1 Guido Trotter

1056 0200a1af Helga Velroyen
    @type hvparams: dict of strings
1057 0200a1af Helga Velroyen
    @param hvparams: hypervisor parameter
1058 c41eea6e Iustin Pop
    @return: list of tuples (name, id, memory, vcpus, stat, times)
1059 c41eea6e Iustin Pop

1060 eb58f9b1 Guido Trotter
    """
1061 eb58f9b1 Guido Trotter
    data = []
1062 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1063 263b8de6 Guido Trotter
      try:
1064 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
1065 263b8de6 Guido Trotter
      except errors.HypervisorError:
1066 3bc145d8 Bernardo Dal Seno
        # Ignore exceptions due to instances being shut down
1067 263b8de6 Guido Trotter
        continue
1068 263b8de6 Guido Trotter
      if info:
1069 263b8de6 Guido Trotter
        data.append(info)
1070 eb58f9b1 Guido Trotter
    return data
1071 eb58f9b1 Guido Trotter
1072 6bf6870b Dimitris Aragiorgis
  def _GetExistingDeviceKVMId(self, instance, dev_type, dev):
1073 6bf6870b Dimitris Aragiorgis
    (_, kvm_nics, __, block_devices) = self._LoadKVMRuntime(instance)
1074 6bf6870b Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_NIC:
1075 6bf6870b Dimitris Aragiorgis
      found = [n for n in kvm_nics
1076 6bf6870b Dimitris Aragiorgis
               if n.uuid == dev.uuid]
1077 6bf6870b Dimitris Aragiorgis
    elif dev_type == constants.HOTPLUG_DISK:
1078 6bf6870b Dimitris Aragiorgis
      found = [d for d, _ in block_devices
1079 6bf6870b Dimitris Aragiorgis
               if d.uuid == dev.uuid]
1080 6bf6870b Dimitris Aragiorgis
    dev_info = None
1081 6bf6870b Dimitris Aragiorgis
    if found:
1082 6bf6870b Dimitris Aragiorgis
      dev_info = found[0]
1083 6bf6870b Dimitris Aragiorgis
    return _GenerateDeviceKVMId(dev_type, dev_info)
1084 6bf6870b Dimitris Aragiorgis
1085 6bf6870b Dimitris Aragiorgis
  def _GenerateKVMBlockDevicesOptions(self, instance, kvm_cmd, block_devices,
1086 6bf6870b Dimitris Aragiorgis
                                      pci_reservations, kvmhelp):
1087 6bf6870b Dimitris Aragiorgis
1088 6bf6870b Dimitris Aragiorgis
    hvp = instance.hvparams
1089 6bf6870b Dimitris Aragiorgis
    boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
1090 6bf6870b Dimitris Aragiorgis
1091 6bf6870b Dimitris Aragiorgis
    # whether this is an older KVM version that uses the boot=on flag
1092 6bf6870b Dimitris Aragiorgis
    # on devices
1093 6bf6870b Dimitris Aragiorgis
    needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1094 6bf6870b Dimitris Aragiorgis
1095 6bf6870b Dimitris Aragiorgis
    disk_type = hvp[constants.HV_DISK_TYPE]
1096 6bf6870b Dimitris Aragiorgis
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
1097 6bf6870b Dimitris Aragiorgis
      #TODO: parse kvm -device ? output
1098 6bf6870b Dimitris Aragiorgis
      disk_model = "virtio-blk-pci"
1099 6bf6870b Dimitris Aragiorgis
      if_val = ",if=virtio"
1100 6bf6870b Dimitris Aragiorgis
    else:
1101 6bf6870b Dimitris Aragiorgis
      if_val = ",if=%s" % disk_type
1102 6bf6870b Dimitris Aragiorgis
    # Cache mode
1103 6bf6870b Dimitris Aragiorgis
    disk_cache = hvp[constants.HV_DISK_CACHE]
1104 6bf6870b Dimitris Aragiorgis
    if instance.disk_template in constants.DTS_EXT_MIRROR:
1105 6bf6870b Dimitris Aragiorgis
      if disk_cache != "none":
1106 6bf6870b Dimitris Aragiorgis
        # TODO: make this a hard error, instead of a silent overwrite
1107 6bf6870b Dimitris Aragiorgis
        logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
1108 6bf6870b Dimitris Aragiorgis
                        " to prevent shared storage corruption on migration",
1109 6bf6870b Dimitris Aragiorgis
                        disk_cache)
1110 6bf6870b Dimitris Aragiorgis
      cache_val = ",cache=none"
1111 6bf6870b Dimitris Aragiorgis
    elif disk_cache != constants.HT_CACHE_DEFAULT:
1112 6bf6870b Dimitris Aragiorgis
      cache_val = ",cache=%s" % disk_cache
1113 6bf6870b Dimitris Aragiorgis
    else:
1114 6bf6870b Dimitris Aragiorgis
      cache_val = ""
1115 6bf6870b Dimitris Aragiorgis
    for cfdev, dev_path in block_devices:
1116 6bf6870b Dimitris Aragiorgis
      if cfdev.mode != constants.DISK_RDWR:
1117 6bf6870b Dimitris Aragiorgis
        raise errors.HypervisorError("Instance has read-only disks which"
1118 6bf6870b Dimitris Aragiorgis
                                     " are not supported by KVM")
1119 6bf6870b Dimitris Aragiorgis
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
1120 6bf6870b Dimitris Aragiorgis
      boot_val = ""
1121 6bf6870b Dimitris Aragiorgis
      if boot_disk:
1122 6bf6870b Dimitris Aragiorgis
        kvm_cmd.extend(["-boot", "c"])
1123 6bf6870b Dimitris Aragiorgis
        boot_disk = False
1124 6bf6870b Dimitris Aragiorgis
        if needs_boot_flag and disk_type != constants.HT_DISK_IDE:
1125 6bf6870b Dimitris Aragiorgis
          boot_val = ",boot=on"
1126 6bf6870b Dimitris Aragiorgis
      drive_val = "file=%s,format=raw%s%s" % \
1127 6bf6870b Dimitris Aragiorgis
                  (dev_path, boot_val, cache_val)
1128 6bf6870b Dimitris Aragiorgis
      _UpdatePCISlots(cfdev, pci_reservations)
1129 6bf6870b Dimitris Aragiorgis
      kvm_devid = _GenerateDeviceKVMId("DISK", cfdev)
1130 6bf6870b Dimitris Aragiorgis
      if kvm_devid:
1131 6bf6870b Dimitris Aragiorgis
        #TODO: name id after model
1132 6bf6870b Dimitris Aragiorgis
        drive_val += (",if=none,id=%s" % kvm_devid)
1133 6bf6870b Dimitris Aragiorgis
        drive_val += (",bus=0,unit=%d" % cfdev.pci)
1134 6bf6870b Dimitris Aragiorgis
      else:
1135 6bf6870b Dimitris Aragiorgis
        drive_val += if_val
1136 6bf6870b Dimitris Aragiorgis
1137 6bf6870b Dimitris Aragiorgis
      kvm_cmd.extend(["-drive", drive_val])
1138 6bf6870b Dimitris Aragiorgis
1139 6bf6870b Dimitris Aragiorgis
      if kvm_devid:
1140 6bf6870b Dimitris Aragiorgis
        dev_val = ("%s,drive=%s,id=%s" %
1141 6bf6870b Dimitris Aragiorgis
                    (disk_model, kvm_devid, kvm_devid))
1142 6bf6870b Dimitris Aragiorgis
        dev_val += ",bus=pci.0,addr=%s" % hex(cfdev.pci)
1143 6bf6870b Dimitris Aragiorgis
        kvm_cmd.extend(["-device", dev_val])
1144 6bf6870b Dimitris Aragiorgis
1145 6bf6870b Dimitris Aragiorgis
    return kvm_cmd
1146 6bf6870b Dimitris Aragiorgis
1147 b73f1c59 Guido Trotter
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused,
1148 b73f1c59 Guido Trotter
                          kvmhelp):
1149 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
1150 eb58f9b1 Guido Trotter

1151 b73f1c59 Guido Trotter
    @type kvmhelp: string
1152 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1153 839642c2 Iustin Pop
    @attention: this function must not have any side-effects; for
1154 839642c2 Iustin Pop
        example, it must not write to the filesystem, or read values
1155 839642c2 Iustin Pop
        from the current system the are expected to differ between
1156 839642c2 Iustin Pop
        nodes, since it is only run once at instance startup;
1157 839642c2 Iustin Pop
        actions/kvm arguments that can vary between systems should be
1158 839642c2 Iustin Pop
        done in L{_ExecuteKVMRuntime}
1159 839642c2 Iustin Pop

1160 eb58f9b1 Guido Trotter
    """
1161 4888a609 Guido Trotter
    # pylint: disable=R0912,R0914,R0915
1162 4888a609 Guido Trotter
    hvp = instance.hvparams
1163 81e265f5 Guido Trotter
    self.ValidateParameters(hvp)
1164 4304964a Guido Trotter
1165 e687ec01 Michael Hanselmann
    pidfile = self._InstancePidFile(instance.name)
1166 4b9638dc Guido Trotter
    kvm = hvp[constants.HV_KVM_PATH]
1167 eb58f9b1 Guido Trotter
    kvm_cmd = [kvm]
1168 c6a39fc2 Guido Trotter
    # used just by the vnc server, if enabled
1169 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-name", instance.name])
1170 f5a4b9ce Guido Trotter
    kvm_cmd.extend(["-m", instance.beparams[constants.BE_MAXMEM]])
1171 4888a609 Guido Trotter
1172 4888a609 Guido Trotter
    smp_list = ["%s" % instance.beparams[constants.BE_VCPUS]]
1173 4888a609 Guido Trotter
    if hvp[constants.HV_CPU_CORES]:
1174 4888a609 Guido Trotter
      smp_list.append("cores=%s" % hvp[constants.HV_CPU_CORES])
1175 4888a609 Guido Trotter
    if hvp[constants.HV_CPU_THREADS]:
1176 4888a609 Guido Trotter
      smp_list.append("threads=%s" % hvp[constants.HV_CPU_THREADS])
1177 4888a609 Guido Trotter
    if hvp[constants.HV_CPU_SOCKETS]:
1178 4888a609 Guido Trotter
      smp_list.append("sockets=%s" % hvp[constants.HV_CPU_SOCKETS])
1179 4888a609 Guido Trotter
1180 4888a609 Guido Trotter
    kvm_cmd.extend(["-smp", ",".join(smp_list)])
1181 4888a609 Guido Trotter
1182 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-pidfile", pidfile])
1183 fcf5b670 Guido Trotter
    kvm_cmd.extend(["-balloon", "virtio"])
1184 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-daemonize"])
1185 6b5605e8 Iustin Pop
    if not instance.hvparams[constants.HV_ACPI]:
1186 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-no-acpi"])
1187 990ade2d Stephen Shirley
    if instance.hvparams[constants.HV_REBOOT_BEHAVIOR] == \
1188 990ade2d Stephen Shirley
        constants.INSTANCE_REBOOT_EXIT:
1189 990ade2d Stephen Shirley
      kvm_cmd.extend(["-no-reboot"])
1190 eb58f9b1 Guido Trotter
1191 4ab75599 Dimitris Aragiorgis
    mversion = hvp[constants.HV_KVM_MACHINE_VERSION]
1192 4ab75599 Dimitris Aragiorgis
    if not mversion:
1193 4b9638dc Guido Trotter
      mversion = self._GetDefaultMachineVersion(kvm)
1194 8cb5634a Guido Trotter
    if self._MACHINE_RE.search(kvmhelp):
1195 8cb5634a Guido Trotter
      # TODO (2.8): kernel_irqchip and kvm_shadow_mem machine properties, as
1196 8cb5634a Guido Trotter
      # extra hypervisor parameters. We should also investigate whether and how
1197 8cb5634a Guido Trotter
      # shadow_mem should be considered for the resource model.
1198 8cb5634a Guido Trotter
      if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED):
1199 8cb5634a Guido Trotter
        specprop = ",accel=kvm"
1200 8cb5634a Guido Trotter
      else:
1201 8cb5634a Guido Trotter
        specprop = ""
1202 8cb5634a Guido Trotter
      machinespec = "%s%s" % (mversion, specprop)
1203 8cb5634a Guido Trotter
      kvm_cmd.extend(["-machine", machinespec])
1204 8cb5634a Guido Trotter
    else:
1205 8cb5634a Guido Trotter
      kvm_cmd.extend(["-M", mversion])
1206 8cb5634a Guido Trotter
      if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED and
1207 8cb5634a Guido Trotter
          self._ENABLE_KVM_RE.search(kvmhelp)):
1208 8cb5634a Guido Trotter
        kvm_cmd.extend(["-enable-kvm"])
1209 8cb5634a Guido Trotter
      elif (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED and
1210 8cb5634a Guido Trotter
            self._DISABLE_KVM_RE.search(kvmhelp)):
1211 8cb5634a Guido Trotter
        kvm_cmd.extend(["-disable-kvm"])
1212 4ab75599 Dimitris Aragiorgis
1213 2b846304 Iustin Pop
    kernel_path = hvp[constants.HV_KERNEL_PATH]
1214 2b846304 Iustin Pop
    if kernel_path:
1215 6bf6870b Dimitris Aragiorgis
      boot_cdrom = boot_floppy = boot_network = False
1216 2b846304 Iustin Pop
    else:
1217 2b846304 Iustin Pop
      boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
1218 2b846304 Iustin Pop
      boot_floppy = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_FLOPPY
1219 2b846304 Iustin Pop
      boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
1220 8745c3d7 Guido Trotter
1221 b693125f Tsachy Shacham
    if startup_paused:
1222 b693125f Tsachy Shacham
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1223 b693125f Tsachy Shacham
1224 8745c3d7 Guido Trotter
    if boot_network:
1225 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-boot", "n"])
1226 1213604d Guido Trotter
1227 24be50e0 Iustin Pop
    # whether this is an older KVM version that uses the boot=on flag
1228 24be50e0 Iustin Pop
    # on devices
1229 0ad7f5d8 Guido Trotter
    needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1230 24be50e0 Iustin Pop
1231 a985b417 Iustin Pop
    disk_type = hvp[constants.HV_DISK_TYPE]
1232 eb58f9b1 Guido Trotter
1233 cc130cc7 Marco Casavecchia
    #Now we can specify a different device type for CDROM devices.
1234 cc130cc7 Marco Casavecchia
    cdrom_disk_type = hvp[constants.HV_KVM_CDROM_DISK_TYPE]
1235 cc130cc7 Marco Casavecchia
    if not cdrom_disk_type:
1236 cc130cc7 Marco Casavecchia
      cdrom_disk_type = disk_type
1237 cc130cc7 Marco Casavecchia
1238 a985b417 Iustin Pop
    iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
1239 66d5dbef Guido Trotter
    if iso_image:
1240 d0c8c01d Iustin Pop
      options = ",format=raw,media=cdrom"
1241 24be50e0 Iustin Pop
      # set cdrom 'if' type
1242 66d5dbef Guido Trotter
      if boot_cdrom:
1243 24be50e0 Iustin Pop
        actual_cdrom_type = constants.HT_DISK_IDE
1244 24be50e0 Iustin Pop
      elif cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1245 24be50e0 Iustin Pop
        actual_cdrom_type = "virtio"
1246 9dd363eb Guido Trotter
      else:
1247 24be50e0 Iustin Pop
        actual_cdrom_type = cdrom_disk_type
1248 24be50e0 Iustin Pop
      if_val = ",if=%s" % actual_cdrom_type
1249 24be50e0 Iustin Pop
      # set boot flag, if needed
1250 24be50e0 Iustin Pop
      boot_val = ""
1251 24be50e0 Iustin Pop
      if boot_cdrom:
1252 24be50e0 Iustin Pop
        kvm_cmd.extend(["-boot", "d"])
1253 24be50e0 Iustin Pop
        if needs_boot_flag:
1254 24be50e0 Iustin Pop
          boot_val = ",boot=on"
1255 24be50e0 Iustin Pop
      # and finally build the entire '-drive' value
1256 24be50e0 Iustin Pop
      drive_val = "file=%s%s%s%s" % (iso_image, options, if_val, boot_val)
1257 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1258 66d5dbef Guido Trotter
1259 cc130cc7 Marco Casavecchia
    iso_image2 = hvp[constants.HV_KVM_CDROM2_IMAGE_PATH]
1260 cc130cc7 Marco Casavecchia
    if iso_image2:
1261 d0c8c01d Iustin Pop
      options = ",format=raw,media=cdrom"
1262 cc130cc7 Marco Casavecchia
      if cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1263 d0c8c01d Iustin Pop
        if_val = ",if=virtio"
1264 cc130cc7 Marco Casavecchia
      else:
1265 d0c8c01d Iustin Pop
        if_val = ",if=%s" % cdrom_disk_type
1266 24be50e0 Iustin Pop
      drive_val = "file=%s%s%s" % (iso_image2, options, if_val)
1267 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1268 cc130cc7 Marco Casavecchia
1269 cc130cc7 Marco Casavecchia
    floppy_image = hvp[constants.HV_KVM_FLOPPY_IMAGE_PATH]
1270 cc130cc7 Marco Casavecchia
    if floppy_image:
1271 d0c8c01d Iustin Pop
      options = ",format=raw,media=disk"
1272 cc130cc7 Marco Casavecchia
      if boot_floppy:
1273 d0c8c01d Iustin Pop
        kvm_cmd.extend(["-boot", "a"])
1274 d0c8c01d Iustin Pop
        options = "%s,boot=on" % options
1275 d0c8c01d Iustin Pop
      if_val = ",if=floppy"
1276 d0c8c01d Iustin Pop
      options = "%s%s" % (options, if_val)
1277 d0c8c01d Iustin Pop
      drive_val = "file=%s%s" % (floppy_image, options)
1278 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1279 cc130cc7 Marco Casavecchia
1280 df5ab9f0 Guido Trotter
    if kernel_path:
1281 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-kernel", kernel_path])
1282 a985b417 Iustin Pop
      initrd_path = hvp[constants.HV_INITRD_PATH]
1283 df5ab9f0 Guido Trotter
      if initrd_path:
1284 d0c8c01d Iustin Pop
        kvm_cmd.extend(["-initrd", initrd_path])
1285 d0c8c01d Iustin Pop
      root_append = ["root=%s" % hvp[constants.HV_ROOT_PATH],
1286 07813a9e Iustin Pop
                     hvp[constants.HV_KERNEL_ARGS]]
1287 07813a9e Iustin Pop
      if hvp[constants.HV_SERIAL_CONSOLE]:
1288 14fd6c81 Guido Trotter
        serial_speed = hvp[constants.HV_SERIAL_SPEED]
1289 14fd6c81 Guido Trotter
        root_append.append("console=ttyS0,%s" % serial_speed)
1290 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-append", " ".join(root_append)])
1291 eb58f9b1 Guido Trotter
1292 4f958b0b Miguel Di Ciurcio Filho
    mem_path = hvp[constants.HV_MEM_PATH]
1293 4f958b0b Miguel Di Ciurcio Filho
    if mem_path:
1294 9d3015f9 Guido Trotter
      kvm_cmd.extend(["-mem-path", mem_path, "-mem-prealloc"])
1295 4f958b0b Miguel Di Ciurcio Filho
1296 596b2459 Guido Trotter
    monitor_dev = ("unix:%s,server,nowait" %
1297 596b2459 Guido Trotter
                   self._InstanceMonitor(instance.name))
1298 596b2459 Guido Trotter
    kvm_cmd.extend(["-monitor", monitor_dev])
1299 596b2459 Guido Trotter
    if hvp[constants.HV_SERIAL_CONSOLE]:
1300 596b2459 Guido Trotter
      serial_dev = ("unix:%s,server,nowait" %
1301 596b2459 Guido Trotter
                    self._InstanceSerial(instance.name))
1302 596b2459 Guido Trotter
      kvm_cmd.extend(["-serial", serial_dev])
1303 596b2459 Guido Trotter
    else:
1304 596b2459 Guido Trotter
      kvm_cmd.extend(["-serial", "none"])
1305 596b2459 Guido Trotter
1306 a985b417 Iustin Pop
    mouse_type = hvp[constants.HV_USB_MOUSE]
1307 31f6f67a Guido Trotter
    vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
1308 596b2459 Guido Trotter
    spice_bind = hvp[constants.HV_KVM_SPICE_BIND]
1309 596b2459 Guido Trotter
    spice_ip_version = None
1310 31f6f67a Guido Trotter
1311 a900a30c Guido Trotter
    kvm_cmd.extend(["-usb"])
1312 a900a30c Guido Trotter
1313 11344a50 Guido Trotter
    if mouse_type:
1314 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-usbdevice", mouse_type])
1315 31f6f67a Guido Trotter
    elif vnc_bind_address:
1316 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-usbdevice", constants.HT_MOUSE_TABLET])
1317 11344a50 Guido Trotter
1318 8470c8db Guido Trotter
    if vnc_bind_address:
1319 d6e5767e Klaus Aehlig
      if netutils.IsValidInterface(vnc_bind_address):
1320 d6e5767e Klaus Aehlig
        if_addresses = netutils.GetInterfaceIpAddresses(vnc_bind_address)
1321 d6e5767e Klaus Aehlig
        if_ip4_addresses = if_addresses[constants.IP4_VERSION]
1322 d6e5767e Klaus Aehlig
        if len(if_ip4_addresses) < 1:
1323 d6e5767e Klaus Aehlig
          logging.error("Could not determine IPv4 address of interface %s",
1324 d6e5767e Klaus Aehlig
                        vnc_bind_address)
1325 d6e5767e Klaus Aehlig
        else:
1326 d6e5767e Klaus Aehlig
          vnc_bind_address = if_ip4_addresses[0]
1327 8b312c1d Manuel Franceschini
      if netutils.IP4Address.IsValid(vnc_bind_address):
1328 377d74c9 Guido Trotter
        if instance.network_port > constants.VNC_BASE_PORT:
1329 377d74c9 Guido Trotter
          display = instance.network_port - constants.VNC_BASE_PORT
1330 14f5f1b6 Manuel Franceschini
          if vnc_bind_address == constants.IP4_ADDRESS_ANY:
1331 d0c8c01d Iustin Pop
            vnc_arg = ":%d" % (display)
1332 8447f52b Guido Trotter
          else:
1333 d0c8c01d Iustin Pop
            vnc_arg = "%s:%d" % (vnc_bind_address, display)
1334 8470c8db Guido Trotter
        else:
1335 afa9bb2e Michael Hanselmann
          logging.error("Network port is not a valid VNC display (%d < %d),"
1336 afa9bb2e Michael Hanselmann
                        " not starting VNC",
1337 afa9bb2e Michael Hanselmann
                        instance.network_port, constants.VNC_BASE_PORT)
1338 d0c8c01d Iustin Pop
          vnc_arg = "none"
1339 8b2d1013 Guido Trotter
1340 8b2d1013 Guido Trotter
        # Only allow tls and other option when not binding to a file, for now.
1341 8b2d1013 Guido Trotter
        # kvm/qemu gets confused otherwise about the filename to use.
1342 d0c8c01d Iustin Pop
        vnc_append = ""
1343 a985b417 Iustin Pop
        if hvp[constants.HV_VNC_TLS]:
1344 d0c8c01d Iustin Pop
          vnc_append = "%s,tls" % vnc_append
1345 a985b417 Iustin Pop
          if hvp[constants.HV_VNC_X509_VERIFY]:
1346 d0c8c01d Iustin Pop
            vnc_append = "%s,x509verify=%s" % (vnc_append,
1347 a985b417 Iustin Pop
                                               hvp[constants.HV_VNC_X509])
1348 a985b417 Iustin Pop
          elif hvp[constants.HV_VNC_X509]:
1349 d0c8c01d Iustin Pop
            vnc_append = "%s,x509=%s" % (vnc_append,
1350 a985b417 Iustin Pop
                                         hvp[constants.HV_VNC_X509])
1351 6e6bb8d5 Guido Trotter
        if hvp[constants.HV_VNC_PASSWORD_FILE]:
1352 d0c8c01d Iustin Pop
          vnc_append = "%s,password" % vnc_append
1353 6e6bb8d5 Guido Trotter
1354 d0c8c01d Iustin Pop
        vnc_arg = "%s%s" % (vnc_arg, vnc_append)
1355 8b2d1013 Guido Trotter
1356 8470c8db Guido Trotter
      else:
1357 d0c8c01d Iustin Pop
        vnc_arg = "unix:%s/%s.vnc" % (vnc_bind_address, instance.name)
1358 8b2d1013 Guido Trotter
1359 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-vnc", vnc_arg])
1360 596b2459 Guido Trotter
    elif spice_bind:
1361 839642c2 Iustin Pop
      # FIXME: this is wrong here; the iface ip address differs
1362 839642c2 Iustin Pop
      # between systems, so it should be done in _ExecuteKVMRuntime
1363 b1cb62bd Andrea Spadaccini
      if netutils.IsValidInterface(spice_bind):
1364 b1cb62bd Andrea Spadaccini
        # The user specified a network interface, we have to figure out the IP
1365 b1cb62bd Andrea Spadaccini
        # address.
1366 b1cb62bd Andrea Spadaccini
        addresses = netutils.GetInterfaceIpAddresses(spice_bind)
1367 b1cb62bd Andrea Spadaccini
        spice_ip_version = hvp[constants.HV_KVM_SPICE_IP_VERSION]
1368 b1cb62bd Andrea Spadaccini
1369 b1cb62bd Andrea Spadaccini
        # if the user specified an IP version and the interface does not
1370 b1cb62bd Andrea Spadaccini
        # have that kind of IP addresses, throw an exception
1371 b1cb62bd Andrea Spadaccini
        if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1372 b1cb62bd Andrea Spadaccini
          if not addresses[spice_ip_version]:
1373 afa9bb2e Michael Hanselmann
            raise errors.HypervisorError("SPICE: Unable to get an IPv%s address"
1374 b1cb62bd Andrea Spadaccini
                                         " for %s" % (spice_ip_version,
1375 b1cb62bd Andrea Spadaccini
                                                      spice_bind))
1376 b1cb62bd Andrea Spadaccini
1377 b1cb62bd Andrea Spadaccini
        # the user did not specify an IP version, we have to figure it out
1378 b1cb62bd Andrea Spadaccini
        elif (addresses[constants.IP4_VERSION] and
1379 b1cb62bd Andrea Spadaccini
              addresses[constants.IP6_VERSION]):
1380 b1cb62bd Andrea Spadaccini
          # we have both ipv4 and ipv6, let's use the cluster default IP
1381 b1cb62bd Andrea Spadaccini
          # version
1382 b1cb62bd Andrea Spadaccini
          cluster_family = ssconf.SimpleStore().GetPrimaryIPFamily()
1383 65107a2f Michael Hanselmann
          spice_ip_version = \
1384 65107a2f Michael Hanselmann
            netutils.IPAddress.GetVersionFromAddressFamily(cluster_family)
1385 b1cb62bd Andrea Spadaccini
        elif addresses[constants.IP4_VERSION]:
1386 b1cb62bd Andrea Spadaccini
          spice_ip_version = constants.IP4_VERSION
1387 b845c8a1 Andrea Spadaccini
        elif addresses[constants.IP6_VERSION]:
1388 b1cb62bd Andrea Spadaccini
          spice_ip_version = constants.IP6_VERSION
1389 b845c8a1 Andrea Spadaccini
        else:
1390 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Unable to get an IP address"
1391 b845c8a1 Andrea Spadaccini
                                       " for %s" % (spice_bind))
1392 b1cb62bd Andrea Spadaccini
1393 b1cb62bd Andrea Spadaccini
        spice_address = addresses[spice_ip_version][0]
1394 b1cb62bd Andrea Spadaccini
1395 b1cb62bd Andrea Spadaccini
      else:
1396 b1cb62bd Andrea Spadaccini
        # spice_bind is known to be a valid IP address, because
1397 b1cb62bd Andrea Spadaccini
        # ValidateParameters checked it.
1398 b1cb62bd Andrea Spadaccini
        spice_address = spice_bind
1399 b1cb62bd Andrea Spadaccini
1400 bfe86c76 Andrea Spadaccini
      spice_arg = "addr=%s" % spice_address
1401 bfe86c76 Andrea Spadaccini
      if hvp[constants.HV_KVM_SPICE_USE_TLS]:
1402 5ae4945a Iustin Pop
        spice_arg = ("%s,tls-port=%s,x509-cacert-file=%s" %
1403 5ae4945a Iustin Pop
                     (spice_arg, instance.network_port,
1404 9d9bded1 Michael Hanselmann
                      pathutils.SPICE_CACERT_FILE))
1405 5ae4945a Iustin Pop
        spice_arg = ("%s,x509-key-file=%s,x509-cert-file=%s" %
1406 9d9bded1 Michael Hanselmann
                     (spice_arg, pathutils.SPICE_CERT_FILE,
1407 9d9bded1 Michael Hanselmann
                      pathutils.SPICE_CERT_FILE))
1408 3e40b587 Andrea Spadaccini
        tls_ciphers = hvp[constants.HV_KVM_SPICE_TLS_CIPHERS]
1409 3e40b587 Andrea Spadaccini
        if tls_ciphers:
1410 3e40b587 Andrea Spadaccini
          spice_arg = "%s,tls-ciphers=%s" % (spice_arg, tls_ciphers)
1411 bfe86c76 Andrea Spadaccini
      else:
1412 bfe86c76 Andrea Spadaccini
        spice_arg = "%s,port=%s" % (spice_arg, instance.network_port)
1413 bfe86c76 Andrea Spadaccini
1414 b451c4c7 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]:
1415 b451c4c7 Andrea Spadaccini
        spice_arg = "%s,disable-ticketing" % spice_arg
1416 b451c4c7 Andrea Spadaccini
1417 11ae7a0a Andrea Spadaccini
      if spice_ip_version:
1418 11ae7a0a Andrea Spadaccini
        spice_arg = "%s,ipv%s" % (spice_arg, spice_ip_version)
1419 b1cb62bd Andrea Spadaccini
1420 ea064d24 Andrea Spadaccini
      # Image compression options
1421 ea064d24 Andrea Spadaccini
      img_lossless = hvp[constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR]
1422 ea064d24 Andrea Spadaccini
      img_jpeg = hvp[constants.HV_KVM_SPICE_JPEG_IMG_COMPR]
1423 ea064d24 Andrea Spadaccini
      img_zlib_glz = hvp[constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR]
1424 ea064d24 Andrea Spadaccini
      if img_lossless:
1425 ea064d24 Andrea Spadaccini
        spice_arg = "%s,image-compression=%s" % (spice_arg, img_lossless)
1426 ea064d24 Andrea Spadaccini
      if img_jpeg:
1427 ea064d24 Andrea Spadaccini
        spice_arg = "%s,jpeg-wan-compression=%s" % (spice_arg, img_jpeg)
1428 ea064d24 Andrea Spadaccini
      if img_zlib_glz:
1429 ea064d24 Andrea Spadaccini
        spice_arg = "%s,zlib-glz-wan-compression=%s" % (spice_arg, img_zlib_glz)
1430 ea064d24 Andrea Spadaccini
1431 ea064d24 Andrea Spadaccini
      # Video stream detection
1432 ea064d24 Andrea Spadaccini
      video_streaming = hvp[constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION]
1433 ea064d24 Andrea Spadaccini
      if video_streaming:
1434 ea064d24 Andrea Spadaccini
        spice_arg = "%s,streaming-video=%s" % (spice_arg, video_streaming)
1435 ea064d24 Andrea Spadaccini
1436 ea064d24 Andrea Spadaccini
      # Audio compression, by default in qemu-kvm it is on
1437 ea064d24 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_AUDIO_COMPR]:
1438 ea064d24 Andrea Spadaccini
        spice_arg = "%s,playback-compression=off" % spice_arg
1439 3e40b587 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_USE_VDAGENT]:
1440 3e40b587 Andrea Spadaccini
        spice_arg = "%s,agent-mouse=off" % spice_arg
1441 447af814 Nikos Skalkotos
      else:
1442 447af814 Nikos Skalkotos
        # Enable the spice agent communication channel between the host and the
1443 447af814 Nikos Skalkotos
        # agent.
1444 447af814 Nikos Skalkotos
        kvm_cmd.extend(["-device", "virtio-serial-pci"])
1445 afa9bb2e Michael Hanselmann
        kvm_cmd.extend([
1446 afa9bb2e Michael Hanselmann
          "-device",
1447 afa9bb2e Michael Hanselmann
          "virtserialport,chardev=spicechannel0,name=com.redhat.spice.0",
1448 afa9bb2e Michael Hanselmann
          ])
1449 447af814 Nikos Skalkotos
        kvm_cmd.extend(["-chardev", "spicevmc,id=spicechannel0,name=vdagent"])
1450 ea064d24 Andrea Spadaccini
1451 b1cb62bd Andrea Spadaccini
      logging.info("KVM: SPICE will listen on port %s", instance.network_port)
1452 b1cb62bd Andrea Spadaccini
      kvm_cmd.extend(["-spice", spice_arg])
1453 b1cb62bd Andrea Spadaccini
1454 596b2459 Guido Trotter
    else:
1455 99c7cd5b Guido Trotter
      # From qemu 1.4 -nographic is incompatible with -daemonize. The new way
1456 99c7cd5b Guido Trotter
      # also works in earlier versions though (tested with 1.1 and 1.3)
1457 99c7cd5b Guido Trotter
      if self._DISPLAY_RE.search(kvmhelp):
1458 99c7cd5b Guido Trotter
        kvm_cmd.extend(["-display", "none"])
1459 99c7cd5b Guido Trotter
      else:
1460 99c7cd5b Guido Trotter
        kvm_cmd.extend(["-nographic"])
1461 596b2459 Guido Trotter
1462 6b970cef Jun Futagawa
    if hvp[constants.HV_USE_LOCALTIME]:
1463 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-localtime"])
1464 6b970cef Jun Futagawa
1465 547a63b7 Balazs Lecz
    if hvp[constants.HV_KVM_USE_CHROOT]:
1466 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-chroot", self._InstanceChrootDir(instance.name)])
1467 547a63b7 Balazs Lecz
1468 7cb42171 Nikita Staroverov
    # Add qemu-KVM -cpu param
1469 7cb42171 Nikita Staroverov
    if hvp[constants.HV_CPU_TYPE]:
1470 7cb42171 Nikita Staroverov
      kvm_cmd.extend(["-cpu", hvp[constants.HV_CPU_TYPE]])
1471 7cb42171 Nikita Staroverov
1472 2fddb144 Guido Trotter
    # As requested by music lovers
1473 2fddb144 Guido Trotter
    if hvp[constants.HV_SOUNDHW]:
1474 2fddb144 Guido Trotter
      kvm_cmd.extend(["-soundhw", hvp[constants.HV_SOUNDHW]])
1475 2fddb144 Guido Trotter
1476 7589346f Guido Trotter
    # Pass a -vga option if requested, or if spice is used, for backwards
1477 7589346f Guido Trotter
    # compatibility.
1478 7589346f Guido Trotter
    if hvp[constants.HV_VGA]:
1479 7589346f Guido Trotter
      kvm_cmd.extend(["-vga", hvp[constants.HV_VGA]])
1480 7589346f Guido Trotter
    elif spice_bind:
1481 7589346f Guido Trotter
      kvm_cmd.extend(["-vga", "qxl"])
1482 7589346f Guido Trotter
1483 156681c1 Guido Trotter
    # Various types of usb devices, comma separated
1484 156681c1 Guido Trotter
    if hvp[constants.HV_USB_DEVICES]:
1485 156681c1 Guido Trotter
      for dev in hvp[constants.HV_USB_DEVICES].split(","):
1486 156681c1 Guido Trotter
        kvm_cmd.extend(["-usbdevice", dev])
1487 156681c1 Guido Trotter
1488 8feeb253 Christos Stavrakakis
    # Set system UUID to instance UUID
1489 8feeb253 Christos Stavrakakis
    if self._UUID_RE.search(kvmhelp):
1490 8feeb253 Christos Stavrakakis
      kvm_cmd.extend(["-uuid", instance.uuid])
1491 8feeb253 Christos Stavrakakis
1492 e6f24d89 Guido Trotter
    if hvp[constants.HV_KVM_EXTRA]:
1493 a967416c Guido Trotter
      kvm_cmd.extend(hvp[constants.HV_KVM_EXTRA].split(" "))
1494 e6f24d89 Guido Trotter
1495 ee5f20b0 Guido Trotter
    # Save the current instance nics, but defer their expansion as parameters,
1496 ee5f20b0 Guido Trotter
    # as we'll need to generate executable temp files for them.
1497 ee5f20b0 Guido Trotter
    kvm_nics = instance.nics
1498 a985b417 Iustin Pop
    hvparams = hvp
1499 ee5f20b0 Guido Trotter
1500 6bf6870b Dimitris Aragiorgis
    return (kvm_cmd, kvm_nics, hvparams, block_devices)
1501 ee5f20b0 Guido Trotter
1502 38e250ba Guido Trotter
  def _WriteKVMRuntime(self, instance_name, data):
1503 38e250ba Guido Trotter
    """Write an instance's KVM runtime
1504 38e250ba Guido Trotter

1505 38e250ba Guido Trotter
    """
1506 38e250ba Guido Trotter
    try:
1507 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1508 38e250ba Guido Trotter
                      data=data)
1509 90c024f6 Guido Trotter
    except EnvironmentError, err:
1510 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1511 38e250ba Guido Trotter
1512 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
1513 38e250ba Guido Trotter
    """Read an instance's KVM runtime
1514 38e250ba Guido Trotter

1515 38e250ba Guido Trotter
    """
1516 38e250ba Guido Trotter
    try:
1517 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1518 90c024f6 Guido Trotter
    except EnvironmentError, err:
1519 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1520 38e250ba Guido Trotter
    return file_content
1521 38e250ba Guido Trotter
1522 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1523 38e250ba Guido Trotter
    """Save an instance's KVM runtime
1524 38e250ba Guido Trotter

1525 38e250ba Guido Trotter
    """
1526 6bf6870b Dimitris Aragiorgis
    kvm_cmd, kvm_nics, hvparams, block_devices = kvm_runtime
1527 6bf6870b Dimitris Aragiorgis
1528 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1529 6bf6870b Dimitris Aragiorgis
    serialized_blockdevs = [(blk.ToDict(), link) for blk, link in block_devices]
1530 6bf6870b Dimitris Aragiorgis
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams,
1531 6bf6870b Dimitris Aragiorgis
                                      serialized_blockdevs))
1532 6bf6870b Dimitris Aragiorgis
1533 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
1534 38e250ba Guido Trotter
1535 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1536 38e250ba Guido Trotter
    """Load an instance's KVM runtime
1537 38e250ba Guido Trotter

1538 38e250ba Guido Trotter
    """
1539 30e42c4e Guido Trotter
    if not serialized_runtime:
1540 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1541 6bf6870b Dimitris Aragiorgis
1542 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
1543 6bf6870b Dimitris Aragiorgis
    if len(loaded_runtime)==3:
1544 6bf6870b Dimitris Aragiorgis
      serialized_blockdevs = []
1545 6bf6870b Dimitris Aragiorgis
      kvm_cmd, serialized_nics, hvparams = loaded_runtime
1546 6bf6870b Dimitris Aragiorgis
    else:
1547 6bf6870b Dimitris Aragiorgis
      kvm_cmd, serialized_nics, hvparams, serialized_blockdevs = loaded_runtime
1548 6bf6870b Dimitris Aragiorgis
1549 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
1550 6bf6870b Dimitris Aragiorgis
    block_devices = [(objects.Disk.FromDict(sdisk), link)
1551 6bf6870b Dimitris Aragiorgis
                     for sdisk, link in serialized_blockdevs]
1552 6bf6870b Dimitris Aragiorgis
1553 6bf6870b Dimitris Aragiorgis
    return (kvm_cmd, kvm_nics, hvparams, block_devices)
1554 38e250ba Guido Trotter
1555 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1556 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
1557 76431533 Guido Trotter

1558 76431533 Guido Trotter
    @type name: string
1559 76431533 Guido Trotter
    @param name: instance name
1560 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1561 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1562 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1563 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1564 76431533 Guido Trotter

1565 76431533 Guido Trotter
    """
1566 5d9bfd87 Apollon Oikonomopoulos
    try:
1567 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1568 5d9bfd87 Apollon Oikonomopoulos
    finally:
1569 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
1570 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
1571 5d9bfd87 Apollon Oikonomopoulos
1572 76431533 Guido Trotter
    if result.failed:
1573 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1574 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
1575 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
1576 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
1577 76431533 Guido Trotter
1578 6bf6870b Dimitris Aragiorgis
  # pylint: disable=R0914
1579 b73f1c59 Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1580 839642c2 Iustin Pop
    """Execute a KVM cmd, after completing it with some last minute data.
1581 ee5f20b0 Guido Trotter

1582 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1583 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1584 b73f1c59 Guido Trotter
    @type kvmhelp: string
1585 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1586 30e42c4e Guido Trotter

1587 ee5f20b0 Guido Trotter
    """
1588 297e6e53 Guido Trotter
    # Small _ExecuteKVMRuntime hv parameters programming howto:
1589 297e6e53 Guido Trotter
    #  - conf_hvp contains the parameters as configured on ganeti. they might
1590 297e6e53 Guido Trotter
    #    have changed since the instance started; only use them if the change
1591 297e6e53 Guido Trotter
    #    won't affect the inside of the instance (which hasn't been rebooted).
1592 297e6e53 Guido Trotter
    #  - up_hvp contains the parameters as they were when the instance was
1593 297e6e53 Guido Trotter
    #    started, plus any new parameter which has been added between ganeti
1594 297e6e53 Guido Trotter
    #    versions: it is paramount that those default to a value which won't
1595 297e6e53 Guido Trotter
    #    affect the inside of the instance as well.
1596 297e6e53 Guido Trotter
    conf_hvp = instance.hvparams
1597 5905901c Iustin Pop
    name = instance.name
1598 5905901c Iustin Pop
    self._CheckDown(name)
1599 ee5f20b0 Guido Trotter
1600 ee5f20b0 Guido Trotter
    temp_files = []
1601 ee5f20b0 Guido Trotter
1602 6bf6870b Dimitris Aragiorgis
    kvm_cmd, kvm_nics, up_hvp, block_devices = kvm_runtime
1603 f0db563d Guido Trotter
    # the first element of kvm_cmd is always the path to the kvm binary
1604 f0db563d Guido Trotter
    kvm_path = kvm_cmd[0]
1605 6bf6870b Dimitris Aragiorgis
1606 6bf6870b Dimitris Aragiorgis
    kvm_cmd_runtime = copy.deepcopy(kvm_cmd)
1607 6bf6870b Dimitris Aragiorgis
1608 297e6e53 Guido Trotter
    up_hvp = objects.FillDict(conf_hvp, up_hvp)
1609 ee5f20b0 Guido Trotter
1610 297e6e53 Guido Trotter
    # We know it's safe to run as a different user upon migration, so we'll use
1611 297e6e53 Guido Trotter
    # the latest conf, from conf_hvp.
1612 297e6e53 Guido Trotter
    security_model = conf_hvp[constants.HV_SECURITY_MODEL]
1613 cef34868 Guido Trotter
    if security_model == constants.HT_SM_USER:
1614 297e6e53 Guido Trotter
      kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
1615 cef34868 Guido Trotter
1616 839642c2 Iustin Pop
    keymap = conf_hvp[constants.HV_KEYMAP]
1617 839642c2 Iustin Pop
    if keymap:
1618 839642c2 Iustin Pop
      keymap_path = self._InstanceKeymapFile(name)
1619 839642c2 Iustin Pop
      # If a keymap file is specified, KVM won't use its internal defaults. By
1620 839642c2 Iustin Pop
      # first including the "en-us" layout, an error on loading the actual
1621 839642c2 Iustin Pop
      # layout (e.g. because it can't be found) won't lead to a non-functional
1622 839642c2 Iustin Pop
      # keyboard. A keyboard with incorrect keys is still better than none.
1623 839642c2 Iustin Pop
      utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
1624 839642c2 Iustin Pop
      kvm_cmd.extend(["-k", keymap_path])
1625 839642c2 Iustin Pop
1626 6bf6870b Dimitris Aragiorgis
    pci_reservations = bitarray(self._DEFAULT_PCI_RESERVATIONS)
1627 6bf6870b Dimitris Aragiorgis
1628 6bf6870b Dimitris Aragiorgis
    kvm_cmd = self._GenerateKVMBlockDevicesOptions(instance, kvm_cmd,
1629 6bf6870b Dimitris Aragiorgis
                                                   block_devices,
1630 6bf6870b Dimitris Aragiorgis
                                                   pci_reservations,
1631 6bf6870b Dimitris Aragiorgis
                                                   kvmhelp)
1632 6bf6870b Dimitris Aragiorgis
1633 297e6e53 Guido Trotter
    # We have reasons to believe changing something like the nic driver/type
1634 297e6e53 Guido Trotter
    # upon migration won't exactly fly with the instance kernel, so for nic
1635 297e6e53 Guido Trotter
    # related parameters we'll use up_hvp
1636 5d9bfd87 Apollon Oikonomopoulos
    tapfds = []
1637 5d9bfd87 Apollon Oikonomopoulos
    taps = []
1638 ee5f20b0 Guido Trotter
    if not kvm_nics:
1639 fbe27e2b Guido Trotter
      kvm_cmd.extend(["-net", "none"])
1640 ee5f20b0 Guido Trotter
    else:
1641 5d9bfd87 Apollon Oikonomopoulos
      vnet_hdr = False
1642 fbe27e2b Guido Trotter
      tap_extra = ""
1643 297e6e53 Guido Trotter
      nic_type = up_hvp[constants.HV_NIC_TYPE]
1644 37f88dc6 Guido Trotter
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
1645 f0db563d Guido Trotter
        nic_model = self._VIRTIO
1646 f0db563d Guido Trotter
        try:
1647 f0db563d Guido Trotter
          devlist = self._GetKVMOutput(kvm_path, self._KVMOPT_DEVICELIST)
1648 f0db563d Guido Trotter
          if self._NEW_VIRTIO_RE.search(devlist):
1649 f0db563d Guido Trotter
            nic_model = self._VIRTIO_NET_PCI
1650 f0db563d Guido Trotter
            vnet_hdr = True
1651 f0db563d Guido Trotter
        except errors.HypervisorError, _:
1652 f0db563d Guido Trotter
          # Older versions of kvm don't support DEVICE_LIST, but they don't
1653 f0db563d Guido Trotter
          # have new virtio syntax either.
1654 f0db563d Guido Trotter
          pass
1655 4b784cf8 Miguel Di Ciurcio Filho
1656 297e6e53 Guido Trotter
        if up_hvp[constants.HV_VHOST_NET]:
1657 3b59ec02 Guido Trotter
          # check for vhost_net support
1658 0ad7f5d8 Guido Trotter
          if self._VHOST_RE.search(kvmhelp):
1659 4b784cf8 Miguel Di Ciurcio Filho
            tap_extra = ",vhost=on"
1660 4b784cf8 Miguel Di Ciurcio Filho
          else:
1661 4b784cf8 Miguel Di Ciurcio Filho
            raise errors.HypervisorError("vhost_net is configured"
1662 5ae4945a Iustin Pop
                                         " but it is not available")
1663 37f88dc6 Guido Trotter
      else:
1664 4b784cf8 Miguel Di Ciurcio Filho
        nic_model = nic_type
1665 37f88dc6 Guido Trotter
1666 6f4070cd Guido Trotter
      kvm_supports_netdev = self._NETDEV_RE.search(kvmhelp)
1667 6f4070cd Guido Trotter
1668 ee5f20b0 Guido Trotter
      for nic_seq, nic in enumerate(kvm_nics):
1669 6f1e1921 Michael Hanselmann
        tapname, tapfd = _OpenTap(vnet_hdr=vnet_hdr)
1670 5d9bfd87 Apollon Oikonomopoulos
        tapfds.append(tapfd)
1671 5d9bfd87 Apollon Oikonomopoulos
        taps.append(tapname)
1672 6f4070cd Guido Trotter
        if kvm_supports_netdev:
1673 6bf6870b Dimitris Aragiorgis
          nic_val = "%s,mac=%s" % (nic_model, nic.mac)
1674 6bf6870b Dimitris Aragiorgis
          _UpdatePCISlots(nic, pci_reservations)
1675 6bf6870b Dimitris Aragiorgis
          kvm_devid = _GenerateDeviceKVMId("NIC", nic)
1676 6bf6870b Dimitris Aragiorgis
          netdev = kvm_devid or "netdev%d" % nic_seq
1677 6bf6870b Dimitris Aragiorgis
          nic_val += (",netdev=%s" % netdev)
1678 6bf6870b Dimitris Aragiorgis
          if kvm_devid:
1679 6bf6870b Dimitris Aragiorgis
            nic_val += (",id=%s,bus=pci.0,addr=%s" % (kvm_devid, hex(nic.pci)))
1680 6bf6870b Dimitris Aragiorgis
          tap_val = ("type=tap,id=%s,fd=%d%s" %
1681 6bf6870b Dimitris Aragiorgis
                     (netdev, tapfd, tap_extra))
1682 4b784cf8 Miguel Di Ciurcio Filho
          kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
1683 4b784cf8 Miguel Di Ciurcio Filho
        else:
1684 049383d9 Adeodato Simo
          nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq,
1685 049383d9 Adeodato Simo
                                                         nic.mac, nic_model)
1686 5d9bfd87 Apollon Oikonomopoulos
          tap_val = "tap,vlan=%s,fd=%d" % (nic_seq, tapfd)
1687 4b784cf8 Miguel Di Ciurcio Filho
          kvm_cmd.extend(["-net", tap_val, "-net", nic_val])
1688 ee5f20b0 Guido Trotter
1689 30e42c4e Guido Trotter
    if incoming:
1690 30e42c4e Guido Trotter
      target, port = incoming
1691 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])
1692 30e42c4e Guido Trotter
1693 297e6e53 Guido Trotter
    # Changing the vnc password doesn't bother the guest that much. At most it
1694 297e6e53 Guido Trotter
    # will surprise people who connect to it. Whether positively or negatively
1695 297e6e53 Guido Trotter
    # it's debatable.
1696 297e6e53 Guido Trotter
    vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
1697 6e6bb8d5 Guido Trotter
    vnc_pwd = None
1698 6e6bb8d5 Guido Trotter
    if vnc_pwd_file:
1699 6e6bb8d5 Guido Trotter
      try:
1700 682f7601 Guido Trotter
        vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
1701 6e6bb8d5 Guido Trotter
      except EnvironmentError, err:
1702 6e6bb8d5 Guido Trotter
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
1703 6e6bb8d5 Guido Trotter
                                     % (vnc_pwd_file, err))
1704 6e6bb8d5 Guido Trotter
1705 297e6e53 Guido Trotter
    if conf_hvp[constants.HV_KVM_USE_CHROOT]:
1706 547a63b7 Balazs Lecz
      utils.EnsureDirs([(self._InstanceChrootDir(name),
1707 547a63b7 Balazs Lecz
                         constants.SECURE_DIR_MODE)])
1708 547a63b7 Balazs Lecz
1709 91c10532 Andrea Spadaccini
    # Automatically enable QMP if version is >= 0.14
1710 0ad7f5d8 Guido Trotter
    if self._QMP_RE.search(kvmhelp):
1711 91c10532 Andrea Spadaccini
      logging.debug("Enabling QMP")
1712 91c10532 Andrea Spadaccini
      kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
1713 5ae4945a Iustin Pop
                      self._InstanceQmpMonitor(instance.name)])
1714 91c10532 Andrea Spadaccini
1715 cc8a8ed7 Apollon Oikonomopoulos
    # Configure the network now for starting instances and bridged interfaces,
1716 cc8a8ed7 Apollon Oikonomopoulos
    # during FinalizeMigration for incoming instances' routed interfaces
1717 cc8a8ed7 Apollon Oikonomopoulos
    for nic_seq, nic in enumerate(kvm_nics):
1718 cc8a8ed7 Apollon Oikonomopoulos
      if (incoming and
1719 cc8a8ed7 Apollon Oikonomopoulos
          nic.nicparams[constants.NIC_MODE] != constants.NIC_MODE_BRIDGED):
1720 cc8a8ed7 Apollon Oikonomopoulos
        continue
1721 cc8a8ed7 Apollon Oikonomopoulos
      self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
1722 5d9bfd87 Apollon Oikonomopoulos
1723 1d8a7812 Andrea Spadaccini
    # CPU affinity requires kvm to start paused, so we set this flag if the
1724 1d8a7812 Andrea Spadaccini
    # instance is not already paused and if we are not going to accept a
1725 1d8a7812 Andrea Spadaccini
    # migrating instance. In the latter case, pausing is not needed.
1726 1d8a7812 Andrea Spadaccini
    start_kvm_paused = not (_KVM_START_PAUSED_FLAG in kvm_cmd) and not incoming
1727 945a7e67 Guido Trotter
    if start_kvm_paused:
1728 945a7e67 Guido Trotter
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1729 b693125f Tsachy Shacham
1730 b693125f Tsachy Shacham
    # Note: CPU pinning is using up_hvp since changes take effect
1731 b693125f Tsachy Shacham
    # during instance startup anyway, and to avoid problems when soft
1732 b693125f Tsachy Shacham
    # rebooting the instance.
1733 c607b1f7 Tsachy Shacham
    cpu_pinning = False
1734 b693125f Tsachy Shacham
    if up_hvp.get(constants.HV_CPU_MASK, None):
1735 b693125f Tsachy Shacham
      cpu_pinning = True
1736 b693125f Tsachy Shacham
1737 76431533 Guido Trotter
    if security_model == constants.HT_SM_POOL:
1738 76431533 Guido Trotter
      ss = ssconf.SimpleStore()
1739 76431533 Guido Trotter
      uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
1740 76431533 Guido Trotter
      all_uids = set(uidpool.ExpandUidPool(uid_pool))
1741 76431533 Guido Trotter
      uid = uidpool.RequestUnusedUid(all_uids)
1742 76431533 Guido Trotter
      try:
1743 76431533 Guido Trotter
        username = pwd.getpwuid(uid.GetUid()).pw_name
1744 76431533 Guido Trotter
        kvm_cmd.extend(["-runas", username])
1745 5d9bfd87 Apollon Oikonomopoulos
        self._RunKVMCmd(name, kvm_cmd, tapfds)
1746 76431533 Guido Trotter
      except:
1747 76431533 Guido Trotter
        uidpool.ReleaseUid(uid)
1748 76431533 Guido Trotter
        raise
1749 76431533 Guido Trotter
      else:
1750 76431533 Guido Trotter
        uid.Unlock()
1751 3af16328 Apollon Oikonomopoulos
        utils.WriteFile(self._InstanceUidFile(name), data=uid.AsStr())
1752 76431533 Guido Trotter
    else:
1753 5d9bfd87 Apollon Oikonomopoulos
      self._RunKVMCmd(name, kvm_cmd, tapfds)
1754 5d9bfd87 Apollon Oikonomopoulos
1755 5d9bfd87 Apollon Oikonomopoulos
    utils.EnsureDirs([(self._InstanceNICDir(instance.name),
1756 5d9bfd87 Apollon Oikonomopoulos
                     constants.RUN_DIRS_MODE)])
1757 5d9bfd87 Apollon Oikonomopoulos
    for nic_seq, tap in enumerate(taps):
1758 5d9bfd87 Apollon Oikonomopoulos
      utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
1759 5d9bfd87 Apollon Oikonomopoulos
                      data=tap)
1760 eb58f9b1 Guido Trotter
1761 6e6bb8d5 Guido Trotter
    if vnc_pwd:
1762 d0c8c01d Iustin Pop
      change_cmd = "change vnc password %s" % vnc_pwd
1763 6e6bb8d5 Guido Trotter
      self._CallMonitorCommand(instance.name, change_cmd)
1764 6e6bb8d5 Guido Trotter
1765 b451c4c7 Andrea Spadaccini
    # Setting SPICE password. We are not vulnerable to malicious passwordless
1766 b451c4c7 Andrea Spadaccini
    # connection attempts because SPICE by default does not allow connections
1767 b451c4c7 Andrea Spadaccini
    # if neither a password nor the "disable_ticketing" options are specified.
1768 b451c4c7 Andrea Spadaccini
    # As soon as we send the password via QMP, that password is a valid ticket
1769 b451c4c7 Andrea Spadaccini
    # for connection.
1770 b451c4c7 Andrea Spadaccini
    spice_password_file = conf_hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]
1771 b451c4c7 Andrea Spadaccini
    if spice_password_file:
1772 fc84cd5d Guido Trotter
      spice_pwd = ""
1773 b451c4c7 Andrea Spadaccini
      try:
1774 b451c4c7 Andrea Spadaccini
        spice_pwd = utils.ReadOneLineFile(spice_password_file, strict=True)
1775 b451c4c7 Andrea Spadaccini
      except EnvironmentError, err:
1776 b451c4c7 Andrea Spadaccini
        raise errors.HypervisorError("Failed to open SPICE password file %s: %s"
1777 b451c4c7 Andrea Spadaccini
                                     % (spice_password_file, err))
1778 b451c4c7 Andrea Spadaccini
1779 fc84cd5d Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
1780 fc84cd5d Guido Trotter
      qmp.connect()
1781 fc84cd5d Guido Trotter
      arguments = {
1782 fc84cd5d Guido Trotter
          "protocol": "spice",
1783 fc84cd5d Guido Trotter
          "password": spice_pwd,
1784 fc84cd5d Guido Trotter
      }
1785 fc84cd5d Guido Trotter
      qmp.Execute("set_password", arguments)
1786 fc84cd5d Guido Trotter
1787 08137f9e Iustin Pop
    for filename in temp_files:
1788 08137f9e Iustin Pop
      utils.RemoveFile(filename)
1789 eb58f9b1 Guido Trotter
1790 b693125f Tsachy Shacham
    # If requested, set CPU affinity and resume instance execution
1791 b693125f Tsachy Shacham
    if cpu_pinning:
1792 945a7e67 Guido Trotter
      self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK])
1793 945a7e67 Guido Trotter
1794 61eb1a46 Guido Trotter
    start_memory = self._InstanceStartupMemory(instance)
1795 61eb1a46 Guido Trotter
    if start_memory < instance.beparams[constants.BE_MAXMEM]:
1796 61eb1a46 Guido Trotter
      self.BalloonInstanceMemory(instance, start_memory)
1797 61eb1a46 Guido Trotter
1798 945a7e67 Guido Trotter
    if start_kvm_paused:
1799 2ed0e208 Iustin Pop
      # To control CPU pinning, ballooning, and vnc/spice passwords
1800 2ed0e208 Iustin Pop
      # the VM was started in a frozen state. If freezing was not
1801 2ed0e208 Iustin Pop
      # explicitly requested resume the vm status.
1802 945a7e67 Guido Trotter
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1803 b693125f Tsachy Shacham
1804 6bf6870b Dimitris Aragiorgis
    kvm_runtime_with_pci_info = (kvm_cmd_runtime, kvm_nics,
1805 6bf6870b Dimitris Aragiorgis
                                 up_hvp, block_devices)
1806 6bf6870b Dimitris Aragiorgis
    return kvm_runtime_with_pci_info
1807 6bf6870b Dimitris Aragiorgis
1808 323f9095 Stephen Shirley
  def StartInstance(self, instance, block_devices, startup_paused):
1809 ee5f20b0 Guido Trotter
    """Start an instance.
1810 ee5f20b0 Guido Trotter

1811 ee5f20b0 Guido Trotter
    """
1812 5905901c Iustin Pop
    self._CheckDown(instance.name)
1813 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1814 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1815 7238edb5 Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1816 b73f1c59 Guido Trotter
                                           startup_paused, kvmhelp)
1817 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1818 6bf6870b Dimitris Aragiorgis
    kvm_runtime_with_pci_info = self._ExecuteKVMRuntime(instance, kvm_runtime,
1819 6bf6870b Dimitris Aragiorgis
                                                        kvmhelp)
1820 6bf6870b Dimitris Aragiorgis
    self._SaveKVMRuntime(instance, kvm_runtime_with_pci_info)
1821 ee5f20b0 Guido Trotter
1822 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
1823 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
1824 6567aff3 Guido Trotter

1825 6567aff3 Guido Trotter
    """
1826 eace6157 Michael Hanselmann
    # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
1827 eace6157 Michael Hanselmann
    # version. The monitor protocol is designed for human consumption, whereas
1828 eace6157 Michael Hanselmann
    # QMP is made for programmatic usage. In the worst case QMP can also
1829 eace6157 Michael Hanselmann
    # execute monitor commands. As it is, all calls to socat take at least
1830 eace6157 Michael Hanselmann
    # 500ms and likely more: socat can't detect the end of the reply and waits
1831 eace6157 Michael Hanselmann
    # for 500ms of no data received before exiting (500 ms is the default for
1832 eace6157 Michael Hanselmann
    # the "-t" parameter).
1833 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1834 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
1835 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
1836 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1837 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
1838 6567aff3 Guido Trotter
    if result.failed:
1839 afa9bb2e Michael Hanselmann
      msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
1840 afa9bb2e Michael Hanselmann
             " output: %s" %
1841 afa9bb2e Michael Hanselmann
             (command, instance_name, result.fail_reason, result.output))
1842 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
1843 6567aff3 Guido Trotter
1844 6567aff3 Guido Trotter
    return result
1845 6567aff3 Guido Trotter
1846 6bf6870b Dimitris Aragiorgis
  def _AnnotateFreePCISlot(self, instance, dev):
1847 6bf6870b Dimitris Aragiorgis
    """Get the first available pci slot of a runnung instance.
1848 6bf6870b Dimitris Aragiorgis

1849 6bf6870b Dimitris Aragiorgis
    """
1850 6bf6870b Dimitris Aragiorgis
    slots = bitarray(32)
1851 6bf6870b Dimitris Aragiorgis
    slots.setall(False) # pylint: disable=E1101
1852 6bf6870b Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance.name, self._INFO_PCI_CMD)
1853 6bf6870b Dimitris Aragiorgis
    for line in output.stdout.splitlines():
1854 6bf6870b Dimitris Aragiorgis
      match = self._INFO_PCI_RE.search(line)
1855 6bf6870b Dimitris Aragiorgis
      if match:
1856 6bf6870b Dimitris Aragiorgis
        slot = int(match.group(1))
1857 6bf6870b Dimitris Aragiorgis
        slots[slot] = True
1858 6bf6870b Dimitris Aragiorgis
1859 6bf6870b Dimitris Aragiorgis
    [free] = slots.search(FREE, 1) # pylint: disable=E1101
1860 6bf6870b Dimitris Aragiorgis
    if not free:
1861 6bf6870b Dimitris Aragiorgis
      raise errors.HypervisorError("All PCI slots occupied")
1862 6bf6870b Dimitris Aragiorgis
1863 6bf6870b Dimitris Aragiorgis
    dev.pci = int(free)
1864 6bf6870b Dimitris Aragiorgis
1865 6bf6870b Dimitris Aragiorgis
  def _TryHotplug(self, instance, dev_type):
1866 6bf6870b Dimitris Aragiorgis
    """Get QEMU version from the instance's monitor.
1867 6bf6870b Dimitris Aragiorgis

1868 6bf6870b Dimitris Aragiorgis
    Hotplug is supported for running instances and for versions >= 1.0.
1869 6bf6870b Dimitris Aragiorgis
    """
1870 6bf6870b Dimitris Aragiorgis
    if dev_type == constants.HOTPLUG_DISK:
1871 6bf6870b Dimitris Aragiorgis
      hvp = instance.hvparams
1872 6bf6870b Dimitris Aragiorgis
      security_model = hvp[constants.HV_SECURITY_MODEL]
1873 6bf6870b Dimitris Aragiorgis
      use_chroot = hvp[constants.HV_KVM_USE_CHROOT]
1874 6bf6870b Dimitris Aragiorgis
      if use_chroot or security_model != constants.HT_SM_NONE:
1875 6bf6870b Dimitris Aragiorgis
        return False
1876 6bf6870b Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD)
1877 6bf6870b Dimitris Aragiorgis
    #TODO: search for netdev_add, drive_add, device_add.....
1878 6bf6870b Dimitris Aragiorgis
    match = self._INFO_VERSION_RE.search(output.stdout)
1879 6bf6870b Dimitris Aragiorgis
    if not match:
1880 6bf6870b Dimitris Aragiorgis
      return False
1881 6bf6870b Dimitris Aragiorgis
    v_major, v_min, _, _ = match.groups()
1882 6bf6870b Dimitris Aragiorgis
    return (v_major, v_min) >= (1, 0)
1883 6bf6870b Dimitris Aragiorgis
1884 6bf6870b Dimitris Aragiorgis
  def _CallMonitorHotplugCommand(self, name, cmd):
1885 6bf6870b Dimitris Aragiorgis
    output = self._CallMonitorCommand(name, cmd)
1886 6bf6870b Dimitris Aragiorgis
    #TODO: parse output and check if succeeded
1887 6bf6870b Dimitris Aragiorgis
    for line in output.stdout.splitlines():
1888 6bf6870b Dimitris Aragiorgis
      logging.info("%s", line)
1889 6bf6870b Dimitris Aragiorgis
1890 6bf6870b Dimitris Aragiorgis
  def HotplugDevice(self, instance, action, dev_type, device, extra, seq):
1891 6bf6870b Dimitris Aragiorgis
    """ Generic method to hotplug device
1892 6bf6870b Dimitris Aragiorgis

1893 6bf6870b Dimitris Aragiorgis
    Depending on action and dev_type invoke the coresponding method that
1894 6bf6870b Dimitris Aragiorgis
    does the actual hotplug (via KVM monitor commands).
1895 6bf6870b Dimitris Aragiorgis
    Before and after, do all hotplug related steps (e.g. check if hotplug
1896 6bf6870b Dimitris Aragiorgis
    is possible, annotate pci slot to device and generate/get existing
1897 6bf6870b Dimitris Aragiorgis
    KVM device ids, read/write runtime file)
1898 6bf6870b Dimitris Aragiorgis

1899 6bf6870b Dimitris Aragiorgis
    """
1900 6bf6870b Dimitris Aragiorgis
    if self._TryHotplug(instance, dev_type):
1901 6bf6870b Dimitris Aragiorgis
      (kvm_cmd, kvm_nics, hvparams, \
1902 6bf6870b Dimitris Aragiorgis
        block_devices) = self._LoadKVMRuntime(instance)
1903 6bf6870b Dimitris Aragiorgis
      if action == constants.HOTPLUG_ADD:
1904 6bf6870b Dimitris Aragiorgis
        self._AnnotateFreePCISlot(instance, device)
1905 6bf6870b Dimitris Aragiorgis
        kvm_devid = _GenerateDeviceKVMId(dev_type, device)
1906 6bf6870b Dimitris Aragiorgis
        if dev_type == constants.HOTPLUG_DISK:
1907 6bf6870b Dimitris Aragiorgis
          self._HotAddDisk(instance,
1908 6bf6870b Dimitris Aragiorgis
                           device, extra, seq, kvm_devid, block_devices)
1909 6bf6870b Dimitris Aragiorgis
        elif dev_type == constants.HOTPLUG_NIC and fdsend:
1910 6bf6870b Dimitris Aragiorgis
          self._HotAddNic(instance, device, extra, seq, kvm_devid, kvm_nics)
1911 6bf6870b Dimitris Aragiorgis
      elif action == constants.HOTPLUG_REMOVE:
1912 6bf6870b Dimitris Aragiorgis
        kvm_devid = self._GetExistingDeviceKVMId(instance, dev_type, device)
1913 6bf6870b Dimitris Aragiorgis
        if dev_type == constants.HOTPLUG_DISK:
1914 6bf6870b Dimitris Aragiorgis
          self._HotDelDisk(instance,
1915 6bf6870b Dimitris Aragiorgis
                           device, extra, seq, kvm_devid, block_devices)
1916 6bf6870b Dimitris Aragiorgis
        elif dev_type == constants.HOTPLUG_NIC and fdsend:
1917 6bf6870b Dimitris Aragiorgis
          self._HotDelNic(instance, device, extra, seq, kvm_devid, kvm_nics)
1918 6bf6870b Dimitris Aragiorgis
      self._SaveKVMRuntime(instance,
1919 6bf6870b Dimitris Aragiorgis
                          (kvm_cmd, kvm_nics, hvparams, block_devices))
1920 6bf6870b Dimitris Aragiorgis
      time.sleep(2)
1921 6bf6870b Dimitris Aragiorgis
1922 6bf6870b Dimitris Aragiorgis
  def _HotAddDisk(self, instance, disk, dev_path, _, kvm_devid, block_devices):
1923 6bf6870b Dimitris Aragiorgis
    """Hotplug/add new disk to and instance
1924 6bf6870b Dimitris Aragiorgis

1925 6bf6870b Dimitris Aragiorgis
    """
1926 6bf6870b Dimitris Aragiorgis
    command = ("drive_add dummy file=%s,if=none,id=%s,format=raw" %
1927 6bf6870b Dimitris Aragiorgis
               (dev_path, kvm_devid))
1928 6bf6870b Dimitris Aragiorgis
    self._CallMonitorHotplugCommand(instance.name, command)
1929 6bf6870b Dimitris Aragiorgis
    command = ("device_add virtio-blk-pci,bus=pci.0,addr=%s,"
1930 6bf6870b Dimitris Aragiorgis
               "drive=%s,id=%s"
1931 6bf6870b Dimitris Aragiorgis
               % (hex(disk.pci), kvm_devid, kvm_devid))
1932 6bf6870b Dimitris Aragiorgis
    self._CallMonitorHotplugCommand(instance.name, command)
1933 6bf6870b Dimitris Aragiorgis
    block_devices.append((disk, dev_path))
1934 6bf6870b Dimitris Aragiorgis
1935 6bf6870b Dimitris Aragiorgis
  def _HotAddNic(self, instance, nic, _, seq, kvm_devid, kvm_nics):
1936 6bf6870b Dimitris Aragiorgis
    """Hotplug/add nic to an instance
1937 6bf6870b Dimitris Aragiorgis

1938 6bf6870b Dimitris Aragiorgis
    """
1939 6bf6870b Dimitris Aragiorgis
    (tap, fd) = _OpenTap()
1940 6bf6870b Dimitris Aragiorgis
    self._PassTapFd(instance, fd, nic)
1941 6bf6870b Dimitris Aragiorgis
    command = ("netdev_add tap,id=%s,fd=%s" % (kvm_devid, kvm_devid))
1942 6bf6870b Dimitris Aragiorgis
    self._CallMonitorHotplugCommand(instance.name, command)
1943 6bf6870b Dimitris Aragiorgis
    command = ("device_add virtio-net-pci,bus=pci.0,addr=%s,mac=%s,"
1944 6bf6870b Dimitris Aragiorgis
               "netdev=%s,id=%s"
1945 6bf6870b Dimitris Aragiorgis
               % (hex(nic.pci), nic.mac, kvm_devid, kvm_devid))
1946 6bf6870b Dimitris Aragiorgis
    self._CallMonitorHotplugCommand(instance.name, command)
1947 6bf6870b Dimitris Aragiorgis
    self._ConfigureNIC(instance, seq, nic, tap)
1948 6bf6870b Dimitris Aragiorgis
    utils.WriteFile(self._InstanceNICFile(instance.name, seq), data=tap)
1949 6bf6870b Dimitris Aragiorgis
    kvm_nics.append(nic)
1950 6bf6870b Dimitris Aragiorgis
1951 6bf6870b Dimitris Aragiorgis
  def _HotDelDisk(self, instance, disk, _, __, kvm_devid, block_devices):
1952 6bf6870b Dimitris Aragiorgis
    """Hotplug/remove disk from an instance
1953 6bf6870b Dimitris Aragiorgis

1954 6bf6870b Dimitris Aragiorgis
    """
1955 6bf6870b Dimitris Aragiorgis
    command = "device_del %s" % kvm_devid
1956 6bf6870b Dimitris Aragiorgis
    self._CallMonitorHotplugCommand(instance.name, command)
1957 6bf6870b Dimitris Aragiorgis
    #command = "drive_del %s" % uuid
1958 6bf6870b Dimitris Aragiorgis
    #self._CallMonitorHotplugCommand(instance.name, command)
1959 6bf6870b Dimitris Aragiorgis
    _RemoveFromRuntimeEntry(block_devices, disk, lambda x: [d for d, l in x])
1960 6bf6870b Dimitris Aragiorgis
1961 6bf6870b Dimitris Aragiorgis
  def _HotDelNic(self, instance, nic, _, __, kvm_devid, kvm_nics):
1962 6bf6870b Dimitris Aragiorgis
    """Hotplug/remove existing nic from an instance
1963 6bf6870b Dimitris Aragiorgis

1964 6bf6870b Dimitris Aragiorgis
    """
1965 6bf6870b Dimitris Aragiorgis
    command = "device_del %s" % kvm_devid
1966 6bf6870b Dimitris Aragiorgis
    self._CallMonitorHotplugCommand(instance.name, command)
1967 6bf6870b Dimitris Aragiorgis
    command = "netdev_del %s" % kvm_devid
1968 6bf6870b Dimitris Aragiorgis
    self._CallMonitorHotplugCommand(instance.name, command)
1969 6bf6870b Dimitris Aragiorgis
    _RemoveFromRuntimeEntry(kvm_nics, nic, lambda x: x)
1970 6bf6870b Dimitris Aragiorgis
1971 6bf6870b Dimitris Aragiorgis
  def _PassTapFd(self, instance, fd, nic):
1972 6bf6870b Dimitris Aragiorgis
    """Pass file descriptor to kvm process via monitor socket using SCM_RIGHTS
1973 6bf6870b Dimitris Aragiorgis

1974 6bf6870b Dimitris Aragiorgis
    """
1975 6bf6870b Dimitris Aragiorgis
    monsock = utils.ShellQuote(self._InstanceMonitor(instance.name))
1976 6bf6870b Dimitris Aragiorgis
    s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1977 6bf6870b Dimitris Aragiorgis
    s.connect(monsock)
1978 6bf6870b Dimitris Aragiorgis
    kvm_devid = _GenerateDeviceKVMId("NIC", nic)
1979 6bf6870b Dimitris Aragiorgis
    command = "getfd %s\n" % kvm_devid
1980 6bf6870b Dimitris Aragiorgis
    fds = [fd]
1981 6bf6870b Dimitris Aragiorgis
    logging.info("%s", fds)
1982 6bf6870b Dimitris Aragiorgis
    fdsend.sendfds(s, command, fds = fds)
1983 6bf6870b Dimitris Aragiorgis
    s.close()
1984 6bf6870b Dimitris Aragiorgis
1985 b52d85c1 Guido Trotter
  @classmethod
1986 585c8187 Guido Trotter
  def _ParseKVMVersion(cls, text):
1987 585c8187 Guido Trotter
    """Parse the KVM version from the --help output.
1988 585c8187 Guido Trotter

1989 585c8187 Guido Trotter
    @type text: string
1990 585c8187 Guido Trotter
    @param text: output of kvm --help
1991 585c8187 Guido Trotter
    @return: (version, v_maj, v_min, v_rev)
1992 5c3d5dfd Iustin Pop
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1993 585c8187 Guido Trotter

1994 585c8187 Guido Trotter
    """
1995 585c8187 Guido Trotter
    match = cls._VERSION_RE.search(text.splitlines()[0])
1996 585c8187 Guido Trotter
    if not match:
1997 585c8187 Guido Trotter
      raise errors.HypervisorError("Unable to get KVM version")
1998 585c8187 Guido Trotter
1999 585c8187 Guido Trotter
    v_all = match.group(0)
2000 585c8187 Guido Trotter
    v_maj = int(match.group(1))
2001 585c8187 Guido Trotter
    v_min = int(match.group(2))
2002 585c8187 Guido Trotter
    if match.group(4):
2003 585c8187 Guido Trotter
      v_rev = int(match.group(4))
2004 585c8187 Guido Trotter
    else:
2005 585c8187 Guido Trotter
      v_rev = 0
2006 585c8187 Guido Trotter
    return (v_all, v_maj, v_min, v_rev)
2007 585c8187 Guido Trotter
2008 585c8187 Guido Trotter
  @classmethod
2009 6e043e60 Guido Trotter
  def _GetKVMOutput(cls, kvm_path, option):
2010 6e043e60 Guido Trotter
    """Return the output of a kvm invocation
2011 e3b89628 Guido Trotter

2012 bc0fed4b Guido Trotter
    @type kvm_path: string
2013 bc0fed4b Guido Trotter
    @param kvm_path: path to the kvm executable
2014 bc0fed4b Guido Trotter
    @type option: a key of _KVMOPTS_CMDS
2015 bc0fed4b Guido Trotter
    @param option: kvm option to fetch the output from
2016 6e043e60 Guido Trotter
    @return: output a supported kvm invocation
2017 e3b89628 Guido Trotter
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
2018 e3b89628 Guido Trotter

2019 e3b89628 Guido Trotter
    """
2020 6e043e60 Guido Trotter
    assert option in cls._KVMOPTS_CMDS, "Invalid output option"
2021 6e043e60 Guido Trotter
2022 bc0fed4b Guido Trotter
    optlist, can_fail = cls._KVMOPTS_CMDS[option]
2023 bc0fed4b Guido Trotter
2024 bc0fed4b Guido Trotter
    result = utils.RunCmd([kvm_path] + optlist)
2025 bc0fed4b Guido Trotter
    if result.failed and not can_fail:
2026 af89fa76 Helga Velroyen
      raise errors.HypervisorError("Unable to get KVM %s output" %
2027 af89fa76 Helga Velroyen
                                    " ".join(cls._KVMOPTS_CMDS[option]))
2028 e3b89628 Guido Trotter
    return result.output
2029 e3b89628 Guido Trotter
2030 e3b89628 Guido Trotter
  @classmethod
2031 3b59ec02 Guido Trotter
  def _GetKVMVersion(cls, kvm_path):
2032 d7e4a2b1 Andrea Spadaccini
    """Return the installed KVM version.
2033 b52d85c1 Guido Trotter

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

2037 b52d85c1 Guido Trotter
    """
2038 6e043e60 Guido Trotter
    return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
2039 82e3bf85 Dimitris Aragiorgis
2040 82e3bf85 Dimitris Aragiorgis
  @classmethod
2041 82e3bf85 Dimitris Aragiorgis
  def _GetDefaultMachineVersion(cls, kvm_path):
2042 82e3bf85 Dimitris Aragiorgis
    """Return the default hardware revision (e.g. pc-1.1)
2043 82e3bf85 Dimitris Aragiorgis

2044 82e3bf85 Dimitris Aragiorgis
    """
2045 6e043e60 Guido Trotter
    output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2046 82e3bf85 Dimitris Aragiorgis
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
2047 82e3bf85 Dimitris Aragiorgis
    if match:
2048 82e3bf85 Dimitris Aragiorgis
      return match.group(1)
2049 82e3bf85 Dimitris Aragiorgis
    else:
2050 82e3bf85 Dimitris Aragiorgis
      return "pc"
2051 82e3bf85 Dimitris Aragiorgis
2052 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
2053 eb58f9b1 Guido Trotter
    """Stop an instance.
2054 eb58f9b1 Guido Trotter

2055 eb58f9b1 Guido Trotter
    """
2056 bbcf7ad0 Iustin Pop
    if name is not None and not force:
2057 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
2058 bbcf7ad0 Iustin Pop
    if name is None:
2059 bbcf7ad0 Iustin Pop
      name = instance.name
2060 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
2061 bbcf7ad0 Iustin Pop
    else:
2062 bbcf7ad0 Iustin Pop
      acpi = False
2063 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
2064 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
2065 bbcf7ad0 Iustin Pop
      if force or not acpi:
2066 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
2067 eb58f9b1 Guido Trotter
      else:
2068 d0c8c01d Iustin Pop
        self._CallMonitorCommand(name, "system_powerdown")
2069 eb58f9b1 Guido Trotter
2070 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
2071 8904b35c Guido Trotter
    """Cleanup after a stopped instance
2072 8904b35c Guido Trotter

2073 8904b35c Guido Trotter
    """
2074 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
2075 8904b35c Guido Trotter
    if pid > 0 and alive:
2076 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
2077 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
2078 eb58f9b1 Guido Trotter
2079 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
2080 eb58f9b1 Guido Trotter
    """Reboot an instance.
2081 eb58f9b1 Guido Trotter

2082 eb58f9b1 Guido Trotter
    """
2083 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
2084 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
2085 eb58f9b1 Guido Trotter
    # to shutdown and restart.
2086 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
2087 1f8b3a27 Guido Trotter
    if not alive:
2088 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
2089 78411c60 Iustin Pop
                                   " not running" % instance.name)
2090 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
2091 f02881e0 Guido Trotter
    # ...first load it...
2092 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
2093 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
2094 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
2095 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
2096 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
2097 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
2098 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2099 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2100 6bf6870b Dimitris Aragiorgis
    kvm_runtime_with_pci_info = \
2101 6bf6870b Dimitris Aragiorgis
      self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
2102 6bf6870b Dimitris Aragiorgis
    self._SaveKVMRuntime(instance, kvm_runtime_with_pci_info)
2103 eb58f9b1 Guido Trotter
2104 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
2105 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
2106 30e42c4e Guido Trotter

2107 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2108 30e42c4e Guido Trotter
    @param instance: instance to be migrated
2109 30e42c4e Guido Trotter
    @rtype: string
2110 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
2111 30e42c4e Guido Trotter

2112 30e42c4e Guido Trotter
    """
2113 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
2114 30e42c4e Guido Trotter
2115 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
2116 30e42c4e Guido Trotter
    """Prepare to accept an instance.
2117 30e42c4e Guido Trotter

2118 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2119 30e42c4e Guido Trotter
    @param instance: instance to be accepted
2120 30e42c4e Guido Trotter
    @type info: string
2121 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
2122 30e42c4e Guido Trotter
    @type target: string
2123 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
2124 30e42c4e Guido Trotter

2125 30e42c4e Guido Trotter
    """
2126 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2127 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
2128 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
2129 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
2130 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
2131 b73f1c59 Guido Trotter
                            incoming=incoming_address)
2132 30e42c4e Guido Trotter
2133 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
2134 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
2135 30e42c4e Guido Trotter

2136 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
2137 30e42c4e Guido Trotter

2138 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
2139 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
2140 30e42c4e Guido Trotter

2141 30e42c4e Guido Trotter
    """
2142 30e42c4e Guido Trotter
    if success:
2143 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
2144 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
2145 5d9bfd87 Apollon Oikonomopoulos
2146 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
2147 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
2148 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
2149 cc8a8ed7 Apollon Oikonomopoulos
          continue
2150 5d9bfd87 Apollon Oikonomopoulos
        try:
2151 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
2152 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
2153 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
2154 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
2155 5d9bfd87 Apollon Oikonomopoulos
          continue
2156 5d9bfd87 Apollon Oikonomopoulos
        try:
2157 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
2158 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
2159 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
2160 5d9bfd87 Apollon Oikonomopoulos
2161 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
2162 30e42c4e Guido Trotter
    else:
2163 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
2164 30e42c4e Guido Trotter
2165 bc0a2284 Helga Velroyen
  def MigrateInstance(self, cluster_name, instance, target, live):
2166 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
2167 30e42c4e Guido Trotter

2168 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
2169 30e42c4e Guido Trotter
    currently running.
2170 30e42c4e Guido Trotter

2171 bc0a2284 Helga Velroyen
    @type cluster_name: string
2172 bc0a2284 Helga Velroyen
    @param cluster_name: name of the cluster
2173 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
2174 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
2175 30e42c4e Guido Trotter
    @type target: string
2176 30e42c4e Guido Trotter
    @param target: ip address of the target node
2177 30e42c4e Guido Trotter
    @type live: boolean
2178 30e42c4e Guido Trotter
    @param live: perform a live migration
2179 30e42c4e Guido Trotter

2180 30e42c4e Guido Trotter
    """
2181 58d38b02 Iustin Pop
    instance_name = instance.name
2182 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
2183 6a1434d7 Andrea Spadaccini
    _, _, alive = self._InstancePidAlive(instance_name)
2184 30e42c4e Guido Trotter
    if not alive:
2185 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
2186 30e42c4e Guido Trotter
2187 30e42c4e Guido Trotter
    if not live:
2188 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
2189 30e42c4e Guido Trotter
2190 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
2191 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
2192 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2193 e43d4f9f Apollon Oikonomopoulos
2194 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
2195 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
2196 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2197 e43d4f9f Apollon Oikonomopoulos
2198 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
2199 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
2200 30e42c4e Guido Trotter
2201 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
2202 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
2203 6a1434d7 Andrea Spadaccini

2204 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2205 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
2206 6a1434d7 Andrea Spadaccini
    @type success: bool
2207 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
2208 6a1434d7 Andrea Spadaccini
    @type live: bool
2209 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
2210 6a1434d7 Andrea Spadaccini

2211 6a1434d7 Andrea Spadaccini
    """
2212 6a1434d7 Andrea Spadaccini
    if success:
2213 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
2214 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
2215 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
2216 6a1434d7 Andrea Spadaccini
    elif live:
2217 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
2218 6a1434d7 Andrea Spadaccini
2219 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
2220 6a1434d7 Andrea Spadaccini
    """Get the migration status
2221 6a1434d7 Andrea Spadaccini

2222 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2223 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
2224 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
2225 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
2226 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
2227 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
2228 6a1434d7 Andrea Spadaccini

2229 6a1434d7 Andrea Spadaccini
    """
2230 d0c8c01d Iustin Pop
    info_command = "info migrate"
2231 6a1434d7 Andrea Spadaccini
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
2232 6a1434d7 Andrea Spadaccini
      result = self._CallMonitorCommand(instance.name, info_command)
2233 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
2234 30e42c4e Guido Trotter
      if not match:
2235 c4e388a5 Guido Trotter
        if not result.stdout:
2236 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
2237 c4e388a5 Guido Trotter
        else:
2238 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
2239 c4e388a5 Guido Trotter
                          result.stdout)
2240 30e42c4e Guido Trotter
      else:
2241 30e42c4e Guido Trotter
        status = match.group(1)
2242 6a1434d7 Andrea Spadaccini
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
2243 6a1434d7 Andrea Spadaccini
          migration_status = objects.MigrationStatus(status=status)
2244 61643226 Andrea Spadaccini
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
2245 61643226 Andrea Spadaccini
          if match:
2246 61643226 Andrea Spadaccini
            migration_status.transferred_ram = match.group("transferred")
2247 61643226 Andrea Spadaccini
            migration_status.total_ram = match.group("total")
2248 61643226 Andrea Spadaccini
2249 6a1434d7 Andrea Spadaccini
          return migration_status
2250 30e42c4e Guido Trotter
2251 6a1434d7 Andrea Spadaccini
        logging.warning("KVM: unknown migration status '%s'", status)
2252 6a1434d7 Andrea Spadaccini
2253 6a1434d7 Andrea Spadaccini
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
2254 6a1434d7 Andrea Spadaccini
2255 62457f51 Iustin Pop
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
2256 30e42c4e Guido Trotter
2257 3d836750 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
2258 3d836750 Guido Trotter
    """Balloon an instance memory to a certain value.
2259 3d836750 Guido Trotter

2260 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
2261 3d836750 Guido Trotter
    @param instance: instance to be accepted
2262 3d836750 Guido Trotter
    @type mem: int
2263 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
2264 3d836750 Guido Trotter

2265 3d836750 Guido Trotter
    """
2266 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2267 3d836750 Guido Trotter
2268 fac489a5 Helga Velroyen
  def GetNodeInfo(self, hvparams=None):
2269 eb58f9b1 Guido Trotter
    """Return information about the node.
2270 eb58f9b1 Guido Trotter

2271 fac489a5 Helga Velroyen
    @type hvparams: dict of strings
2272 fac489a5 Helga Velroyen
    @param hvparams: hypervisor parameters, not used in this class
2273 fac489a5 Helga Velroyen

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

2279 eb58f9b1 Guido Trotter
    """
2280 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
2281 4b9638dc Guido Trotter
    # FIXME: this is the global kvm version, but the actual version can be
2282 4b9638dc Guido Trotter
    # customized as an hv parameter. we should use the nodegroup's default kvm
2283 4b9638dc Guido Trotter
    # path parameter here.
2284 3b59ec02 Guido Trotter
    _, v_major, v_min, v_rev = self._GetKVMVersion(constants.KVM_PATH)
2285 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2286 34fbc862 Andrea Spadaccini
    return result
2287 eb58f9b1 Guido Trotter
2288 637ce7f9 Guido Trotter
  @classmethod
2289 1c3231aa Thomas Thrainer
  def GetInstanceConsole(cls, instance, primary_node, hvparams, beparams):
2290 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
2291 eb58f9b1 Guido Trotter

2292 eb58f9b1 Guido Trotter
    """
2293 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2294 9d9bded1 Michael Hanselmann
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2295 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2296 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2297 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
2298 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2299 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2300 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
2301 1c3231aa Thomas Thrainer
                                     host=primary_node.name,
2302 052783ff Michael Hanselmann
                                     user=constants.SSH_CONSOLE_USER,
2303 55cc0a44 Michael Hanselmann
                                     command=cmd)
2304 3be34f57 Guido Trotter
2305 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2306 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2307 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
2308 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2309 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
2310 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
2311 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
2312 55cc0a44 Michael Hanselmann
                                     display=display)
2313 55cc0a44 Michael Hanselmann
2314 4d2cdb5a Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2315 4d2cdb5a Andrea Spadaccini
    if spice_bind:
2316 4d2cdb5a Andrea Spadaccini
      return objects.InstanceConsole(instance=instance.name,
2317 4d2cdb5a Andrea Spadaccini
                                     kind=constants.CONS_SPICE,
2318 4d2cdb5a Andrea Spadaccini
                                     host=spice_bind,
2319 4d2cdb5a Andrea Spadaccini
                                     port=instance.network_port)
2320 4d2cdb5a Andrea Spadaccini
2321 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
2322 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
2323 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
2324 55cc0a44 Michael Hanselmann
                                            instance.name))
2325 eb58f9b1 Guido Trotter
2326 75bf3149 Helga Velroyen
  def Verify(self, hvparams=None):
2327 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
2328 eb58f9b1 Guido Trotter

2329 cd04dfd2 Michael Hanselmann
    Check that the required binaries exist.
2330 cd04dfd2 Michael Hanselmann

2331 75bf3149 Helga Velroyen
    @type hvparams: dict of strings
2332 75bf3149 Helga Velroyen
    @param hvparams: hypervisor parameters to be verified against, not used here
2333 75bf3149 Helga Velroyen

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

2336 eb58f9b1 Guido Trotter
    """
2337 1f4b9d39 Iustin Pop
    msgs = []
2338 1f4b9d39 Iustin Pop
    # FIXME: this is the global kvm binary, but the actual path can be
2339 1f4b9d39 Iustin Pop
    # customized as an hv parameter; we should use the nodegroup's
2340 1f4b9d39 Iustin Pop
    # default kvm path parameter here.
2341 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
2342 1f4b9d39 Iustin Pop
      msgs.append("The KVM binary ('%s') does not exist" % constants.KVM_PATH)
2343 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2344 1f4b9d39 Iustin Pop
      msgs.append("The socat binary ('%s') does not exist" %
2345 1f4b9d39 Iustin Pop
                  constants.SOCAT_PATH)
2346 1f4b9d39 Iustin Pop
2347 1f4b9d39 Iustin Pop
    return self._FormatVerifyResults(msgs)
2348 14aa53cb Guido Trotter
2349 6b5605e8 Iustin Pop
  @classmethod
2350 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2351 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2352 6b5605e8 Iustin Pop

2353 6b5605e8 Iustin Pop
    @type hvparams:  dict
2354 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2355 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2356 6b5605e8 Iustin Pop

2357 6b5605e8 Iustin Pop
    """
2358 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2359 6b5605e8 Iustin Pop
2360 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
2361 df5ab9f0 Guido Trotter
    if kernel_path:
2362 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
2363 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
2364 205ab586 Iustin Pop
                                     " if a kernel is defined")
2365 6b5605e8 Iustin Pop
2366 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
2367 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
2368 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
2369 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
2370 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
2371 66d5dbef Guido Trotter
2372 14fd6c81 Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2373 14fd6c81 Guido Trotter
      serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2374 14fd6c81 Guido Trotter
      valid_speeds = constants.VALID_SERIAL_SPEEDS
2375 14fd6c81 Guido Trotter
      if not serial_speed or serial_speed not in valid_speeds:
2376 14fd6c81 Guido Trotter
        raise errors.HypervisorError("Invalid serial console speed, must be"
2377 14fd6c81 Guido Trotter
                                     " one of: %s" %
2378 14fd6c81 Guido Trotter
                                     utils.CommaJoin(valid_speeds))
2379 14fd6c81 Guido Trotter
2380 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2381 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
2382 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2383 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2384 835528af Iustin Pop
                                   " ISO path")
2385 f5118ade Iustin Pop
2386 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2387 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2388 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
2389 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
2390 d19d94db Guido Trotter
                                     " must be specified")
2391 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
2392 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
2393 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
2394 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
2395 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
2396 d19d94db Guido Trotter
2397 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2398 b451c4c7 Andrea Spadaccini
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2399 b1cb62bd Andrea Spadaccini
    if spice_bind:
2400 b1cb62bd Andrea Spadaccini
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2401 b1cb62bd Andrea Spadaccini
        # if an IP version is specified, the spice_bind parameter must be an
2402 b1cb62bd Andrea Spadaccini
        # IP of that family
2403 b1cb62bd Andrea Spadaccini
        if (netutils.IP4Address.IsValid(spice_bind) and
2404 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP4_VERSION):
2405 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv4 address (%s), but"
2406 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2407 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2408 b1cb62bd Andrea Spadaccini
2409 b1cb62bd Andrea Spadaccini
        if (netutils.IP6Address.IsValid(spice_bind) and
2410 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP6_VERSION):
2411 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv6 address (%s), but"
2412 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2413 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2414 b451c4c7 Andrea Spadaccini
    else:
2415 0e1b03b9 Andrea Spadaccini
      # All the other SPICE parameters depend on spice_bind being set. Raise an
2416 0e1b03b9 Andrea Spadaccini
      # error if any of them is set without it.
2417 07788a0b Michael Hanselmann
      for param in _SPICE_ADDITIONAL_PARAMS:
2418 0e1b03b9 Andrea Spadaccini
        if hvparams[param]:
2419 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: %s requires %s to be set" %
2420 0e1b03b9 Andrea Spadaccini
                                       (param, constants.HV_KVM_SPICE_BIND))
2421 b1cb62bd Andrea Spadaccini
2422 d19d94db Guido Trotter
  @classmethod
2423 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
2424 d19d94db Guido Trotter
    """Check the given parameters for validity.
2425 d19d94db Guido Trotter

2426 d19d94db Guido Trotter
    @type hvparams:  dict
2427 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2428 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2429 d19d94db Guido Trotter

2430 d19d94db Guido Trotter
    """
2431 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2432 d19d94db Guido Trotter
2433 82e3bf85 Dimitris Aragiorgis
    kvm_path = hvparams[constants.HV_KVM_PATH]
2434 82e3bf85 Dimitris Aragiorgis
2435 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2436 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2437 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2438 d19d94db Guido Trotter
      try:
2439 1feb39ec Guido Trotter
        pwd.getpwnam(username)
2440 d19d94db Guido Trotter
      except KeyError:
2441 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
2442 d19d94db Guido Trotter
                                     % username)
2443 d6e5767e Klaus Aehlig
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2444 d6e5767e Klaus Aehlig
    if vnc_bind_address:
2445 d6e5767e Klaus Aehlig
      bound_to_addr = netutils.IP4Address.IsValid(vnc_bind_address)
2446 d6e5767e Klaus Aehlig
      is_interface = netutils.IsValidInterface(vnc_bind_address)
2447 d6e5767e Klaus Aehlig
      is_path = utils.IsNormAbsPath(vnc_bind_address)
2448 d6e5767e Klaus Aehlig
      if not bound_to_addr and not is_interface and not is_path:
2449 d6e5767e Klaus Aehlig
        raise errors.HypervisorError("VNC: The %s parameter must be either"
2450 d6e5767e Klaus Aehlig
                                     " a valid IP address, an interface name,"
2451 d6e5767e Klaus Aehlig
                                     " or an absolute path" %
2452 d6e5767e Klaus Aehlig
                                     constants.HV_KVM_SPICE_BIND)
2453 d19d94db Guido Trotter
2454 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2455 b1cb62bd Andrea Spadaccini
    if spice_bind:
2456 b1cb62bd Andrea Spadaccini
      # only one of VNC and SPICE can be used currently.
2457 b1cb62bd Andrea Spadaccini
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2458 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("Both SPICE and VNC are configured, but"
2459 b1cb62bd Andrea Spadaccini
                                     " only one of them can be used at a"
2460 afa9bb2e Michael Hanselmann
                                     " given time")
2461 b1cb62bd Andrea Spadaccini
2462 3b59ec02 Guido Trotter
      # check that KVM supports SPICE
2463 6e043e60 Guido Trotter
      kvmhelp = cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP)
2464 0ad7f5d8 Guido Trotter
      if not cls._SPICE_RE.search(kvmhelp):
2465 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE is configured, but it is not"
2466 afa9bb2e Michael Hanselmann
                                     " supported according to 'kvm --help'")
2467 b1cb62bd Andrea Spadaccini
2468 b1cb62bd Andrea Spadaccini
      # if spice_bind is not an IP address, it must be a valid interface
2469 afa9bb2e Michael Hanselmann
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind) or
2470 afa9bb2e Michael Hanselmann
                       netutils.IP6Address.IsValid(spice_bind))
2471 b1cb62bd Andrea Spadaccini
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2472 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE: The %s parameter must be either"
2473 b1cb62bd Andrea Spadaccini
                                     " a valid IP address or interface name" %
2474 b1cb62bd Andrea Spadaccini
                                     constants.HV_KVM_SPICE_BIND)
2475 b1cb62bd Andrea Spadaccini
2476 82e3bf85 Dimitris Aragiorgis
    machine_version = hvparams[constants.HV_KVM_MACHINE_VERSION]
2477 82e3bf85 Dimitris Aragiorgis
    if machine_version:
2478 6e043e60 Guido Trotter
      output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2479 82e3bf85 Dimitris Aragiorgis
      if not cls._CHECK_MACHINE_VERSION_RE(machine_version).search(output):
2480 82e3bf85 Dimitris Aragiorgis
        raise errors.HypervisorError("Unsupported machine version: %s" %
2481 82e3bf85 Dimitris Aragiorgis
                                     machine_version)
2482 82e3bf85 Dimitris Aragiorgis
2483 f5118ade Iustin Pop
  @classmethod
2484 8ef418bb Helga Velroyen
  def PowercycleNode(cls, hvparams=None):
2485 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
2486 f5118ade Iustin Pop

2487 8ef418bb Helga Velroyen
    @type hvparams: dict of strings
2488 8ef418bb Helga Velroyen
    @param hvparams: hypervisor params to be used on this node
2489 8ef418bb Helga Velroyen

2490 f5118ade Iustin Pop
    """
2491 f5118ade Iustin Pop
    cls.LinuxPowercycle()