Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ ddc64582

History | View | Annotate | Download (81.6 kB)

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

24 eb58f9b1 Guido Trotter
"""
25 eb58f9b1 Guido Trotter
26 547a63b7 Balazs Lecz
import errno
27 eb58f9b1 Guido Trotter
import os
28 eb58f9b1 Guido Trotter
import os.path
29 eb58f9b1 Guido Trotter
import re
30 eb58f9b1 Guido Trotter
import tempfile
31 6567aff3 Guido Trotter
import time
32 30e42c4e Guido Trotter
import logging
33 d19d94db Guido Trotter
import pwd
34 199b2053 Apollon Oikonomopoulos
import struct
35 199b2053 Apollon Oikonomopoulos
import fcntl
36 5d9bfd87 Apollon Oikonomopoulos
import shutil
37 91c10532 Andrea Spadaccini
import socket
38 fc84cd5d Guido Trotter
import stat
39 91c10532 Andrea Spadaccini
import StringIO
40 b693125f Tsachy Shacham
try:
41 471a31b6 Andrea Spadaccini
  import affinity   # pylint: disable=F0401
42 b693125f Tsachy Shacham
except ImportError:
43 b693125f Tsachy Shacham
  affinity = None
44 eb58f9b1 Guido Trotter
45 eb58f9b1 Guido Trotter
from ganeti import utils
46 eb58f9b1 Guido Trotter
from ganeti import constants
47 eb58f9b1 Guido Trotter
from ganeti import errors
48 38e250ba Guido Trotter
from ganeti import serializer
49 38e250ba Guido Trotter
from ganeti import objects
50 76431533 Guido Trotter
from ganeti import uidpool
51 76431533 Guido Trotter
from ganeti import ssconf
52 a744b676 Manuel Franceschini
from ganeti import netutils
53 9d9bded1 Michael Hanselmann
from ganeti import pathutils
54 9d9bded1 Michael Hanselmann
from ganeti.hypervisor import hv_base
55 5d9bfd87 Apollon Oikonomopoulos
from ganeti.utils import wrapper as utils_wrapper
56 eb58f9b1 Guido Trotter
57 eb58f9b1 Guido Trotter
58 0e1e0b6a Michael Hanselmann
_KVM_NETWORK_SCRIPT = pathutils.CONF_DIR + "/kvm-vif-bridge"
59 b693125f Tsachy Shacham
_KVM_START_PAUSED_FLAG = "-S"
60 748e4b5a Michael Hanselmann
61 199b2053 Apollon Oikonomopoulos
# TUN/TAP driver constants, taken from <linux/if_tun.h>
62 199b2053 Apollon Oikonomopoulos
# They are architecture-independent and already hardcoded in qemu-kvm source,
63 199b2053 Apollon Oikonomopoulos
# so we can safely include them here.
64 199b2053 Apollon Oikonomopoulos
TUNSETIFF = 0x400454ca
65 199b2053 Apollon Oikonomopoulos
TUNGETIFF = 0x800454d2
66 199b2053 Apollon Oikonomopoulos
TUNGETFEATURES = 0x800454cf
67 199b2053 Apollon Oikonomopoulos
IFF_TAP = 0x0002
68 199b2053 Apollon Oikonomopoulos
IFF_NO_PI = 0x1000
69 199b2053 Apollon Oikonomopoulos
IFF_VNET_HDR = 0x4000
70 199b2053 Apollon Oikonomopoulos
71 07788a0b Michael Hanselmann
#: SPICE parameters which depend on L{constants.HV_KVM_SPICE_BIND}
72 07788a0b Michael Hanselmann
_SPICE_ADDITIONAL_PARAMS = frozenset([
73 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_IP_VERSION,
74 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_PASSWORD_FILE,
75 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR,
76 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_JPEG_IMG_COMPR,
77 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR,
78 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION,
79 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_USE_TLS,
80 07788a0b Michael Hanselmann
  ])
81 07788a0b Michael Hanselmann
82 199b2053 Apollon Oikonomopoulos
83 ea2bcb82 Michael Hanselmann
def _GetTunFeatures(fd, _ioctl=fcntl.ioctl):
84 ea2bcb82 Michael Hanselmann
  """Retrieves supported TUN features from file descriptor.
85 ea2bcb82 Michael Hanselmann

86 ea2bcb82 Michael Hanselmann
  @see: L{_ProbeTapVnetHdr}
87 ea2bcb82 Michael Hanselmann

88 ea2bcb82 Michael Hanselmann
  """
89 ea2bcb82 Michael Hanselmann
  req = struct.pack("I", 0)
90 ea2bcb82 Michael Hanselmann
  try:
91 ea2bcb82 Michael Hanselmann
    buf = _ioctl(fd, TUNGETFEATURES, req)
92 ea2bcb82 Michael Hanselmann
  except EnvironmentError, err:
93 cfc24646 Iustin Pop
    logging.warning("ioctl(TUNGETFEATURES) failed: %s", err)
94 ea2bcb82 Michael Hanselmann
    return None
95 ea2bcb82 Michael Hanselmann
  else:
96 ea2bcb82 Michael Hanselmann
    (flags, ) = struct.unpack("I", buf)
97 ea2bcb82 Michael Hanselmann
    return flags
98 ea2bcb82 Michael Hanselmann
99 ea2bcb82 Michael Hanselmann
100 ea2bcb82 Michael Hanselmann
def _ProbeTapVnetHdr(fd, _features_fn=_GetTunFeatures):
101 199b2053 Apollon Oikonomopoulos
  """Check whether to enable the IFF_VNET_HDR flag.
102 199b2053 Apollon Oikonomopoulos

103 199b2053 Apollon Oikonomopoulos
  To do this, _all_ of the following conditions must be met:
104 199b2053 Apollon Oikonomopoulos
   1. TUNGETFEATURES ioctl() *must* be implemented
105 199b2053 Apollon Oikonomopoulos
   2. TUNGETFEATURES ioctl() result *must* contain the IFF_VNET_HDR flag
106 199b2053 Apollon Oikonomopoulos
   3. TUNGETIFF ioctl() *must* be implemented; reading the kernel code in
107 199b2053 Apollon Oikonomopoulos
      drivers/net/tun.c there is no way to test this until after the tap device
108 199b2053 Apollon Oikonomopoulos
      has been created using TUNSETIFF, and there is no way to change the
109 199b2053 Apollon Oikonomopoulos
      IFF_VNET_HDR flag after creating the interface, catch-22! However both
110 199b2053 Apollon Oikonomopoulos
      TUNGETIFF and TUNGETFEATURES were introduced in kernel version 2.6.27,
111 199b2053 Apollon Oikonomopoulos
      thus we can expect TUNGETIFF to be present if TUNGETFEATURES is.
112 199b2053 Apollon Oikonomopoulos

113 199b2053 Apollon Oikonomopoulos
   @type fd: int
114 199b2053 Apollon Oikonomopoulos
   @param fd: the file descriptor of /dev/net/tun
115 199b2053 Apollon Oikonomopoulos

116 199b2053 Apollon Oikonomopoulos
  """
117 ea2bcb82 Michael Hanselmann
  flags = _features_fn(fd)
118 199b2053 Apollon Oikonomopoulos
119 ea2bcb82 Michael Hanselmann
  if flags is None:
120 ea2bcb82 Michael Hanselmann
    # Not supported
121 199b2053 Apollon Oikonomopoulos
    return False
122 199b2053 Apollon Oikonomopoulos
123 ea2bcb82 Michael Hanselmann
  result = bool(flags & IFF_VNET_HDR)
124 ea2bcb82 Michael Hanselmann
125 ea2bcb82 Michael Hanselmann
  if not result:
126 ea2bcb82 Michael Hanselmann
    logging.warning("Kernel does not support IFF_VNET_HDR, not enabling")
127 ea2bcb82 Michael Hanselmann
128 ea2bcb82 Michael Hanselmann
  return result
129 ea2bcb82 Michael Hanselmann
130 199b2053 Apollon Oikonomopoulos
131 199b2053 Apollon Oikonomopoulos
def _OpenTap(vnet_hdr=True):
132 199b2053 Apollon Oikonomopoulos
  """Open a new tap device and return its file descriptor.
133 199b2053 Apollon Oikonomopoulos

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

137 199b2053 Apollon Oikonomopoulos
  @type vnet_hdr: boolean
138 199b2053 Apollon Oikonomopoulos
  @param vnet_hdr: Enable the VNET Header
139 199b2053 Apollon Oikonomopoulos
  @return: (ifname, tapfd)
140 199b2053 Apollon Oikonomopoulos
  @rtype: tuple
141 199b2053 Apollon Oikonomopoulos

142 199b2053 Apollon Oikonomopoulos
  """
143 199b2053 Apollon Oikonomopoulos
  try:
144 199b2053 Apollon Oikonomopoulos
    tapfd = os.open("/dev/net/tun", os.O_RDWR)
145 199b2053 Apollon Oikonomopoulos
  except EnvironmentError:
146 199b2053 Apollon Oikonomopoulos
    raise errors.HypervisorError("Failed to open /dev/net/tun")
147 199b2053 Apollon Oikonomopoulos
148 199b2053 Apollon Oikonomopoulos
  flags = IFF_TAP | IFF_NO_PI
149 199b2053 Apollon Oikonomopoulos
150 199b2053 Apollon Oikonomopoulos
  if vnet_hdr and _ProbeTapVnetHdr(tapfd):
151 199b2053 Apollon Oikonomopoulos
    flags |= IFF_VNET_HDR
152 199b2053 Apollon Oikonomopoulos
153 199b2053 Apollon Oikonomopoulos
  # The struct ifreq ioctl request (see netdevice(7))
154 199b2053 Apollon Oikonomopoulos
  ifr = struct.pack("16sh", "", flags)
155 199b2053 Apollon Oikonomopoulos
156 199b2053 Apollon Oikonomopoulos
  try:
157 199b2053 Apollon Oikonomopoulos
    res = fcntl.ioctl(tapfd, TUNSETIFF, ifr)
158 6f1e1921 Michael Hanselmann
  except EnvironmentError, err:
159 6f1e1921 Michael Hanselmann
    raise errors.HypervisorError("Failed to allocate a new TAP device: %s" %
160 6f1e1921 Michael Hanselmann
                                 err)
161 199b2053 Apollon Oikonomopoulos
162 199b2053 Apollon Oikonomopoulos
  # Get the interface name from the ioctl
163 199b2053 Apollon Oikonomopoulos
  ifname = struct.unpack("16sh", res)[0].strip("\x00")
164 199b2053 Apollon Oikonomopoulos
  return (ifname, tapfd)
165 199b2053 Apollon Oikonomopoulos
166 748e4b5a Michael Hanselmann
167 91c10532 Andrea Spadaccini
class QmpMessage:
168 91c10532 Andrea Spadaccini
  """QEMU Messaging Protocol (QMP) message.
169 91c10532 Andrea Spadaccini

170 91c10532 Andrea Spadaccini
  """
171 91c10532 Andrea Spadaccini
  def __init__(self, data):
172 91c10532 Andrea Spadaccini
    """Creates a new QMP message based on the passed data.
173 91c10532 Andrea Spadaccini

174 91c10532 Andrea Spadaccini
    """
175 91c10532 Andrea Spadaccini
    if not isinstance(data, dict):
176 91c10532 Andrea Spadaccini
      raise TypeError("QmpMessage must be initialized with a dict")
177 91c10532 Andrea Spadaccini
178 91c10532 Andrea Spadaccini
    self.data = data
179 91c10532 Andrea Spadaccini
180 91c10532 Andrea Spadaccini
  def __getitem__(self, field_name):
181 91c10532 Andrea Spadaccini
    """Get the value of the required field if present, or None.
182 91c10532 Andrea Spadaccini

183 91c10532 Andrea Spadaccini
    Overrides the [] operator to provide access to the message data,
184 91c10532 Andrea Spadaccini
    returning None if the required item is not in the message
185 91c10532 Andrea Spadaccini
    @return: the value of the field_name field, or None if field_name
186 91c10532 Andrea Spadaccini
             is not contained in the message
187 91c10532 Andrea Spadaccini

188 91c10532 Andrea Spadaccini
    """
189 9b87c2cf Michael Hanselmann
    return self.data.get(field_name, None)
190 91c10532 Andrea Spadaccini
191 91c10532 Andrea Spadaccini
  def __setitem__(self, field_name, field_value):
192 91c10532 Andrea Spadaccini
    """Set the value of the required field_name to field_value.
193 91c10532 Andrea Spadaccini

194 91c10532 Andrea Spadaccini
    """
195 91c10532 Andrea Spadaccini
    self.data[field_name] = field_value
196 91c10532 Andrea Spadaccini
197 5e34123e Michele Tartara
  def __len__(self):
198 5e34123e Michele Tartara
    """Return the number of fields stored in this QmpMessage.
199 5e34123e Michele Tartara

200 5e34123e Michele Tartara
    """
201 5e34123e Michele Tartara
    return len(self.data)
202 5e34123e Michele Tartara
203 5e34123e Michele Tartara
  def __delitem__(self, key):
204 5e34123e Michele Tartara
    """Delete the specified element from the QmpMessage.
205 5e34123e Michele Tartara

206 5e34123e Michele Tartara
    """
207 5e34123e Michele Tartara
    del(self.data[key])
208 5e34123e Michele Tartara
209 91c10532 Andrea Spadaccini
  @staticmethod
210 91c10532 Andrea Spadaccini
  def BuildFromJsonString(json_string):
211 91c10532 Andrea Spadaccini
    """Build a QmpMessage from a JSON encoded string.
212 91c10532 Andrea Spadaccini

213 91c10532 Andrea Spadaccini
    @type json_string: str
214 91c10532 Andrea Spadaccini
    @param json_string: JSON string representing the message
215 91c10532 Andrea Spadaccini
    @rtype: L{QmpMessage}
216 91c10532 Andrea Spadaccini
    @return: a L{QmpMessage} built from json_string
217 91c10532 Andrea Spadaccini

218 91c10532 Andrea Spadaccini
    """
219 91c10532 Andrea Spadaccini
    # Parse the string
220 91c10532 Andrea Spadaccini
    data = serializer.LoadJson(json_string)
221 91c10532 Andrea Spadaccini
    return QmpMessage(data)
222 91c10532 Andrea Spadaccini
223 91c10532 Andrea Spadaccini
  def __str__(self):
224 a182a3ed Michael Hanselmann
    # The protocol expects the JSON object to be sent as a single line.
225 a182a3ed Michael Hanselmann
    return serializer.DumpJson(self.data)
226 91c10532 Andrea Spadaccini
227 91c10532 Andrea Spadaccini
  def __eq__(self, other):
228 91c10532 Andrea Spadaccini
    # When comparing two QmpMessages, we are interested in comparing
229 91c10532 Andrea Spadaccini
    # their internal representation of the message data
230 91c10532 Andrea Spadaccini
    return self.data == other.data
231 91c10532 Andrea Spadaccini
232 91c10532 Andrea Spadaccini
233 91c10532 Andrea Spadaccini
class QmpConnection:
234 91c10532 Andrea Spadaccini
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
235 91c10532 Andrea Spadaccini

236 91c10532 Andrea Spadaccini
  """
237 91c10532 Andrea Spadaccini
  _FIRST_MESSAGE_KEY = "QMP"
238 91c10532 Andrea Spadaccini
  _EVENT_KEY = "event"
239 91c10532 Andrea Spadaccini
  _ERROR_KEY = "error"
240 89da2ff3 Guido Trotter
  _RETURN_KEY = RETURN_KEY = "return"
241 89da2ff3 Guido Trotter
  _ACTUAL_KEY = ACTUAL_KEY = "actual"
242 91c10532 Andrea Spadaccini
  _ERROR_CLASS_KEY = "class"
243 91c10532 Andrea Spadaccini
  _ERROR_DESC_KEY = "desc"
244 91c10532 Andrea Spadaccini
  _EXECUTE_KEY = "execute"
245 91c10532 Andrea Spadaccini
  _ARGUMENTS_KEY = "arguments"
246 91c10532 Andrea Spadaccini
  _CAPABILITIES_COMMAND = "qmp_capabilities"
247 91c10532 Andrea Spadaccini
  _MESSAGE_END_TOKEN = "\r\n"
248 91c10532 Andrea Spadaccini
  _SOCKET_TIMEOUT = 5
249 91c10532 Andrea Spadaccini
250 91c10532 Andrea Spadaccini
  def __init__(self, monitor_filename):
251 91c10532 Andrea Spadaccini
    """Instantiates the QmpConnection object.
252 91c10532 Andrea Spadaccini

253 91c10532 Andrea Spadaccini
    @type monitor_filename: string
254 91c10532 Andrea Spadaccini
    @param monitor_filename: the filename of the UNIX raw socket on which the
255 91c10532 Andrea Spadaccini
                             QMP monitor is listening
256 91c10532 Andrea Spadaccini

257 91c10532 Andrea Spadaccini
    """
258 91c10532 Andrea Spadaccini
    self.monitor_filename = monitor_filename
259 91c10532 Andrea Spadaccini
    self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
260 91c10532 Andrea Spadaccini
    # We want to fail if the server doesn't send a complete message
261 91c10532 Andrea Spadaccini
    # in a reasonable amount of time
262 91c10532 Andrea Spadaccini
    self.sock.settimeout(self._SOCKET_TIMEOUT)
263 91c10532 Andrea Spadaccini
    self._connected = False
264 91c10532 Andrea Spadaccini
    self._buf = ""
265 91c10532 Andrea Spadaccini
266 fc84cd5d Guido Trotter
  def _check_socket(self):
267 fc84cd5d Guido Trotter
    sock_stat = None
268 fc84cd5d Guido Trotter
    try:
269 fc84cd5d Guido Trotter
      sock_stat = os.stat(self.monitor_filename)
270 fc84cd5d Guido Trotter
    except EnvironmentError, err:
271 fc84cd5d Guido Trotter
      if err.errno == errno.ENOENT:
272 fc84cd5d Guido Trotter
        raise errors.HypervisorError("No qmp socket found")
273 fc84cd5d Guido Trotter
      else:
274 fc84cd5d Guido Trotter
        raise errors.HypervisorError("Error checking qmp socket: %s",
275 fc84cd5d Guido Trotter
                                     utils.ErrnoOrStr(err))
276 fc84cd5d Guido Trotter
    if not stat.S_ISSOCK(sock_stat.st_mode):
277 fc84cd5d Guido Trotter
      raise errors.HypervisorError("Qmp socket is not a socket")
278 fc84cd5d Guido Trotter
279 91c10532 Andrea Spadaccini
  def _check_connection(self):
280 91c10532 Andrea Spadaccini
    """Make sure that the connection is established.
281 91c10532 Andrea Spadaccini

282 91c10532 Andrea Spadaccini
    """
283 91c10532 Andrea Spadaccini
    if not self._connected:
284 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("To use a QmpConnection you need to first"
285 91c10532 Andrea Spadaccini
                                   " invoke connect() on it")
286 91c10532 Andrea Spadaccini
287 91c10532 Andrea Spadaccini
  def connect(self):
288 91c10532 Andrea Spadaccini
    """Connects to the QMP monitor.
289 91c10532 Andrea Spadaccini

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

293 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
294 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
295 91c10532 Andrea Spadaccini

296 91c10532 Andrea Spadaccini
    """
297 fc84cd5d Guido Trotter
    if self._connected:
298 fc84cd5d Guido Trotter
      raise errors.ProgrammerError("Cannot connect twice")
299 fc84cd5d Guido Trotter
300 fc84cd5d Guido Trotter
    self._check_socket()
301 fc84cd5d Guido Trotter
302 fc84cd5d Guido Trotter
    # Check file existance/stuff
303 fc84cd5d Guido Trotter
    try:
304 fc84cd5d Guido Trotter
      self.sock.connect(self.monitor_filename)
305 fc84cd5d Guido Trotter
    except EnvironmentError:
306 fc84cd5d Guido Trotter
      raise errors.HypervisorError("Can't connect to qmp socket")
307 91c10532 Andrea Spadaccini
    self._connected = True
308 91c10532 Andrea Spadaccini
309 91c10532 Andrea Spadaccini
    # Check if we receive a correct greeting message from the server
310 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 2.2)
311 91c10532 Andrea Spadaccini
    greeting = self._Recv()
312 91c10532 Andrea Spadaccini
    if not greeting[self._FIRST_MESSAGE_KEY]:
313 91c10532 Andrea Spadaccini
      self._connected = False
314 afa9bb2e Michael Hanselmann
      raise errors.HypervisorError("kvm: QMP communication error (wrong"
315 91c10532 Andrea Spadaccini
                                   " server greeting")
316 91c10532 Andrea Spadaccini
317 91c10532 Andrea Spadaccini
    # Let's put the monitor in command mode using the qmp_capabilities
318 91c10532 Andrea Spadaccini
    # command, or else no command will be executable.
319 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 4)
320 91c10532 Andrea Spadaccini
    self.Execute(self._CAPABILITIES_COMMAND)
321 91c10532 Andrea Spadaccini
322 91c10532 Andrea Spadaccini
  def _ParseMessage(self, buf):
323 91c10532 Andrea Spadaccini
    """Extract and parse a QMP message from the given buffer.
324 91c10532 Andrea Spadaccini

325 91c10532 Andrea Spadaccini
    Seeks for a QMP message in the given buf. If found, it parses it and
326 91c10532 Andrea Spadaccini
    returns it together with the rest of the characters in the buf.
327 91c10532 Andrea Spadaccini
    If no message is found, returns None and the whole buffer.
328 91c10532 Andrea Spadaccini

329 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
330 91c10532 Andrea Spadaccini

331 91c10532 Andrea Spadaccini
    """
332 91c10532 Andrea Spadaccini
    message = None
333 91c10532 Andrea Spadaccini
    # Check if we got the message end token (CRLF, as per the QEMU Protocol
334 91c10532 Andrea Spadaccini
    # Specification 0.1 - Section 2.1.1)
335 91c10532 Andrea Spadaccini
    pos = buf.find(self._MESSAGE_END_TOKEN)
336 91c10532 Andrea Spadaccini
    if pos >= 0:
337 91c10532 Andrea Spadaccini
      try:
338 91c10532 Andrea Spadaccini
        message = QmpMessage.BuildFromJsonString(buf[:pos + 1])
339 91c10532 Andrea Spadaccini
      except Exception, err:
340 91c10532 Andrea Spadaccini
        raise errors.ProgrammerError("QMP data serialization error: %s" % err)
341 91c10532 Andrea Spadaccini
      buf = buf[pos + 1:]
342 91c10532 Andrea Spadaccini
343 91c10532 Andrea Spadaccini
    return (message, buf)
344 91c10532 Andrea Spadaccini
345 91c10532 Andrea Spadaccini
  def _Recv(self):
346 91c10532 Andrea Spadaccini
    """Receives a message from QMP and decodes the received JSON object.
347 91c10532 Andrea Spadaccini

348 91c10532 Andrea Spadaccini
    @rtype: QmpMessage
349 91c10532 Andrea Spadaccini
    @return: the received message
350 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
351 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
352 91c10532 Andrea Spadaccini

353 91c10532 Andrea Spadaccini
    """
354 91c10532 Andrea Spadaccini
    self._check_connection()
355 91c10532 Andrea Spadaccini
356 91c10532 Andrea Spadaccini
    # Check if there is already a message in the buffer
357 91c10532 Andrea Spadaccini
    (message, self._buf) = self._ParseMessage(self._buf)
358 91c10532 Andrea Spadaccini
    if message:
359 91c10532 Andrea Spadaccini
      return message
360 91c10532 Andrea Spadaccini
361 91c10532 Andrea Spadaccini
    recv_buffer = StringIO.StringIO(self._buf)
362 91c10532 Andrea Spadaccini
    recv_buffer.seek(len(self._buf))
363 91c10532 Andrea Spadaccini
    try:
364 91c10532 Andrea Spadaccini
      while True:
365 91c10532 Andrea Spadaccini
        data = self.sock.recv(4096)
366 91c10532 Andrea Spadaccini
        if not data:
367 91c10532 Andrea Spadaccini
          break
368 91c10532 Andrea Spadaccini
        recv_buffer.write(data)
369 91c10532 Andrea Spadaccini
370 91c10532 Andrea Spadaccini
        (message, self._buf) = self._ParseMessage(recv_buffer.getvalue())
371 91c10532 Andrea Spadaccini
        if message:
372 91c10532 Andrea Spadaccini
          return message
373 91c10532 Andrea Spadaccini
374 91c10532 Andrea Spadaccini
    except socket.timeout, err:
375 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while receiving a QMP message: "
376 91c10532 Andrea Spadaccini
                                   "%s" % (err))
377 91c10532 Andrea Spadaccini
    except socket.error, err:
378 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to receive data from KVM using the"
379 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
380 91c10532 Andrea Spadaccini
381 91c10532 Andrea Spadaccini
  def _Send(self, message):
382 91c10532 Andrea Spadaccini
    """Encodes and sends a message to KVM using QMP.
383 91c10532 Andrea Spadaccini

384 91c10532 Andrea Spadaccini
    @type message: QmpMessage
385 91c10532 Andrea Spadaccini
    @param message: message to send to KVM
386 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
387 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
388 91c10532 Andrea Spadaccini

389 91c10532 Andrea Spadaccini
    """
390 91c10532 Andrea Spadaccini
    self._check_connection()
391 91c10532 Andrea Spadaccini
    try:
392 91c10532 Andrea Spadaccini
      message_str = str(message)
393 91c10532 Andrea Spadaccini
    except Exception, err:
394 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("QMP data deserialization error: %s" % err)
395 91c10532 Andrea Spadaccini
396 91c10532 Andrea Spadaccini
    try:
397 91c10532 Andrea Spadaccini
      self.sock.sendall(message_str)
398 91c10532 Andrea Spadaccini
    except socket.timeout, err:
399 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while sending a QMP message: "
400 91c10532 Andrea Spadaccini
                                   "%s (%s)" % (err.string, err.errno))
401 91c10532 Andrea Spadaccini
    except socket.error, err:
402 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to send data from KVM using the"
403 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
404 91c10532 Andrea Spadaccini
405 91c10532 Andrea Spadaccini
  def Execute(self, command, arguments=None):
406 91c10532 Andrea Spadaccini
    """Executes a QMP command and returns the response of the server.
407 91c10532 Andrea Spadaccini

408 91c10532 Andrea Spadaccini
    @type command: str
409 91c10532 Andrea Spadaccini
    @param command: the command to execute
410 91c10532 Andrea Spadaccini
    @type arguments: dict
411 91c10532 Andrea Spadaccini
    @param arguments: dictionary of arguments to be passed to the command
412 91c10532 Andrea Spadaccini
    @rtype: dict
413 91c10532 Andrea Spadaccini
    @return: dictionary representing the received JSON object
414 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
415 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
416 91c10532 Andrea Spadaccini

417 91c10532 Andrea Spadaccini
    """
418 91c10532 Andrea Spadaccini
    self._check_connection()
419 91c10532 Andrea Spadaccini
    message = QmpMessage({self._EXECUTE_KEY: command})
420 91c10532 Andrea Spadaccini
    if arguments:
421 91c10532 Andrea Spadaccini
      message[self._ARGUMENTS_KEY] = arguments
422 91c10532 Andrea Spadaccini
    self._Send(message)
423 91c10532 Andrea Spadaccini
424 91c10532 Andrea Spadaccini
    # Events can occur between the sending of the command and the reception
425 91c10532 Andrea Spadaccini
    # of the response, so we need to filter out messages with the event key.
426 91c10532 Andrea Spadaccini
    while True:
427 91c10532 Andrea Spadaccini
      response = self._Recv()
428 91c10532 Andrea Spadaccini
      err = response[self._ERROR_KEY]
429 91c10532 Andrea Spadaccini
      if err:
430 91c10532 Andrea Spadaccini
        raise errors.HypervisorError("kvm: error executing the %s"
431 02d17fe3 Dimitris Aragiorgis
                                     " command: %s (%s):" %
432 91c10532 Andrea Spadaccini
                                     (command,
433 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DESC_KEY],
434 02d17fe3 Dimitris Aragiorgis
                                      err[self._ERROR_CLASS_KEY]))
435 91c10532 Andrea Spadaccini
436 91c10532 Andrea Spadaccini
      elif not response[self._EVENT_KEY]:
437 91c10532 Andrea Spadaccini
        return response
438 91c10532 Andrea Spadaccini
439 91c10532 Andrea Spadaccini
440 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
441 65107a2f Michael Hanselmann
  """KVM hypervisor interface
442 65107a2f Michael Hanselmann

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

614 98ec75d6 Iustin Pop
    """
615 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
616 98ec75d6 Iustin Pop
617 263b8de6 Guido Trotter
  @classmethod
618 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
619 7548396c Guido Trotter
    """Returns the instance uidfile.
620 7548396c Guido Trotter

621 7548396c Guido Trotter
    """
622 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
623 7548396c Guido Trotter
624 7548396c Guido Trotter
  @classmethod
625 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
626 263b8de6 Guido Trotter
    """Check pid file for instance information.
627 263b8de6 Guido Trotter

628 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
629 263b8de6 Guido Trotter
    information from its command line.
630 263b8de6 Guido Trotter

631 263b8de6 Guido Trotter
    @type pid: string or int
632 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
633 263b8de6 Guido Trotter
    @rtype: tuple
634 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
635 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
636 263b8de6 Guido Trotter

637 263b8de6 Guido Trotter
    """
638 263b8de6 Guido Trotter
    alive = utils.IsProcessAlive(pid)
639 263b8de6 Guido Trotter
    if not alive:
640 263b8de6 Guido Trotter
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
641 263b8de6 Guido Trotter
642 263b8de6 Guido Trotter
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
643 263b8de6 Guido Trotter
    try:
644 263b8de6 Guido Trotter
      cmdline = utils.ReadFile(cmdline_file)
645 263b8de6 Guido Trotter
    except EnvironmentError, err:
646 263b8de6 Guido Trotter
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
647 263b8de6 Guido Trotter
                                   (pid, err))
648 263b8de6 Guido Trotter
649 263b8de6 Guido Trotter
    instance = None
650 263b8de6 Guido Trotter
    memory = 0
651 263b8de6 Guido Trotter
    vcpus = 0
652 263b8de6 Guido Trotter
653 d0c8c01d Iustin Pop
    arg_list = cmdline.split("\x00")
654 263b8de6 Guido Trotter
    while arg_list:
655 e687ec01 Michael Hanselmann
      arg = arg_list.pop(0)
656 263b8de6 Guido Trotter
      if arg == "-name":
657 263b8de6 Guido Trotter
        instance = arg_list.pop(0)
658 263b8de6 Guido Trotter
      elif arg == "-m":
659 263b8de6 Guido Trotter
        memory = int(arg_list.pop(0))
660 263b8de6 Guido Trotter
      elif arg == "-smp":
661 4888a609 Guido Trotter
        vcpus = int(arg_list.pop(0).split(",")[0])
662 263b8de6 Guido Trotter
663 263b8de6 Guido Trotter
    if instance is None:
664 263b8de6 Guido Trotter
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
665 263b8de6 Guido Trotter
                                   " instance" % pid)
666 263b8de6 Guido Trotter
667 263b8de6 Guido Trotter
    return (instance, memory, vcpus)
668 263b8de6 Guido Trotter
669 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
670 263b8de6 Guido Trotter
    """Returns the instance pidfile, pid, and liveness.
671 263b8de6 Guido Trotter

672 263b8de6 Guido Trotter
    @type instance_name: string
673 263b8de6 Guido Trotter
    @param instance_name: instance name
674 263b8de6 Guido Trotter
    @rtype: tuple
675 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
676 1f8b3a27 Guido Trotter

677 1f8b3a27 Guido Trotter
    """
678 98ec75d6 Iustin Pop
    pidfile = self._InstancePidFile(instance_name)
679 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
680 263b8de6 Guido Trotter
681 263b8de6 Guido Trotter
    alive = False
682 263b8de6 Guido Trotter
    try:
683 263b8de6 Guido Trotter
      cmd_instance = self._InstancePidInfo(pid)[0]
684 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
685 263b8de6 Guido Trotter
    except errors.HypervisorError:
686 263b8de6 Guido Trotter
      pass
687 1f8b3a27 Guido Trotter
688 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
689 1f8b3a27 Guido Trotter
690 5905901c Iustin Pop
  def _CheckDown(self, instance_name):
691 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
692 5905901c Iustin Pop

693 5905901c Iustin Pop
    """
694 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
695 5905901c Iustin Pop
    if alive:
696 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
697 5905901c Iustin Pop
                                   (instance_name, "already running"))
698 5905901c Iustin Pop
699 0df4d98a Guido Trotter
  @classmethod
700 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
701 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
702 c4fbefc8 Guido Trotter

703 c4fbefc8 Guido Trotter
    """
704 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
705 c4fbefc8 Guido Trotter
706 0df4d98a Guido Trotter
  @classmethod
707 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
708 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
709 c4fbefc8 Guido Trotter

710 c4fbefc8 Guido Trotter
    """
711 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
712 c4fbefc8 Guido Trotter
713 91c10532 Andrea Spadaccini
  @classmethod
714 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
715 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
716 91c10532 Andrea Spadaccini

717 91c10532 Andrea Spadaccini
    """
718 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
719 91c10532 Andrea Spadaccini
720 86d6bc2a Guido Trotter
  @staticmethod
721 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
722 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
723 86d6bc2a Guido Trotter

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

726 86d6bc2a Guido Trotter
    """
727 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
728 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
729 86d6bc2a Guido Trotter
    else:
730 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
731 86d6bc2a Guido Trotter
732 0df4d98a Guido Trotter
  @classmethod
733 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
734 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
735 38e250ba Guido Trotter

736 38e250ba Guido Trotter
    """
737 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
738 38e250ba Guido Trotter
739 7e66c35b Guido Trotter
  @classmethod
740 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
741 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
742 547a63b7 Balazs Lecz

743 547a63b7 Balazs Lecz
    """
744 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
745 547a63b7 Balazs Lecz
746 547a63b7 Balazs Lecz
  @classmethod
747 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
748 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
749 5d9bfd87 Apollon Oikonomopoulos
    given instance.
750 5d9bfd87 Apollon Oikonomopoulos

751 5d9bfd87 Apollon Oikonomopoulos
    """
752 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
753 5d9bfd87 Apollon Oikonomopoulos
754 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
755 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
756 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
757 5d9bfd87 Apollon Oikonomopoulos

758 5d9bfd87 Apollon Oikonomopoulos
    """
759 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
760 5d9bfd87 Apollon Oikonomopoulos
761 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
762 4f580fef Sรฉbastien Bocahu
  def _InstanceKeymapFile(cls, instance_name):
763 4f580fef Sรฉbastien Bocahu
    """Returns the name of the file containing the keymap for a given instance
764 4f580fef Sรฉbastien Bocahu

765 4f580fef Sรฉbastien Bocahu
    """
766 4f580fef Sรฉbastien Bocahu
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
767 4f580fef Sรฉbastien Bocahu
768 4f580fef Sรฉbastien Bocahu
  @classmethod
769 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
770 7548396c Guido Trotter
    """Try to read a uid file
771 7548396c Guido Trotter

772 7548396c Guido Trotter
    """
773 7548396c Guido Trotter
    if os.path.exists(uid_file):
774 7548396c Guido Trotter
      try:
775 682f7601 Guido Trotter
        uid = int(utils.ReadOneLineFile(uid_file))
776 aa0b600b Guido Trotter
        return uid
777 7548396c Guido Trotter
      except EnvironmentError:
778 7548396c Guido Trotter
        logging.warning("Can't read uid file", exc_info=True)
779 7548396c Guido Trotter
      except (TypeError, ValueError):
780 7548396c Guido Trotter
        logging.warning("Can't parse uid file contents", exc_info=True)
781 aa0b600b Guido Trotter
    return None
782 7548396c Guido Trotter
783 7548396c Guido Trotter
  @classmethod
784 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
785 547a63b7 Balazs Lecz
    """Removes an instance's rutime sockets/files/dirs.
786 7e66c35b Guido Trotter

787 7e66c35b Guido Trotter
    """
788 7e66c35b Guido Trotter
    utils.RemoveFile(pidfile)
789 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
790 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceSerial(instance_name))
791 91c10532 Andrea Spadaccini
    utils.RemoveFile(cls._InstanceQmpMonitor(instance_name))
792 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
793 4f580fef Sรฉbastien Bocahu
    utils.RemoveFile(cls._InstanceKeymapFile(instance_name))
794 7548396c Guido Trotter
    uid_file = cls._InstanceUidFile(instance_name)
795 7548396c Guido Trotter
    uid = cls._TryReadUidFile(uid_file)
796 7548396c Guido Trotter
    utils.RemoveFile(uid_file)
797 7548396c Guido Trotter
    if uid is not None:
798 7548396c Guido Trotter
      uidpool.ReleaseUid(uid)
799 7be85163 Guido Trotter
    try:
800 7be85163 Guido Trotter
      shutil.rmtree(cls._InstanceNICDir(instance_name))
801 7be85163 Guido Trotter
    except OSError, err:
802 7be85163 Guido Trotter
      if err.errno != errno.ENOENT:
803 7be85163 Guido Trotter
        raise
804 547a63b7 Balazs Lecz
    try:
805 547a63b7 Balazs Lecz
      chroot_dir = cls._InstanceChrootDir(instance_name)
806 547a63b7 Balazs Lecz
      utils.RemoveDir(chroot_dir)
807 547a63b7 Balazs Lecz
    except OSError, err:
808 547a63b7 Balazs Lecz
      if err.errno == errno.ENOTEMPTY:
809 547a63b7 Balazs Lecz
        # The chroot directory is expected to be empty, but it isn't.
810 547a63b7 Balazs Lecz
        new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
811 547a63b7 Balazs Lecz
                                          prefix="%s-%s-" %
812 547a63b7 Balazs Lecz
                                          (instance_name,
813 547a63b7 Balazs Lecz
                                           utils.TimestampForFilename()))
814 547a63b7 Balazs Lecz
        logging.warning("The chroot directory of instance %s can not be"
815 547a63b7 Balazs Lecz
                        " removed as it is not empty. Moving it to the"
816 547a63b7 Balazs Lecz
                        " quarantine instead. Please investigate the"
817 547a63b7 Balazs Lecz
                        " contents (%s) and clean up manually",
818 547a63b7 Balazs Lecz
                        instance_name, new_chroot_dir)
819 547a63b7 Balazs Lecz
        utils.RenameFile(chroot_dir, new_chroot_dir)
820 547a63b7 Balazs Lecz
      else:
821 547a63b7 Balazs Lecz
        raise
822 7e66c35b Guido Trotter
823 748e4b5a Michael Hanselmann
  @staticmethod
824 5d9bfd87 Apollon Oikonomopoulos
  def _ConfigureNIC(instance, seq, nic, tap):
825 5d9bfd87 Apollon Oikonomopoulos
    """Run the network configuration script for a specified NIC
826 eb58f9b1 Guido Trotter

827 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
828 eb58f9b1 Guido Trotter
    @type instance: instance object
829 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
830 eb58f9b1 Guido Trotter
    @type seq: int
831 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
832 eb58f9b1 Guido Trotter
    @type nic: nic object
833 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
834 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
835 eb58f9b1 Guido Trotter

836 eb58f9b1 Guido Trotter
    """
837 5d9bfd87 Apollon Oikonomopoulos
    if instance.tags:
838 5d9bfd87 Apollon Oikonomopoulos
      tags = " ".join(instance.tags)
839 5d9bfd87 Apollon Oikonomopoulos
    else:
840 5d9bfd87 Apollon Oikonomopoulos
      tags = ""
841 5d9bfd87 Apollon Oikonomopoulos
842 5d9bfd87 Apollon Oikonomopoulos
    env = {
843 5d9bfd87 Apollon Oikonomopoulos
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
844 5d9bfd87 Apollon Oikonomopoulos
      "INSTANCE": instance.name,
845 5d9bfd87 Apollon Oikonomopoulos
      "MAC": nic.mac,
846 5d9bfd87 Apollon Oikonomopoulos
      "MODE": nic.nicparams[constants.NIC_MODE],
847 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE": tap,
848 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE_INDEX": str(seq),
849 5d9bfd87 Apollon Oikonomopoulos
      "TAGS": tags,
850 5d9bfd87 Apollon Oikonomopoulos
    }
851 5d9bfd87 Apollon Oikonomopoulos
852 5d9bfd87 Apollon Oikonomopoulos
    if nic.ip:
853 5d9bfd87 Apollon Oikonomopoulos
      env["IP"] = nic.ip
854 5d9bfd87 Apollon Oikonomopoulos
855 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_LINK]:
856 5d9bfd87 Apollon Oikonomopoulos
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
857 5d9bfd87 Apollon Oikonomopoulos
858 a5ad5e58 Apollon Oikonomopoulos
    if nic.network:
859 cbe4a0a5 Dimitris Aragiorgis
      n = objects.Network.FromDict(nic.netinfo)
860 7e8f03e3 Dimitris Aragiorgis
      env.update(n.HooksDict())
861 a5ad5e58 Apollon Oikonomopoulos
862 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
863 5d9bfd87 Apollon Oikonomopoulos
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
864 5d9bfd87 Apollon Oikonomopoulos
865 9d9bded1 Michael Hanselmann
    result = utils.RunCmd([pathutils.KVM_IFUP, tap], env=env)
866 5d9bfd87 Apollon Oikonomopoulos
    if result.failed:
867 afa9bb2e Michael Hanselmann
      raise errors.HypervisorError("Failed to configure interface %s: %s;"
868 afa9bb2e Michael Hanselmann
                                   " network configuration script output: %s" %
869 5d9bfd87 Apollon Oikonomopoulos
                                   (tap, result.fail_reason, result.output))
870 eb58f9b1 Guido Trotter
871 b693125f Tsachy Shacham
  @staticmethod
872 b693125f Tsachy Shacham
  def _VerifyAffinityPackage():
873 b693125f Tsachy Shacham
    if affinity is None:
874 b693125f Tsachy Shacham
      raise errors.HypervisorError("affinity Python package not"
875 5ae4945a Iustin Pop
                                   " found; cannot use CPU pinning under KVM")
876 b693125f Tsachy Shacham
877 b693125f Tsachy Shacham
  @staticmethod
878 b693125f Tsachy Shacham
  def _BuildAffinityCpuMask(cpu_list):
879 b693125f Tsachy Shacham
    """Create a CPU mask suitable for sched_setaffinity from a list of
880 b693125f Tsachy Shacham
    CPUs.
881 b693125f Tsachy Shacham

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

885 b693125f Tsachy Shacham
    @type cpu_list: list of int
886 b693125f Tsachy Shacham
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
887 b693125f Tsachy Shacham
    @rtype: int
888 b693125f Tsachy Shacham
    @return: a bit mask of CPU affinities
889 b693125f Tsachy Shacham

890 b693125f Tsachy Shacham
    """
891 b693125f Tsachy Shacham
    if cpu_list == constants.CPU_PINNING_OFF:
892 b693125f Tsachy Shacham
      return constants.CPU_PINNING_ALL_KVM
893 b693125f Tsachy Shacham
    else:
894 b693125f Tsachy Shacham
      return sum(2 ** cpu for cpu in cpu_list)
895 b693125f Tsachy Shacham
896 b693125f Tsachy Shacham
  @classmethod
897 b693125f Tsachy Shacham
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
898 b693125f Tsachy Shacham
    """Change CPU affinity for running VM according to given CPU mask.
899 b693125f Tsachy Shacham

900 b693125f Tsachy Shacham
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
901 b693125f Tsachy Shacham
    @type cpu_mask: string
902 b693125f Tsachy Shacham
    @param process_id: process ID of KVM process. Used to pin entire VM
903 b693125f Tsachy Shacham
                       to physical CPUs.
904 b693125f Tsachy Shacham
    @type process_id: int
905 b693125f Tsachy Shacham
    @param thread_dict: map of virtual CPUs to KVM thread IDs
906 b693125f Tsachy Shacham
    @type thread_dict: dict int:int
907 b693125f Tsachy Shacham

908 b693125f Tsachy Shacham
    """
909 b693125f Tsachy Shacham
    # Convert the string CPU mask to a list of list of int's
910 b693125f Tsachy Shacham
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
911 b693125f Tsachy Shacham
912 b693125f Tsachy Shacham
    if len(cpu_list) == 1:
913 b693125f Tsachy Shacham
      all_cpu_mapping = cpu_list[0]
914 b693125f Tsachy Shacham
      if all_cpu_mapping == constants.CPU_PINNING_OFF:
915 b693125f Tsachy Shacham
        # If CPU pinning has 1 entry that's "all", then do nothing
916 b693125f Tsachy Shacham
        pass
917 b693125f Tsachy Shacham
      else:
918 b693125f Tsachy Shacham
        # If CPU pinning has one non-all entry, map the entire VM to
919 b693125f Tsachy Shacham
        # one set of physical CPUs
920 b693125f Tsachy Shacham
        cls._VerifyAffinityPackage()
921 5ae4945a Iustin Pop
        affinity.set_process_affinity_mask(
922 5ae4945a Iustin Pop
          process_id, cls._BuildAffinityCpuMask(all_cpu_mapping))
923 b693125f Tsachy Shacham
    else:
924 b693125f Tsachy Shacham
      # The number of vCPUs mapped should match the number of vCPUs
925 b693125f Tsachy Shacham
      # reported by KVM. This was already verified earlier, so
926 b693125f Tsachy Shacham
      # here only as a sanity check.
927 b693125f Tsachy Shacham
      assert len(thread_dict) == len(cpu_list)
928 b693125f Tsachy Shacham
      cls._VerifyAffinityPackage()
929 b693125f Tsachy Shacham
930 b693125f Tsachy Shacham
      # For each vCPU, map it to the proper list of physical CPUs
931 b693125f Tsachy Shacham
      for vcpu, i in zip(cpu_list, range(len(cpu_list))):
932 b693125f Tsachy Shacham
        affinity.set_process_affinity_mask(thread_dict[i],
933 5ae4945a Iustin Pop
                                           cls._BuildAffinityCpuMask(vcpu))
934 b693125f Tsachy Shacham
935 b693125f Tsachy Shacham
  def _GetVcpuThreadIds(self, instance_name):
936 b693125f Tsachy Shacham
    """Get a mapping of vCPU no. to thread IDs for the instance
937 b693125f Tsachy Shacham

938 b693125f Tsachy Shacham
    @type instance_name: string
939 b693125f Tsachy Shacham
    @param instance_name: instance in question
940 b693125f Tsachy Shacham
    @rtype: dictionary of int:int
941 b693125f Tsachy Shacham
    @return: a dictionary mapping vCPU numbers to thread IDs
942 b693125f Tsachy Shacham

943 b693125f Tsachy Shacham
    """
944 b693125f Tsachy Shacham
    result = {}
945 b693125f Tsachy Shacham
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
946 b693125f Tsachy Shacham
    for line in output.stdout.splitlines():
947 b693125f Tsachy Shacham
      match = self._CPU_INFO_RE.search(line)
948 b693125f Tsachy Shacham
      if not match:
949 b693125f Tsachy Shacham
        continue
950 b693125f Tsachy Shacham
      grp = map(int, match.groups())
951 b693125f Tsachy Shacham
      result[grp[0]] = grp[1]
952 b693125f Tsachy Shacham
953 b693125f Tsachy Shacham
    return result
954 b693125f Tsachy Shacham
955 1d8a7812 Andrea Spadaccini
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
956 1d8a7812 Andrea Spadaccini
    """Complete CPU pinning.
957 b693125f Tsachy Shacham

958 b693125f Tsachy Shacham
    @type instance_name: string
959 b693125f Tsachy Shacham
    @param instance_name: name of instance
960 b693125f Tsachy Shacham
    @type cpu_mask: string
961 b693125f Tsachy Shacham
    @param cpu_mask: CPU pinning mask as entered by user
962 b693125f Tsachy Shacham

963 b693125f Tsachy Shacham
    """
964 1d8a7812 Andrea Spadaccini
    # Get KVM process ID, to be used if need to pin entire VM
965 1d8a7812 Andrea Spadaccini
    _, pid, _ = self._InstancePidAlive(instance_name)
966 1d8a7812 Andrea Spadaccini
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
967 1d8a7812 Andrea Spadaccini
    thread_dict = self._GetVcpuThreadIds(instance_name)
968 1d8a7812 Andrea Spadaccini
    # Run CPU pinning, based on configured mask
969 1d8a7812 Andrea Spadaccini
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
970 b693125f Tsachy Shacham
971 58e356a9 Helga Velroyen
  def ListInstances(self, hvparams=None):
972 eb58f9b1 Guido Trotter
    """Get the list of running instances.
973 eb58f9b1 Guido Trotter

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

977 eb58f9b1 Guido Trotter
    """
978 eb58f9b1 Guido Trotter
    result = []
979 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
980 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
981 eb58f9b1 Guido Trotter
        result.append(name)
982 eb58f9b1 Guido Trotter
    return result
983 eb58f9b1 Guido Trotter
984 0bbec3af Helga Velroyen
  def GetInstanceInfo(self, instance_name, hvparams=None):
985 eb58f9b1 Guido Trotter
    """Get instance properties.
986 eb58f9b1 Guido Trotter

987 4fbb3c60 Guido Trotter
    @type instance_name: string
988 c41eea6e Iustin Pop
    @param instance_name: the instance name
989 0bbec3af Helga Velroyen
    @type hvparams: dict of strings
990 0bbec3af Helga Velroyen
    @param hvparams: hvparams to be used with this instance
991 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
992 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
993 eb58f9b1 Guido Trotter

994 eb58f9b1 Guido Trotter
    """
995 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
996 1f8b3a27 Guido Trotter
    if not alive:
997 eb58f9b1 Guido Trotter
      return None
998 eb58f9b1 Guido Trotter
999 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
1000 fc84cd5d Guido Trotter
    istat = "---b-"
1001 eb58f9b1 Guido Trotter
    times = "0"
1002 eb58f9b1 Guido Trotter
1003 89da2ff3 Guido Trotter
    try:
1004 89da2ff3 Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
1005 89da2ff3 Guido Trotter
      qmp.connect()
1006 89da2ff3 Guido Trotter
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
1007 89da2ff3 Guido Trotter
      # Will fail if ballooning is not enabled, but we can then just resort to
1008 89da2ff3 Guido Trotter
      # the value above.
1009 89da2ff3 Guido Trotter
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
1010 89da2ff3 Guido Trotter
      memory = mem_bytes / 1048576
1011 89da2ff3 Guido Trotter
    except errors.HypervisorError:
1012 89da2ff3 Guido Trotter
      pass
1013 89da2ff3 Guido Trotter
1014 fc84cd5d Guido Trotter
    return (instance_name, pid, memory, vcpus, istat, times)
1015 eb58f9b1 Guido Trotter
1016 0200a1af Helga Velroyen
  def GetAllInstancesInfo(self, hvparams=None):
1017 eb58f9b1 Guido Trotter
    """Get properties of all instances.
1018 eb58f9b1 Guido Trotter

1019 0200a1af Helga Velroyen
    @type hvparams: dict of strings
1020 0200a1af Helga Velroyen
    @param hvparams: hypervisor parameter
1021 c41eea6e Iustin Pop
    @return: list of tuples (name, id, memory, vcpus, stat, times)
1022 c41eea6e Iustin Pop

1023 eb58f9b1 Guido Trotter
    """
1024 eb58f9b1 Guido Trotter
    data = []
1025 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1026 263b8de6 Guido Trotter
      try:
1027 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
1028 263b8de6 Guido Trotter
      except errors.HypervisorError:
1029 3bc145d8 Bernardo Dal Seno
        # Ignore exceptions due to instances being shut down
1030 263b8de6 Guido Trotter
        continue
1031 263b8de6 Guido Trotter
      if info:
1032 263b8de6 Guido Trotter
        data.append(info)
1033 eb58f9b1 Guido Trotter
    return data
1034 eb58f9b1 Guido Trotter
1035 b73f1c59 Guido Trotter
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused,
1036 b73f1c59 Guido Trotter
                          kvmhelp):
1037 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
1038 eb58f9b1 Guido Trotter

1039 b73f1c59 Guido Trotter
    @type kvmhelp: string
1040 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1041 839642c2 Iustin Pop
    @attention: this function must not have any side-effects; for
1042 839642c2 Iustin Pop
        example, it must not write to the filesystem, or read values
1043 839642c2 Iustin Pop
        from the current system the are expected to differ between
1044 839642c2 Iustin Pop
        nodes, since it is only run once at instance startup;
1045 839642c2 Iustin Pop
        actions/kvm arguments that can vary between systems should be
1046 839642c2 Iustin Pop
        done in L{_ExecuteKVMRuntime}
1047 839642c2 Iustin Pop

1048 eb58f9b1 Guido Trotter
    """
1049 4888a609 Guido Trotter
    # pylint: disable=R0912,R0914,R0915
1050 4888a609 Guido Trotter
    hvp = instance.hvparams
1051 81e265f5 Guido Trotter
    self.ValidateParameters(hvp)
1052 4304964a Guido Trotter
1053 e687ec01 Michael Hanselmann
    pidfile = self._InstancePidFile(instance.name)
1054 4b9638dc Guido Trotter
    kvm = hvp[constants.HV_KVM_PATH]
1055 eb58f9b1 Guido Trotter
    kvm_cmd = [kvm]
1056 c6a39fc2 Guido Trotter
    # used just by the vnc server, if enabled
1057 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-name", instance.name])
1058 f5a4b9ce Guido Trotter
    kvm_cmd.extend(["-m", instance.beparams[constants.BE_MAXMEM]])
1059 4888a609 Guido Trotter
1060 4888a609 Guido Trotter
    smp_list = ["%s" % instance.beparams[constants.BE_VCPUS]]
1061 4888a609 Guido Trotter
    if hvp[constants.HV_CPU_CORES]:
1062 4888a609 Guido Trotter
      smp_list.append("cores=%s" % hvp[constants.HV_CPU_CORES])
1063 4888a609 Guido Trotter
    if hvp[constants.HV_CPU_THREADS]:
1064 4888a609 Guido Trotter
      smp_list.append("threads=%s" % hvp[constants.HV_CPU_THREADS])
1065 4888a609 Guido Trotter
    if hvp[constants.HV_CPU_SOCKETS]:
1066 4888a609 Guido Trotter
      smp_list.append("sockets=%s" % hvp[constants.HV_CPU_SOCKETS])
1067 4888a609 Guido Trotter
1068 4888a609 Guido Trotter
    kvm_cmd.extend(["-smp", ",".join(smp_list)])
1069 4888a609 Guido Trotter
1070 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-pidfile", pidfile])
1071 fcf5b670 Guido Trotter
    kvm_cmd.extend(["-balloon", "virtio"])
1072 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-daemonize"])
1073 6b5605e8 Iustin Pop
    if not instance.hvparams[constants.HV_ACPI]:
1074 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-no-acpi"])
1075 990ade2d Stephen Shirley
    if instance.hvparams[constants.HV_REBOOT_BEHAVIOR] == \
1076 990ade2d Stephen Shirley
        constants.INSTANCE_REBOOT_EXIT:
1077 990ade2d Stephen Shirley
      kvm_cmd.extend(["-no-reboot"])
1078 eb58f9b1 Guido Trotter
1079 4ab75599 Dimitris Aragiorgis
    mversion = hvp[constants.HV_KVM_MACHINE_VERSION]
1080 4ab75599 Dimitris Aragiorgis
    if not mversion:
1081 4b9638dc Guido Trotter
      mversion = self._GetDefaultMachineVersion(kvm)
1082 8cb5634a Guido Trotter
    if self._MACHINE_RE.search(kvmhelp):
1083 8cb5634a Guido Trotter
      # TODO (2.8): kernel_irqchip and kvm_shadow_mem machine properties, as
1084 8cb5634a Guido Trotter
      # extra hypervisor parameters. We should also investigate whether and how
1085 8cb5634a Guido Trotter
      # shadow_mem should be considered for the resource model.
1086 8cb5634a Guido Trotter
      if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED):
1087 8cb5634a Guido Trotter
        specprop = ",accel=kvm"
1088 8cb5634a Guido Trotter
      else:
1089 8cb5634a Guido Trotter
        specprop = ""
1090 8cb5634a Guido Trotter
      machinespec = "%s%s" % (mversion, specprop)
1091 8cb5634a Guido Trotter
      kvm_cmd.extend(["-machine", machinespec])
1092 8cb5634a Guido Trotter
    else:
1093 8cb5634a Guido Trotter
      kvm_cmd.extend(["-M", mversion])
1094 8cb5634a Guido Trotter
      if (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED and
1095 8cb5634a Guido Trotter
          self._ENABLE_KVM_RE.search(kvmhelp)):
1096 8cb5634a Guido Trotter
        kvm_cmd.extend(["-enable-kvm"])
1097 8cb5634a Guido Trotter
      elif (hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED and
1098 8cb5634a Guido Trotter
            self._DISABLE_KVM_RE.search(kvmhelp)):
1099 8cb5634a Guido Trotter
        kvm_cmd.extend(["-disable-kvm"])
1100 4ab75599 Dimitris Aragiorgis
1101 2b846304 Iustin Pop
    kernel_path = hvp[constants.HV_KERNEL_PATH]
1102 2b846304 Iustin Pop
    if kernel_path:
1103 2b846304 Iustin Pop
      boot_disk = boot_cdrom = boot_floppy = boot_network = False
1104 2b846304 Iustin Pop
    else:
1105 2b846304 Iustin Pop
      boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
1106 2b846304 Iustin Pop
      boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
1107 2b846304 Iustin Pop
      boot_floppy = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_FLOPPY
1108 2b846304 Iustin Pop
      boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
1109 8745c3d7 Guido Trotter
1110 b693125f Tsachy Shacham
    if startup_paused:
1111 b693125f Tsachy Shacham
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1112 b693125f Tsachy Shacham
1113 8745c3d7 Guido Trotter
    if boot_network:
1114 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-boot", "n"])
1115 1213604d Guido Trotter
1116 24be50e0 Iustin Pop
    # whether this is an older KVM version that uses the boot=on flag
1117 24be50e0 Iustin Pop
    # on devices
1118 0ad7f5d8 Guido Trotter
    needs_boot_flag = self._BOOT_RE.search(kvmhelp)
1119 24be50e0 Iustin Pop
1120 a985b417 Iustin Pop
    disk_type = hvp[constants.HV_DISK_TYPE]
1121 1213604d Guido Trotter
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
1122 d0c8c01d Iustin Pop
      if_val = ",if=virtio"
1123 1213604d Guido Trotter
    else:
1124 d0c8c01d Iustin Pop
      if_val = ",if=%s" % disk_type
1125 19572932 Iustin Pop
    # Cache mode
1126 19572932 Iustin Pop
    disk_cache = hvp[constants.HV_DISK_CACHE]
1127 41e794f6 Apollon Oikonomopoulos
    if instance.disk_template in constants.DTS_EXT_MIRROR:
1128 41e794f6 Apollon Oikonomopoulos
      if disk_cache != "none":
1129 41e794f6 Apollon Oikonomopoulos
        # TODO: make this a hard error, instead of a silent overwrite
1130 41e794f6 Apollon Oikonomopoulos
        logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
1131 41e794f6 Apollon Oikonomopoulos
                        " to prevent shared storage corruption on migration",
1132 41e794f6 Apollon Oikonomopoulos
                        disk_cache)
1133 41e794f6 Apollon Oikonomopoulos
      cache_val = ",cache=none"
1134 41e794f6 Apollon Oikonomopoulos
    elif disk_cache != constants.HT_CACHE_DEFAULT:
1135 19572932 Iustin Pop
      cache_val = ",cache=%s" % disk_cache
1136 19572932 Iustin Pop
    else:
1137 19572932 Iustin Pop
      cache_val = ""
1138 069cfbf1 Iustin Pop
    for cfdev, dev_path in block_devices:
1139 d34b16d7 Iustin Pop
      if cfdev.mode != constants.DISK_RDWR:
1140 d34b16d7 Iustin Pop
        raise errors.HypervisorError("Instance has read-only disks which"
1141 d34b16d7 Iustin Pop
                                     " are not supported by KVM")
1142 eb58f9b1 Guido Trotter
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
1143 4304964a Guido Trotter
      boot_val = ""
1144 66d5dbef Guido Trotter
      if boot_disk:
1145 d0c8c01d Iustin Pop
        kvm_cmd.extend(["-boot", "c"])
1146 66d5dbef Guido Trotter
        boot_disk = False
1147 24be50e0 Iustin Pop
        if needs_boot_flag and disk_type != constants.HT_DISK_IDE:
1148 4304964a Guido Trotter
          boot_val = ",boot=on"
1149 eb58f9b1 Guido Trotter
1150 d0c8c01d Iustin Pop
      drive_val = "file=%s,format=raw%s%s%s" % (dev_path, if_val, boot_val,
1151 19572932 Iustin Pop
                                                cache_val)
1152 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1153 eb58f9b1 Guido Trotter
1154 cc130cc7 Marco Casavecchia
    #Now we can specify a different device type for CDROM devices.
1155 cc130cc7 Marco Casavecchia
    cdrom_disk_type = hvp[constants.HV_KVM_CDROM_DISK_TYPE]
1156 cc130cc7 Marco Casavecchia
    if not cdrom_disk_type:
1157 cc130cc7 Marco Casavecchia
      cdrom_disk_type = disk_type
1158 cc130cc7 Marco Casavecchia
1159 a985b417 Iustin Pop
    iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
1160 66d5dbef Guido Trotter
    if iso_image:
1161 d0c8c01d Iustin Pop
      options = ",format=raw,media=cdrom"
1162 24be50e0 Iustin Pop
      # set cdrom 'if' type
1163 66d5dbef Guido Trotter
      if boot_cdrom:
1164 24be50e0 Iustin Pop
        actual_cdrom_type = constants.HT_DISK_IDE
1165 24be50e0 Iustin Pop
      elif cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1166 24be50e0 Iustin Pop
        actual_cdrom_type = "virtio"
1167 9dd363eb Guido Trotter
      else:
1168 24be50e0 Iustin Pop
        actual_cdrom_type = cdrom_disk_type
1169 24be50e0 Iustin Pop
      if_val = ",if=%s" % actual_cdrom_type
1170 24be50e0 Iustin Pop
      # set boot flag, if needed
1171 24be50e0 Iustin Pop
      boot_val = ""
1172 24be50e0 Iustin Pop
      if boot_cdrom:
1173 24be50e0 Iustin Pop
        kvm_cmd.extend(["-boot", "d"])
1174 24be50e0 Iustin Pop
        if needs_boot_flag:
1175 24be50e0 Iustin Pop
          boot_val = ",boot=on"
1176 24be50e0 Iustin Pop
      # and finally build the entire '-drive' value
1177 24be50e0 Iustin Pop
      drive_val = "file=%s%s%s%s" % (iso_image, options, if_val, boot_val)
1178 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1179 66d5dbef Guido Trotter
1180 cc130cc7 Marco Casavecchia
    iso_image2 = hvp[constants.HV_KVM_CDROM2_IMAGE_PATH]
1181 cc130cc7 Marco Casavecchia
    if iso_image2:
1182 d0c8c01d Iustin Pop
      options = ",format=raw,media=cdrom"
1183 cc130cc7 Marco Casavecchia
      if cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1184 d0c8c01d Iustin Pop
        if_val = ",if=virtio"
1185 cc130cc7 Marco Casavecchia
      else:
1186 d0c8c01d Iustin Pop
        if_val = ",if=%s" % cdrom_disk_type
1187 24be50e0 Iustin Pop
      drive_val = "file=%s%s%s" % (iso_image2, options, if_val)
1188 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1189 cc130cc7 Marco Casavecchia
1190 cc130cc7 Marco Casavecchia
    floppy_image = hvp[constants.HV_KVM_FLOPPY_IMAGE_PATH]
1191 cc130cc7 Marco Casavecchia
    if floppy_image:
1192 d0c8c01d Iustin Pop
      options = ",format=raw,media=disk"
1193 cc130cc7 Marco Casavecchia
      if boot_floppy:
1194 d0c8c01d Iustin Pop
        kvm_cmd.extend(["-boot", "a"])
1195 d0c8c01d Iustin Pop
        options = "%s,boot=on" % options
1196 d0c8c01d Iustin Pop
      if_val = ",if=floppy"
1197 d0c8c01d Iustin Pop
      options = "%s%s" % (options, if_val)
1198 d0c8c01d Iustin Pop
      drive_val = "file=%s%s" % (floppy_image, options)
1199 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1200 cc130cc7 Marco Casavecchia
1201 df5ab9f0 Guido Trotter
    if kernel_path:
1202 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-kernel", kernel_path])
1203 a985b417 Iustin Pop
      initrd_path = hvp[constants.HV_INITRD_PATH]
1204 df5ab9f0 Guido Trotter
      if initrd_path:
1205 d0c8c01d Iustin Pop
        kvm_cmd.extend(["-initrd", initrd_path])
1206 d0c8c01d Iustin Pop
      root_append = ["root=%s" % hvp[constants.HV_ROOT_PATH],
1207 07813a9e Iustin Pop
                     hvp[constants.HV_KERNEL_ARGS]]
1208 07813a9e Iustin Pop
      if hvp[constants.HV_SERIAL_CONSOLE]:
1209 14fd6c81 Guido Trotter
        serial_speed = hvp[constants.HV_SERIAL_SPEED]
1210 14fd6c81 Guido Trotter
        root_append.append("console=ttyS0,%s" % serial_speed)
1211 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-append", " ".join(root_append)])
1212 eb58f9b1 Guido Trotter
1213 4f958b0b Miguel Di Ciurcio Filho
    mem_path = hvp[constants.HV_MEM_PATH]
1214 4f958b0b Miguel Di Ciurcio Filho
    if mem_path:
1215 9d3015f9 Guido Trotter
      kvm_cmd.extend(["-mem-path", mem_path, "-mem-prealloc"])
1216 4f958b0b Miguel Di Ciurcio Filho
1217 596b2459 Guido Trotter
    monitor_dev = ("unix:%s,server,nowait" %
1218 596b2459 Guido Trotter
                   self._InstanceMonitor(instance.name))
1219 596b2459 Guido Trotter
    kvm_cmd.extend(["-monitor", monitor_dev])
1220 596b2459 Guido Trotter
    if hvp[constants.HV_SERIAL_CONSOLE]:
1221 596b2459 Guido Trotter
      serial_dev = ("unix:%s,server,nowait" %
1222 596b2459 Guido Trotter
                    self._InstanceSerial(instance.name))
1223 596b2459 Guido Trotter
      kvm_cmd.extend(["-serial", serial_dev])
1224 596b2459 Guido Trotter
    else:
1225 596b2459 Guido Trotter
      kvm_cmd.extend(["-serial", "none"])
1226 596b2459 Guido Trotter
1227 a985b417 Iustin Pop
    mouse_type = hvp[constants.HV_USB_MOUSE]
1228 31f6f67a Guido Trotter
    vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
1229 596b2459 Guido Trotter
    spice_bind = hvp[constants.HV_KVM_SPICE_BIND]
1230 596b2459 Guido Trotter
    spice_ip_version = None
1231 31f6f67a Guido Trotter
1232 a900a30c Guido Trotter
    kvm_cmd.extend(["-usb"])
1233 a900a30c Guido Trotter
1234 11344a50 Guido Trotter
    if mouse_type:
1235 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-usbdevice", mouse_type])
1236 31f6f67a Guido Trotter
    elif vnc_bind_address:
1237 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-usbdevice", constants.HT_MOUSE_TABLET])
1238 11344a50 Guido Trotter
1239 8470c8db Guido Trotter
    if vnc_bind_address:
1240 d6e5767e Klaus Aehlig
      if netutils.IsValidInterface(vnc_bind_address):
1241 d6e5767e Klaus Aehlig
        if_addresses = netutils.GetInterfaceIpAddresses(vnc_bind_address)
1242 d6e5767e Klaus Aehlig
        if_ip4_addresses = if_addresses[constants.IP4_VERSION]
1243 d6e5767e Klaus Aehlig
        if len(if_ip4_addresses) < 1:
1244 d6e5767e Klaus Aehlig
          logging.error("Could not determine IPv4 address of interface %s",
1245 d6e5767e Klaus Aehlig
                        vnc_bind_address)
1246 d6e5767e Klaus Aehlig
        else:
1247 d6e5767e Klaus Aehlig
          vnc_bind_address = if_ip4_addresses[0]
1248 8b312c1d Manuel Franceschini
      if netutils.IP4Address.IsValid(vnc_bind_address):
1249 377d74c9 Guido Trotter
        if instance.network_port > constants.VNC_BASE_PORT:
1250 377d74c9 Guido Trotter
          display = instance.network_port - constants.VNC_BASE_PORT
1251 14f5f1b6 Manuel Franceschini
          if vnc_bind_address == constants.IP4_ADDRESS_ANY:
1252 d0c8c01d Iustin Pop
            vnc_arg = ":%d" % (display)
1253 8447f52b Guido Trotter
          else:
1254 d0c8c01d Iustin Pop
            vnc_arg = "%s:%d" % (vnc_bind_address, display)
1255 8470c8db Guido Trotter
        else:
1256 afa9bb2e Michael Hanselmann
          logging.error("Network port is not a valid VNC display (%d < %d),"
1257 afa9bb2e Michael Hanselmann
                        " not starting VNC",
1258 afa9bb2e Michael Hanselmann
                        instance.network_port, constants.VNC_BASE_PORT)
1259 d0c8c01d Iustin Pop
          vnc_arg = "none"
1260 8b2d1013 Guido Trotter
1261 8b2d1013 Guido Trotter
        # Only allow tls and other option when not binding to a file, for now.
1262 8b2d1013 Guido Trotter
        # kvm/qemu gets confused otherwise about the filename to use.
1263 d0c8c01d Iustin Pop
        vnc_append = ""
1264 a985b417 Iustin Pop
        if hvp[constants.HV_VNC_TLS]:
1265 d0c8c01d Iustin Pop
          vnc_append = "%s,tls" % vnc_append
1266 a985b417 Iustin Pop
          if hvp[constants.HV_VNC_X509_VERIFY]:
1267 d0c8c01d Iustin Pop
            vnc_append = "%s,x509verify=%s" % (vnc_append,
1268 a985b417 Iustin Pop
                                               hvp[constants.HV_VNC_X509])
1269 a985b417 Iustin Pop
          elif hvp[constants.HV_VNC_X509]:
1270 d0c8c01d Iustin Pop
            vnc_append = "%s,x509=%s" % (vnc_append,
1271 a985b417 Iustin Pop
                                         hvp[constants.HV_VNC_X509])
1272 6e6bb8d5 Guido Trotter
        if hvp[constants.HV_VNC_PASSWORD_FILE]:
1273 d0c8c01d Iustin Pop
          vnc_append = "%s,password" % vnc_append
1274 6e6bb8d5 Guido Trotter
1275 d0c8c01d Iustin Pop
        vnc_arg = "%s%s" % (vnc_arg, vnc_append)
1276 8b2d1013 Guido Trotter
1277 8470c8db Guido Trotter
      else:
1278 d0c8c01d Iustin Pop
        vnc_arg = "unix:%s/%s.vnc" % (vnc_bind_address, instance.name)
1279 8b2d1013 Guido Trotter
1280 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-vnc", vnc_arg])
1281 596b2459 Guido Trotter
    elif spice_bind:
1282 839642c2 Iustin Pop
      # FIXME: this is wrong here; the iface ip address differs
1283 839642c2 Iustin Pop
      # between systems, so it should be done in _ExecuteKVMRuntime
1284 b1cb62bd Andrea Spadaccini
      if netutils.IsValidInterface(spice_bind):
1285 b1cb62bd Andrea Spadaccini
        # The user specified a network interface, we have to figure out the IP
1286 b1cb62bd Andrea Spadaccini
        # address.
1287 b1cb62bd Andrea Spadaccini
        addresses = netutils.GetInterfaceIpAddresses(spice_bind)
1288 b1cb62bd Andrea Spadaccini
        spice_ip_version = hvp[constants.HV_KVM_SPICE_IP_VERSION]
1289 b1cb62bd Andrea Spadaccini
1290 b1cb62bd Andrea Spadaccini
        # if the user specified an IP version and the interface does not
1291 b1cb62bd Andrea Spadaccini
        # have that kind of IP addresses, throw an exception
1292 b1cb62bd Andrea Spadaccini
        if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1293 b1cb62bd Andrea Spadaccini
          if not addresses[spice_ip_version]:
1294 afa9bb2e Michael Hanselmann
            raise errors.HypervisorError("SPICE: Unable to get an IPv%s address"
1295 b1cb62bd Andrea Spadaccini
                                         " for %s" % (spice_ip_version,
1296 b1cb62bd Andrea Spadaccini
                                                      spice_bind))
1297 b1cb62bd Andrea Spadaccini
1298 b1cb62bd Andrea Spadaccini
        # the user did not specify an IP version, we have to figure it out
1299 b1cb62bd Andrea Spadaccini
        elif (addresses[constants.IP4_VERSION] and
1300 b1cb62bd Andrea Spadaccini
              addresses[constants.IP6_VERSION]):
1301 b1cb62bd Andrea Spadaccini
          # we have both ipv4 and ipv6, let's use the cluster default IP
1302 b1cb62bd Andrea Spadaccini
          # version
1303 b1cb62bd Andrea Spadaccini
          cluster_family = ssconf.SimpleStore().GetPrimaryIPFamily()
1304 65107a2f Michael Hanselmann
          spice_ip_version = \
1305 65107a2f Michael Hanselmann
            netutils.IPAddress.GetVersionFromAddressFamily(cluster_family)
1306 b1cb62bd Andrea Spadaccini
        elif addresses[constants.IP4_VERSION]:
1307 b1cb62bd Andrea Spadaccini
          spice_ip_version = constants.IP4_VERSION
1308 b845c8a1 Andrea Spadaccini
        elif addresses[constants.IP6_VERSION]:
1309 b1cb62bd Andrea Spadaccini
          spice_ip_version = constants.IP6_VERSION
1310 b845c8a1 Andrea Spadaccini
        else:
1311 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Unable to get an IP address"
1312 b845c8a1 Andrea Spadaccini
                                       " for %s" % (spice_bind))
1313 b1cb62bd Andrea Spadaccini
1314 b1cb62bd Andrea Spadaccini
        spice_address = addresses[spice_ip_version][0]
1315 b1cb62bd Andrea Spadaccini
1316 b1cb62bd Andrea Spadaccini
      else:
1317 b1cb62bd Andrea Spadaccini
        # spice_bind is known to be a valid IP address, because
1318 b1cb62bd Andrea Spadaccini
        # ValidateParameters checked it.
1319 b1cb62bd Andrea Spadaccini
        spice_address = spice_bind
1320 b1cb62bd Andrea Spadaccini
1321 bfe86c76 Andrea Spadaccini
      spice_arg = "addr=%s" % spice_address
1322 bfe86c76 Andrea Spadaccini
      if hvp[constants.HV_KVM_SPICE_USE_TLS]:
1323 5ae4945a Iustin Pop
        spice_arg = ("%s,tls-port=%s,x509-cacert-file=%s" %
1324 5ae4945a Iustin Pop
                     (spice_arg, instance.network_port,
1325 9d9bded1 Michael Hanselmann
                      pathutils.SPICE_CACERT_FILE))
1326 5ae4945a Iustin Pop
        spice_arg = ("%s,x509-key-file=%s,x509-cert-file=%s" %
1327 9d9bded1 Michael Hanselmann
                     (spice_arg, pathutils.SPICE_CERT_FILE,
1328 9d9bded1 Michael Hanselmann
                      pathutils.SPICE_CERT_FILE))
1329 3e40b587 Andrea Spadaccini
        tls_ciphers = hvp[constants.HV_KVM_SPICE_TLS_CIPHERS]
1330 3e40b587 Andrea Spadaccini
        if tls_ciphers:
1331 3e40b587 Andrea Spadaccini
          spice_arg = "%s,tls-ciphers=%s" % (spice_arg, tls_ciphers)
1332 bfe86c76 Andrea Spadaccini
      else:
1333 bfe86c76 Andrea Spadaccini
        spice_arg = "%s,port=%s" % (spice_arg, instance.network_port)
1334 bfe86c76 Andrea Spadaccini
1335 b451c4c7 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]:
1336 b451c4c7 Andrea Spadaccini
        spice_arg = "%s,disable-ticketing" % spice_arg
1337 b451c4c7 Andrea Spadaccini
1338 11ae7a0a Andrea Spadaccini
      if spice_ip_version:
1339 11ae7a0a Andrea Spadaccini
        spice_arg = "%s,ipv%s" % (spice_arg, spice_ip_version)
1340 b1cb62bd Andrea Spadaccini
1341 ea064d24 Andrea Spadaccini
      # Image compression options
1342 ea064d24 Andrea Spadaccini
      img_lossless = hvp[constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR]
1343 ea064d24 Andrea Spadaccini
      img_jpeg = hvp[constants.HV_KVM_SPICE_JPEG_IMG_COMPR]
1344 ea064d24 Andrea Spadaccini
      img_zlib_glz = hvp[constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR]
1345 ea064d24 Andrea Spadaccini
      if img_lossless:
1346 ea064d24 Andrea Spadaccini
        spice_arg = "%s,image-compression=%s" % (spice_arg, img_lossless)
1347 ea064d24 Andrea Spadaccini
      if img_jpeg:
1348 ea064d24 Andrea Spadaccini
        spice_arg = "%s,jpeg-wan-compression=%s" % (spice_arg, img_jpeg)
1349 ea064d24 Andrea Spadaccini
      if img_zlib_glz:
1350 ea064d24 Andrea Spadaccini
        spice_arg = "%s,zlib-glz-wan-compression=%s" % (spice_arg, img_zlib_glz)
1351 ea064d24 Andrea Spadaccini
1352 ea064d24 Andrea Spadaccini
      # Video stream detection
1353 ea064d24 Andrea Spadaccini
      video_streaming = hvp[constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION]
1354 ea064d24 Andrea Spadaccini
      if video_streaming:
1355 ea064d24 Andrea Spadaccini
        spice_arg = "%s,streaming-video=%s" % (spice_arg, video_streaming)
1356 ea064d24 Andrea Spadaccini
1357 ea064d24 Andrea Spadaccini
      # Audio compression, by default in qemu-kvm it is on
1358 ea064d24 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_AUDIO_COMPR]:
1359 ea064d24 Andrea Spadaccini
        spice_arg = "%s,playback-compression=off" % spice_arg
1360 3e40b587 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_USE_VDAGENT]:
1361 3e40b587 Andrea Spadaccini
        spice_arg = "%s,agent-mouse=off" % spice_arg
1362 447af814 Nikos Skalkotos
      else:
1363 447af814 Nikos Skalkotos
        # Enable the spice agent communication channel between the host and the
1364 447af814 Nikos Skalkotos
        # agent.
1365 447af814 Nikos Skalkotos
        kvm_cmd.extend(["-device", "virtio-serial-pci"])
1366 afa9bb2e Michael Hanselmann
        kvm_cmd.extend([
1367 afa9bb2e Michael Hanselmann
          "-device",
1368 afa9bb2e Michael Hanselmann
          "virtserialport,chardev=spicechannel0,name=com.redhat.spice.0",
1369 afa9bb2e Michael Hanselmann
          ])
1370 447af814 Nikos Skalkotos
        kvm_cmd.extend(["-chardev", "spicevmc,id=spicechannel0,name=vdagent"])
1371 ea064d24 Andrea Spadaccini
1372 b1cb62bd Andrea Spadaccini
      logging.info("KVM: SPICE will listen on port %s", instance.network_port)
1373 b1cb62bd Andrea Spadaccini
      kvm_cmd.extend(["-spice", spice_arg])
1374 b1cb62bd Andrea Spadaccini
1375 596b2459 Guido Trotter
    else:
1376 99c7cd5b Guido Trotter
      # From qemu 1.4 -nographic is incompatible with -daemonize. The new way
1377 99c7cd5b Guido Trotter
      # also works in earlier versions though (tested with 1.1 and 1.3)
1378 99c7cd5b Guido Trotter
      if self._DISPLAY_RE.search(kvmhelp):
1379 99c7cd5b Guido Trotter
        kvm_cmd.extend(["-display", "none"])
1380 99c7cd5b Guido Trotter
      else:
1381 99c7cd5b Guido Trotter
        kvm_cmd.extend(["-nographic"])
1382 596b2459 Guido Trotter
1383 6b970cef Jun Futagawa
    if hvp[constants.HV_USE_LOCALTIME]:
1384 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-localtime"])
1385 6b970cef Jun Futagawa
1386 547a63b7 Balazs Lecz
    if hvp[constants.HV_KVM_USE_CHROOT]:
1387 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-chroot", self._InstanceChrootDir(instance.name)])
1388 547a63b7 Balazs Lecz
1389 7cb42171 Nikita Staroverov
    # Add qemu-KVM -cpu param
1390 7cb42171 Nikita Staroverov
    if hvp[constants.HV_CPU_TYPE]:
1391 7cb42171 Nikita Staroverov
      kvm_cmd.extend(["-cpu", hvp[constants.HV_CPU_TYPE]])
1392 7cb42171 Nikita Staroverov
1393 2fddb144 Guido Trotter
    # As requested by music lovers
1394 2fddb144 Guido Trotter
    if hvp[constants.HV_SOUNDHW]:
1395 2fddb144 Guido Trotter
      kvm_cmd.extend(["-soundhw", hvp[constants.HV_SOUNDHW]])
1396 2fddb144 Guido Trotter
1397 7589346f Guido Trotter
    # Pass a -vga option if requested, or if spice is used, for backwards
1398 7589346f Guido Trotter
    # compatibility.
1399 7589346f Guido Trotter
    if hvp[constants.HV_VGA]:
1400 7589346f Guido Trotter
      kvm_cmd.extend(["-vga", hvp[constants.HV_VGA]])
1401 7589346f Guido Trotter
    elif spice_bind:
1402 7589346f Guido Trotter
      kvm_cmd.extend(["-vga", "qxl"])
1403 7589346f Guido Trotter
1404 156681c1 Guido Trotter
    # Various types of usb devices, comma separated
1405 156681c1 Guido Trotter
    if hvp[constants.HV_USB_DEVICES]:
1406 156681c1 Guido Trotter
      for dev in hvp[constants.HV_USB_DEVICES].split(","):
1407 156681c1 Guido Trotter
        kvm_cmd.extend(["-usbdevice", dev])
1408 156681c1 Guido Trotter
1409 8feeb253 Christos Stavrakakis
    # Set system UUID to instance UUID
1410 8feeb253 Christos Stavrakakis
    if self._UUID_RE.search(kvmhelp):
1411 8feeb253 Christos Stavrakakis
      kvm_cmd.extend(["-uuid", instance.uuid])
1412 8feeb253 Christos Stavrakakis
1413 e6f24d89 Guido Trotter
    if hvp[constants.HV_KVM_EXTRA]:
1414 a967416c Guido Trotter
      kvm_cmd.extend(hvp[constants.HV_KVM_EXTRA].split(" "))
1415 e6f24d89 Guido Trotter
1416 ee5f20b0 Guido Trotter
    # Save the current instance nics, but defer their expansion as parameters,
1417 ee5f20b0 Guido Trotter
    # as we'll need to generate executable temp files for them.
1418 ee5f20b0 Guido Trotter
    kvm_nics = instance.nics
1419 a985b417 Iustin Pop
    hvparams = hvp
1420 ee5f20b0 Guido Trotter
1421 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
1422 ee5f20b0 Guido Trotter
1423 38e250ba Guido Trotter
  def _WriteKVMRuntime(self, instance_name, data):
1424 38e250ba Guido Trotter
    """Write an instance's KVM runtime
1425 38e250ba Guido Trotter

1426 38e250ba Guido Trotter
    """
1427 38e250ba Guido Trotter
    try:
1428 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1429 38e250ba Guido Trotter
                      data=data)
1430 90c024f6 Guido Trotter
    except EnvironmentError, err:
1431 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1432 38e250ba Guido Trotter
1433 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
1434 38e250ba Guido Trotter
    """Read an instance's KVM runtime
1435 38e250ba Guido Trotter

1436 38e250ba Guido Trotter
    """
1437 38e250ba Guido Trotter
    try:
1438 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1439 90c024f6 Guido Trotter
    except EnvironmentError, err:
1440 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1441 38e250ba Guido Trotter
    return file_content
1442 38e250ba Guido Trotter
1443 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1444 38e250ba Guido Trotter
    """Save an instance's KVM runtime
1445 38e250ba Guido Trotter

1446 38e250ba Guido Trotter
    """
1447 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
1448 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1449 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
1450 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
1451 38e250ba Guido Trotter
1452 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1453 38e250ba Guido Trotter
    """Load an instance's KVM runtime
1454 38e250ba Guido Trotter

1455 38e250ba Guido Trotter
    """
1456 30e42c4e Guido Trotter
    if not serialized_runtime:
1457 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1458 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
1459 c2672466 Guido Trotter
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
1460 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
1461 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
1462 38e250ba Guido Trotter
1463 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1464 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
1465 76431533 Guido Trotter

1466 76431533 Guido Trotter
    @type name: string
1467 76431533 Guido Trotter
    @param name: instance name
1468 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1469 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1470 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1471 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1472 76431533 Guido Trotter

1473 76431533 Guido Trotter
    """
1474 5d9bfd87 Apollon Oikonomopoulos
    try:
1475 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1476 5d9bfd87 Apollon Oikonomopoulos
    finally:
1477 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
1478 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
1479 5d9bfd87 Apollon Oikonomopoulos
1480 76431533 Guido Trotter
    if result.failed:
1481 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1482 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
1483 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
1484 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
1485 76431533 Guido Trotter
1486 b73f1c59 Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1487 839642c2 Iustin Pop
    """Execute a KVM cmd, after completing it with some last minute data.
1488 ee5f20b0 Guido Trotter

1489 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1490 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1491 b73f1c59 Guido Trotter
    @type kvmhelp: string
1492 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1493 30e42c4e Guido Trotter

1494 ee5f20b0 Guido Trotter
    """
1495 297e6e53 Guido Trotter
    # Small _ExecuteKVMRuntime hv parameters programming howto:
1496 297e6e53 Guido Trotter
    #  - conf_hvp contains the parameters as configured on ganeti. they might
1497 297e6e53 Guido Trotter
    #    have changed since the instance started; only use them if the change
1498 297e6e53 Guido Trotter
    #    won't affect the inside of the instance (which hasn't been rebooted).
1499 297e6e53 Guido Trotter
    #  - up_hvp contains the parameters as they were when the instance was
1500 297e6e53 Guido Trotter
    #    started, plus any new parameter which has been added between ganeti
1501 297e6e53 Guido Trotter
    #    versions: it is paramount that those default to a value which won't
1502 297e6e53 Guido Trotter
    #    affect the inside of the instance as well.
1503 297e6e53 Guido Trotter
    conf_hvp = instance.hvparams
1504 5905901c Iustin Pop
    name = instance.name
1505 5905901c Iustin Pop
    self._CheckDown(name)
1506 ee5f20b0 Guido Trotter
1507 ee5f20b0 Guido Trotter
    temp_files = []
1508 ee5f20b0 Guido Trotter
1509 297e6e53 Guido Trotter
    kvm_cmd, kvm_nics, up_hvp = kvm_runtime
1510 f0db563d Guido Trotter
    # the first element of kvm_cmd is always the path to the kvm binary
1511 f0db563d Guido Trotter
    kvm_path = kvm_cmd[0]
1512 297e6e53 Guido Trotter
    up_hvp = objects.FillDict(conf_hvp, up_hvp)
1513 ee5f20b0 Guido Trotter
1514 297e6e53 Guido Trotter
    # We know it's safe to run as a different user upon migration, so we'll use
1515 297e6e53 Guido Trotter
    # the latest conf, from conf_hvp.
1516 297e6e53 Guido Trotter
    security_model = conf_hvp[constants.HV_SECURITY_MODEL]
1517 cef34868 Guido Trotter
    if security_model == constants.HT_SM_USER:
1518 297e6e53 Guido Trotter
      kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
1519 cef34868 Guido Trotter
1520 839642c2 Iustin Pop
    keymap = conf_hvp[constants.HV_KEYMAP]
1521 839642c2 Iustin Pop
    if keymap:
1522 839642c2 Iustin Pop
      keymap_path = self._InstanceKeymapFile(name)
1523 839642c2 Iustin Pop
      # If a keymap file is specified, KVM won't use its internal defaults. By
1524 839642c2 Iustin Pop
      # first including the "en-us" layout, an error on loading the actual
1525 839642c2 Iustin Pop
      # layout (e.g. because it can't be found) won't lead to a non-functional
1526 839642c2 Iustin Pop
      # keyboard. A keyboard with incorrect keys is still better than none.
1527 839642c2 Iustin Pop
      utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
1528 839642c2 Iustin Pop
      kvm_cmd.extend(["-k", keymap_path])
1529 839642c2 Iustin Pop
1530 297e6e53 Guido Trotter
    # We have reasons to believe changing something like the nic driver/type
1531 297e6e53 Guido Trotter
    # upon migration won't exactly fly with the instance kernel, so for nic
1532 297e6e53 Guido Trotter
    # related parameters we'll use up_hvp
1533 5d9bfd87 Apollon Oikonomopoulos
    tapfds = []
1534 5d9bfd87 Apollon Oikonomopoulos
    taps = []
1535 ee5f20b0 Guido Trotter
    if not kvm_nics:
1536 fbe27e2b Guido Trotter
      kvm_cmd.extend(["-net", "none"])
1537 ee5f20b0 Guido Trotter
    else:
1538 5d9bfd87 Apollon Oikonomopoulos
      vnet_hdr = False
1539 fbe27e2b Guido Trotter
      tap_extra = ""
1540 297e6e53 Guido Trotter
      nic_type = up_hvp[constants.HV_NIC_TYPE]
1541 37f88dc6 Guido Trotter
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
1542 f0db563d Guido Trotter
        nic_model = self._VIRTIO
1543 f0db563d Guido Trotter
        try:
1544 f0db563d Guido Trotter
          devlist = self._GetKVMOutput(kvm_path, self._KVMOPT_DEVICELIST)
1545 f0db563d Guido Trotter
          if self._NEW_VIRTIO_RE.search(devlist):
1546 f0db563d Guido Trotter
            nic_model = self._VIRTIO_NET_PCI
1547 8a534fbe Stratos Psomdakis
            vnet_hdr = up_hvp[constants.HV_VNET_HDR]
1548 f0db563d Guido Trotter
        except errors.HypervisorError, _:
1549 f0db563d Guido Trotter
          # Older versions of kvm don't support DEVICE_LIST, but they don't
1550 f0db563d Guido Trotter
          # have new virtio syntax either.
1551 f0db563d Guido Trotter
          pass
1552 4b784cf8 Miguel Di Ciurcio Filho
1553 297e6e53 Guido Trotter
        if up_hvp[constants.HV_VHOST_NET]:
1554 3b59ec02 Guido Trotter
          # check for vhost_net support
1555 0ad7f5d8 Guido Trotter
          if self._VHOST_RE.search(kvmhelp):
1556 4b784cf8 Miguel Di Ciurcio Filho
            tap_extra = ",vhost=on"
1557 4b784cf8 Miguel Di Ciurcio Filho
          else:
1558 4b784cf8 Miguel Di Ciurcio Filho
            raise errors.HypervisorError("vhost_net is configured"
1559 5ae4945a Iustin Pop
                                         " but it is not available")
1560 37f88dc6 Guido Trotter
      else:
1561 4b784cf8 Miguel Di Ciurcio Filho
        nic_model = nic_type
1562 37f88dc6 Guido Trotter
1563 6f4070cd Guido Trotter
      kvm_supports_netdev = self._NETDEV_RE.search(kvmhelp)
1564 6f4070cd Guido Trotter
1565 ee5f20b0 Guido Trotter
      for nic_seq, nic in enumerate(kvm_nics):
1566 6f1e1921 Michael Hanselmann
        tapname, tapfd = _OpenTap(vnet_hdr=vnet_hdr)
1567 5d9bfd87 Apollon Oikonomopoulos
        tapfds.append(tapfd)
1568 5d9bfd87 Apollon Oikonomopoulos
        taps.append(tapname)
1569 6f4070cd Guido Trotter
        if kvm_supports_netdev:
1570 4b784cf8 Miguel Di Ciurcio Filho
          nic_val = "%s,mac=%s,netdev=netdev%s" % (nic_model, nic.mac, nic_seq)
1571 5d9bfd87 Apollon Oikonomopoulos
          tap_val = "type=tap,id=netdev%s,fd=%d%s" % (nic_seq, tapfd, tap_extra)
1572 4b784cf8 Miguel Di Ciurcio Filho
          kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
1573 4b784cf8 Miguel Di Ciurcio Filho
        else:
1574 049383d9 Adeodato Simo
          nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq,
1575 049383d9 Adeodato Simo
                                                         nic.mac, nic_model)
1576 5d9bfd87 Apollon Oikonomopoulos
          tap_val = "tap,vlan=%s,fd=%d" % (nic_seq, tapfd)
1577 4b784cf8 Miguel Di Ciurcio Filho
          kvm_cmd.extend(["-net", tap_val, "-net", nic_val])
1578 ee5f20b0 Guido Trotter
1579 30e42c4e Guido Trotter
    if incoming:
1580 30e42c4e Guido Trotter
      target, port = incoming
1581 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])
1582 30e42c4e Guido Trotter
1583 297e6e53 Guido Trotter
    # Changing the vnc password doesn't bother the guest that much. At most it
1584 297e6e53 Guido Trotter
    # will surprise people who connect to it. Whether positively or negatively
1585 297e6e53 Guido Trotter
    # it's debatable.
1586 297e6e53 Guido Trotter
    vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
1587 6e6bb8d5 Guido Trotter
    vnc_pwd = None
1588 6e6bb8d5 Guido Trotter
    if vnc_pwd_file:
1589 6e6bb8d5 Guido Trotter
      try:
1590 682f7601 Guido Trotter
        vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
1591 6e6bb8d5 Guido Trotter
      except EnvironmentError, err:
1592 6e6bb8d5 Guido Trotter
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
1593 6e6bb8d5 Guido Trotter
                                     % (vnc_pwd_file, err))
1594 6e6bb8d5 Guido Trotter
1595 297e6e53 Guido Trotter
    if conf_hvp[constants.HV_KVM_USE_CHROOT]:
1596 547a63b7 Balazs Lecz
      utils.EnsureDirs([(self._InstanceChrootDir(name),
1597 547a63b7 Balazs Lecz
                         constants.SECURE_DIR_MODE)])
1598 547a63b7 Balazs Lecz
1599 91c10532 Andrea Spadaccini
    # Automatically enable QMP if version is >= 0.14
1600 0ad7f5d8 Guido Trotter
    if self._QMP_RE.search(kvmhelp):
1601 91c10532 Andrea Spadaccini
      logging.debug("Enabling QMP")
1602 91c10532 Andrea Spadaccini
      kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
1603 5ae4945a Iustin Pop
                      self._InstanceQmpMonitor(instance.name)])
1604 91c10532 Andrea Spadaccini
1605 cc8a8ed7 Apollon Oikonomopoulos
    # Configure the network now for starting instances and bridged interfaces,
1606 cc8a8ed7 Apollon Oikonomopoulos
    # during FinalizeMigration for incoming instances' routed interfaces
1607 cc8a8ed7 Apollon Oikonomopoulos
    for nic_seq, nic in enumerate(kvm_nics):
1608 cc8a8ed7 Apollon Oikonomopoulos
      if (incoming and
1609 cc8a8ed7 Apollon Oikonomopoulos
          nic.nicparams[constants.NIC_MODE] != constants.NIC_MODE_BRIDGED):
1610 cc8a8ed7 Apollon Oikonomopoulos
        continue
1611 cc8a8ed7 Apollon Oikonomopoulos
      self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
1612 5d9bfd87 Apollon Oikonomopoulos
1613 1d8a7812 Andrea Spadaccini
    # CPU affinity requires kvm to start paused, so we set this flag if the
1614 1d8a7812 Andrea Spadaccini
    # instance is not already paused and if we are not going to accept a
1615 1d8a7812 Andrea Spadaccini
    # migrating instance. In the latter case, pausing is not needed.
1616 1d8a7812 Andrea Spadaccini
    start_kvm_paused = not (_KVM_START_PAUSED_FLAG in kvm_cmd) and not incoming
1617 945a7e67 Guido Trotter
    if start_kvm_paused:
1618 945a7e67 Guido Trotter
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1619 b693125f Tsachy Shacham
1620 b693125f Tsachy Shacham
    # Note: CPU pinning is using up_hvp since changes take effect
1621 b693125f Tsachy Shacham
    # during instance startup anyway, and to avoid problems when soft
1622 b693125f Tsachy Shacham
    # rebooting the instance.
1623 c607b1f7 Tsachy Shacham
    cpu_pinning = False
1624 b693125f Tsachy Shacham
    if up_hvp.get(constants.HV_CPU_MASK, None):
1625 b693125f Tsachy Shacham
      cpu_pinning = True
1626 b693125f Tsachy Shacham
1627 76431533 Guido Trotter
    if security_model == constants.HT_SM_POOL:
1628 76431533 Guido Trotter
      ss = ssconf.SimpleStore()
1629 76431533 Guido Trotter
      uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
1630 76431533 Guido Trotter
      all_uids = set(uidpool.ExpandUidPool(uid_pool))
1631 76431533 Guido Trotter
      uid = uidpool.RequestUnusedUid(all_uids)
1632 76431533 Guido Trotter
      try:
1633 76431533 Guido Trotter
        username = pwd.getpwuid(uid.GetUid()).pw_name
1634 76431533 Guido Trotter
        kvm_cmd.extend(["-runas", username])
1635 5d9bfd87 Apollon Oikonomopoulos
        self._RunKVMCmd(name, kvm_cmd, tapfds)
1636 76431533 Guido Trotter
      except:
1637 76431533 Guido Trotter
        uidpool.ReleaseUid(uid)
1638 76431533 Guido Trotter
        raise
1639 76431533 Guido Trotter
      else:
1640 76431533 Guido Trotter
        uid.Unlock()
1641 3af16328 Apollon Oikonomopoulos
        utils.WriteFile(self._InstanceUidFile(name), data=uid.AsStr())
1642 76431533 Guido Trotter
    else:
1643 5d9bfd87 Apollon Oikonomopoulos
      self._RunKVMCmd(name, kvm_cmd, tapfds)
1644 5d9bfd87 Apollon Oikonomopoulos
1645 5d9bfd87 Apollon Oikonomopoulos
    utils.EnsureDirs([(self._InstanceNICDir(instance.name),
1646 5d9bfd87 Apollon Oikonomopoulos
                     constants.RUN_DIRS_MODE)])
1647 5d9bfd87 Apollon Oikonomopoulos
    for nic_seq, tap in enumerate(taps):
1648 5d9bfd87 Apollon Oikonomopoulos
      utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
1649 5d9bfd87 Apollon Oikonomopoulos
                      data=tap)
1650 eb58f9b1 Guido Trotter
1651 6e6bb8d5 Guido Trotter
    if vnc_pwd:
1652 d0c8c01d Iustin Pop
      change_cmd = "change vnc password %s" % vnc_pwd
1653 6e6bb8d5 Guido Trotter
      self._CallMonitorCommand(instance.name, change_cmd)
1654 6e6bb8d5 Guido Trotter
1655 b451c4c7 Andrea Spadaccini
    # Setting SPICE password. We are not vulnerable to malicious passwordless
1656 b451c4c7 Andrea Spadaccini
    # connection attempts because SPICE by default does not allow connections
1657 b451c4c7 Andrea Spadaccini
    # if neither a password nor the "disable_ticketing" options are specified.
1658 b451c4c7 Andrea Spadaccini
    # As soon as we send the password via QMP, that password is a valid ticket
1659 b451c4c7 Andrea Spadaccini
    # for connection.
1660 b451c4c7 Andrea Spadaccini
    spice_password_file = conf_hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]
1661 b451c4c7 Andrea Spadaccini
    if spice_password_file:
1662 fc84cd5d Guido Trotter
      spice_pwd = ""
1663 b451c4c7 Andrea Spadaccini
      try:
1664 b451c4c7 Andrea Spadaccini
        spice_pwd = utils.ReadOneLineFile(spice_password_file, strict=True)
1665 b451c4c7 Andrea Spadaccini
      except EnvironmentError, err:
1666 b451c4c7 Andrea Spadaccini
        raise errors.HypervisorError("Failed to open SPICE password file %s: %s"
1667 b451c4c7 Andrea Spadaccini
                                     % (spice_password_file, err))
1668 b451c4c7 Andrea Spadaccini
1669 fc84cd5d Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
1670 fc84cd5d Guido Trotter
      qmp.connect()
1671 fc84cd5d Guido Trotter
      arguments = {
1672 fc84cd5d Guido Trotter
          "protocol": "spice",
1673 fc84cd5d Guido Trotter
          "password": spice_pwd,
1674 fc84cd5d Guido Trotter
      }
1675 fc84cd5d Guido Trotter
      qmp.Execute("set_password", arguments)
1676 fc84cd5d Guido Trotter
1677 08137f9e Iustin Pop
    for filename in temp_files:
1678 08137f9e Iustin Pop
      utils.RemoveFile(filename)
1679 eb58f9b1 Guido Trotter
1680 b693125f Tsachy Shacham
    # If requested, set CPU affinity and resume instance execution
1681 b693125f Tsachy Shacham
    if cpu_pinning:
1682 945a7e67 Guido Trotter
      self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK])
1683 945a7e67 Guido Trotter
1684 61eb1a46 Guido Trotter
    start_memory = self._InstanceStartupMemory(instance)
1685 61eb1a46 Guido Trotter
    if start_memory < instance.beparams[constants.BE_MAXMEM]:
1686 61eb1a46 Guido Trotter
      self.BalloonInstanceMemory(instance, start_memory)
1687 61eb1a46 Guido Trotter
1688 945a7e67 Guido Trotter
    if start_kvm_paused:
1689 2ed0e208 Iustin Pop
      # To control CPU pinning, ballooning, and vnc/spice passwords
1690 2ed0e208 Iustin Pop
      # the VM was started in a frozen state. If freezing was not
1691 2ed0e208 Iustin Pop
      # explicitly requested resume the vm status.
1692 945a7e67 Guido Trotter
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1693 b693125f Tsachy Shacham
1694 323f9095 Stephen Shirley
  def StartInstance(self, instance, block_devices, startup_paused):
1695 ee5f20b0 Guido Trotter
    """Start an instance.
1696 ee5f20b0 Guido Trotter

1697 ee5f20b0 Guido Trotter
    """
1698 5905901c Iustin Pop
    self._CheckDown(instance.name)
1699 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1700 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1701 7238edb5 Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1702 b73f1c59 Guido Trotter
                                           startup_paused, kvmhelp)
1703 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1704 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1705 ee5f20b0 Guido Trotter
1706 2a2d087a Michele Tartara
  def _CallMonitorCommand(self, instance_name, command, timeout=None):
1707 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
1708 6567aff3 Guido Trotter

1709 6567aff3 Guido Trotter
    """
1710 2a2d087a Michele Tartara
    if timeout is not None:
1711 2a2d087a Michele Tartara
      timeout_cmd = "timeout %s" % (timeout, )
1712 2a2d087a Michele Tartara
    else:
1713 2a2d087a Michele Tartara
      timeout_cmd = ""
1714 2a2d087a Michele Tartara
1715 eace6157 Michael Hanselmann
    # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
1716 eace6157 Michael Hanselmann
    # version. The monitor protocol is designed for human consumption, whereas
1717 eace6157 Michael Hanselmann
    # QMP is made for programmatic usage. In the worst case QMP can also
1718 eace6157 Michael Hanselmann
    # execute monitor commands. As it is, all calls to socat take at least
1719 eace6157 Michael Hanselmann
    # 500ms and likely more: socat can't detect the end of the reply and waits
1720 eace6157 Michael Hanselmann
    # for 500ms of no data received before exiting (500 ms is the default for
1721 eace6157 Michael Hanselmann
    # the "-t" parameter).
1722 874f6148 Michele Tartara
    socat = ("echo %s | %s %s STDIO UNIX-CONNECT:%s" %
1723 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
1724 874f6148 Michele Tartara
              timeout_cmd,
1725 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
1726 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1727 874f6148 Michele Tartara
1728 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
1729 6567aff3 Guido Trotter
    if result.failed:
1730 afa9bb2e Michael Hanselmann
      msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
1731 afa9bb2e Michael Hanselmann
             " output: %s" %
1732 afa9bb2e Michael Hanselmann
             (command, instance_name, result.fail_reason, result.output))
1733 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
1734 6567aff3 Guido Trotter
1735 6567aff3 Guido Trotter
    return result
1736 6567aff3 Guido Trotter
1737 b52d85c1 Guido Trotter
  @classmethod
1738 585c8187 Guido Trotter
  def _ParseKVMVersion(cls, text):
1739 585c8187 Guido Trotter
    """Parse the KVM version from the --help output.
1740 585c8187 Guido Trotter

1741 585c8187 Guido Trotter
    @type text: string
1742 585c8187 Guido Trotter
    @param text: output of kvm --help
1743 585c8187 Guido Trotter
    @return: (version, v_maj, v_min, v_rev)
1744 5c3d5dfd Iustin Pop
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1745 585c8187 Guido Trotter

1746 585c8187 Guido Trotter
    """
1747 585c8187 Guido Trotter
    match = cls._VERSION_RE.search(text.splitlines()[0])
1748 585c8187 Guido Trotter
    if not match:
1749 585c8187 Guido Trotter
      raise errors.HypervisorError("Unable to get KVM version")
1750 585c8187 Guido Trotter
1751 585c8187 Guido Trotter
    v_all = match.group(0)
1752 585c8187 Guido Trotter
    v_maj = int(match.group(1))
1753 585c8187 Guido Trotter
    v_min = int(match.group(2))
1754 585c8187 Guido Trotter
    if match.group(4):
1755 585c8187 Guido Trotter
      v_rev = int(match.group(4))
1756 585c8187 Guido Trotter
    else:
1757 585c8187 Guido Trotter
      v_rev = 0
1758 585c8187 Guido Trotter
    return (v_all, v_maj, v_min, v_rev)
1759 585c8187 Guido Trotter
1760 585c8187 Guido Trotter
  @classmethod
1761 6e043e60 Guido Trotter
  def _GetKVMOutput(cls, kvm_path, option):
1762 6e043e60 Guido Trotter
    """Return the output of a kvm invocation
1763 e3b89628 Guido Trotter

1764 bc0fed4b Guido Trotter
    @type kvm_path: string
1765 bc0fed4b Guido Trotter
    @param kvm_path: path to the kvm executable
1766 bc0fed4b Guido Trotter
    @type option: a key of _KVMOPTS_CMDS
1767 bc0fed4b Guido Trotter
    @param option: kvm option to fetch the output from
1768 6e043e60 Guido Trotter
    @return: output a supported kvm invocation
1769 e3b89628 Guido Trotter
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
1770 e3b89628 Guido Trotter

1771 e3b89628 Guido Trotter
    """
1772 6e043e60 Guido Trotter
    assert option in cls._KVMOPTS_CMDS, "Invalid output option"
1773 6e043e60 Guido Trotter
1774 bc0fed4b Guido Trotter
    optlist, can_fail = cls._KVMOPTS_CMDS[option]
1775 bc0fed4b Guido Trotter
1776 bc0fed4b Guido Trotter
    result = utils.RunCmd([kvm_path] + optlist)
1777 bc0fed4b Guido Trotter
    if result.failed and not can_fail:
1778 af89fa76 Helga Velroyen
      raise errors.HypervisorError("Unable to get KVM %s output" %
1779 3ddc7650 Jose A. Lopes
                                    " ".join(optlist))
1780 e3b89628 Guido Trotter
    return result.output
1781 e3b89628 Guido Trotter
1782 e3b89628 Guido Trotter
  @classmethod
1783 3b59ec02 Guido Trotter
  def _GetKVMVersion(cls, kvm_path):
1784 d7e4a2b1 Andrea Spadaccini
    """Return the installed KVM version.
1785 b52d85c1 Guido Trotter

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

1789 b52d85c1 Guido Trotter
    """
1790 6e043e60 Guido Trotter
    return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
1791 82e3bf85 Dimitris Aragiorgis
1792 82e3bf85 Dimitris Aragiorgis
  @classmethod
1793 82e3bf85 Dimitris Aragiorgis
  def _GetDefaultMachineVersion(cls, kvm_path):
1794 82e3bf85 Dimitris Aragiorgis
    """Return the default hardware revision (e.g. pc-1.1)
1795 82e3bf85 Dimitris Aragiorgis

1796 82e3bf85 Dimitris Aragiorgis
    """
1797 6e043e60 Guido Trotter
    output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
1798 82e3bf85 Dimitris Aragiorgis
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
1799 82e3bf85 Dimitris Aragiorgis
    if match:
1800 82e3bf85 Dimitris Aragiorgis
      return match.group(1)
1801 82e3bf85 Dimitris Aragiorgis
    else:
1802 82e3bf85 Dimitris Aragiorgis
      return "pc"
1803 82e3bf85 Dimitris Aragiorgis
1804 874f6148 Michele Tartara
  def StopInstance(self, instance, force=False, retry=False, name=None,
1805 874f6148 Michele Tartara
                   timeout=None):
1806 eb58f9b1 Guido Trotter
    """Stop an instance.
1807 eb58f9b1 Guido Trotter

1808 eb58f9b1 Guido Trotter
    """
1809 874f6148 Michele Tartara
    assert(timeout is None or force is not None)
1810 874f6148 Michele Tartara
1811 bbcf7ad0 Iustin Pop
    if name is not None and not force:
1812 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
1813 bbcf7ad0 Iustin Pop
    if name is None:
1814 bbcf7ad0 Iustin Pop
      name = instance.name
1815 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
1816 bbcf7ad0 Iustin Pop
    else:
1817 bbcf7ad0 Iustin Pop
      acpi = False
1818 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
1819 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
1820 bbcf7ad0 Iustin Pop
      if force or not acpi:
1821 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
1822 eb58f9b1 Guido Trotter
      else:
1823 874f6148 Michele Tartara
        self._CallMonitorCommand(name, "system_powerdown", timeout)
1824 eb58f9b1 Guido Trotter
1825 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
1826 8904b35c Guido Trotter
    """Cleanup after a stopped instance
1827 8904b35c Guido Trotter

1828 8904b35c Guido Trotter
    """
1829 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1830 8904b35c Guido Trotter
    if pid > 0 and alive:
1831 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
1832 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1833 eb58f9b1 Guido Trotter
1834 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
1835 eb58f9b1 Guido Trotter
    """Reboot an instance.
1836 eb58f9b1 Guido Trotter

1837 eb58f9b1 Guido Trotter
    """
1838 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
1839 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
1840 eb58f9b1 Guido Trotter
    # to shutdown and restart.
1841 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
1842 1f8b3a27 Guido Trotter
    if not alive:
1843 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
1844 78411c60 Iustin Pop
                                   " not running" % instance.name)
1845 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
1846 f02881e0 Guido Trotter
    # ...first load it...
1847 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
1848 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
1849 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
1850 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
1851 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
1852 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1853 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1854 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1855 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1856 eb58f9b1 Guido Trotter
1857 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
1858 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
1859 30e42c4e Guido Trotter

1860 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1861 30e42c4e Guido Trotter
    @param instance: instance to be migrated
1862 30e42c4e Guido Trotter
    @rtype: string
1863 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
1864 30e42c4e Guido Trotter

1865 30e42c4e Guido Trotter
    """
1866 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
1867 30e42c4e Guido Trotter
1868 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
1869 30e42c4e Guido Trotter
    """Prepare to accept an instance.
1870 30e42c4e Guido Trotter

1871 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1872 30e42c4e Guido Trotter
    @param instance: instance to be accepted
1873 30e42c4e Guido Trotter
    @type info: string
1874 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
1875 30e42c4e Guido Trotter
    @type target: string
1876 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
1877 30e42c4e Guido Trotter

1878 30e42c4e Guido Trotter
    """
1879 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1880 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1881 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1882 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1883 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
1884 b73f1c59 Guido Trotter
                            incoming=incoming_address)
1885 30e42c4e Guido Trotter
1886 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
1887 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
1888 30e42c4e Guido Trotter

1889 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
1890 30e42c4e Guido Trotter

1891 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1892 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
1893 30e42c4e Guido Trotter

1894 30e42c4e Guido Trotter
    """
1895 30e42c4e Guido Trotter
    if success:
1896 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1897 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
1898 5d9bfd87 Apollon Oikonomopoulos
1899 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
1900 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1901 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
1902 cc8a8ed7 Apollon Oikonomopoulos
          continue
1903 5d9bfd87 Apollon Oikonomopoulos
        try:
1904 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
1905 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
1906 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
1907 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
1908 5d9bfd87 Apollon Oikonomopoulos
          continue
1909 5d9bfd87 Apollon Oikonomopoulos
        try:
1910 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
1911 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
1912 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
1913 5d9bfd87 Apollon Oikonomopoulos
1914 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
1915 30e42c4e Guido Trotter
    else:
1916 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
1917 30e42c4e Guido Trotter
1918 bc0a2284 Helga Velroyen
  def MigrateInstance(self, cluster_name, instance, target, live):
1919 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
1920 30e42c4e Guido Trotter

1921 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
1922 30e42c4e Guido Trotter
    currently running.
1923 30e42c4e Guido Trotter

1924 bc0a2284 Helga Velroyen
    @type cluster_name: string
1925 bc0a2284 Helga Velroyen
    @param cluster_name: name of the cluster
1926 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
1927 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
1928 30e42c4e Guido Trotter
    @type target: string
1929 30e42c4e Guido Trotter
    @param target: ip address of the target node
1930 30e42c4e Guido Trotter
    @type live: boolean
1931 30e42c4e Guido Trotter
    @param live: perform a live migration
1932 30e42c4e Guido Trotter

1933 30e42c4e Guido Trotter
    """
1934 58d38b02 Iustin Pop
    instance_name = instance.name
1935 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
1936 6a1434d7 Andrea Spadaccini
    _, _, alive = self._InstancePidAlive(instance_name)
1937 30e42c4e Guido Trotter
    if not alive:
1938 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
1939 30e42c4e Guido Trotter
1940 30e42c4e Guido Trotter
    if not live:
1941 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
1942 30e42c4e Guido Trotter
1943 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
1944 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1945 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
1946 e43d4f9f Apollon Oikonomopoulos
1947 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
1948 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
1949 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
1950 e43d4f9f Apollon Oikonomopoulos
1951 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
1952 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
1953 30e42c4e Guido Trotter
1954 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
1955 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
1956 6a1434d7 Andrea Spadaccini

1957 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
1958 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
1959 6a1434d7 Andrea Spadaccini
    @type success: bool
1960 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
1961 6a1434d7 Andrea Spadaccini
    @type live: bool
1962 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
1963 6a1434d7 Andrea Spadaccini

1964 6a1434d7 Andrea Spadaccini
    """
1965 6a1434d7 Andrea Spadaccini
    if success:
1966 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
1967 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
1968 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
1969 6a1434d7 Andrea Spadaccini
    elif live:
1970 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1971 6a1434d7 Andrea Spadaccini
1972 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
1973 6a1434d7 Andrea Spadaccini
    """Get the migration status
1974 6a1434d7 Andrea Spadaccini

1975 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
1976 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
1977 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
1978 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
1979 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
1980 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
1981 6a1434d7 Andrea Spadaccini

1982 6a1434d7 Andrea Spadaccini
    """
1983 d0c8c01d Iustin Pop
    info_command = "info migrate"
1984 6a1434d7 Andrea Spadaccini
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
1985 6a1434d7 Andrea Spadaccini
      result = self._CallMonitorCommand(instance.name, info_command)
1986 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
1987 30e42c4e Guido Trotter
      if not match:
1988 c4e388a5 Guido Trotter
        if not result.stdout:
1989 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
1990 c4e388a5 Guido Trotter
        else:
1991 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
1992 c4e388a5 Guido Trotter
                          result.stdout)
1993 30e42c4e Guido Trotter
      else:
1994 30e42c4e Guido Trotter
        status = match.group(1)
1995 6a1434d7 Andrea Spadaccini
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
1996 6a1434d7 Andrea Spadaccini
          migration_status = objects.MigrationStatus(status=status)
1997 61643226 Andrea Spadaccini
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
1998 61643226 Andrea Spadaccini
          if match:
1999 61643226 Andrea Spadaccini
            migration_status.transferred_ram = match.group("transferred")
2000 61643226 Andrea Spadaccini
            migration_status.total_ram = match.group("total")
2001 61643226 Andrea Spadaccini
2002 6a1434d7 Andrea Spadaccini
          return migration_status
2003 30e42c4e Guido Trotter
2004 6a1434d7 Andrea Spadaccini
        logging.warning("KVM: unknown migration status '%s'", status)
2005 6a1434d7 Andrea Spadaccini
2006 6a1434d7 Andrea Spadaccini
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
2007 6a1434d7 Andrea Spadaccini
2008 62457f51 Iustin Pop
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
2009 30e42c4e Guido Trotter
2010 3d836750 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
2011 3d836750 Guido Trotter
    """Balloon an instance memory to a certain value.
2012 3d836750 Guido Trotter

2013 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
2014 3d836750 Guido Trotter
    @param instance: instance to be accepted
2015 3d836750 Guido Trotter
    @type mem: int
2016 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
2017 3d836750 Guido Trotter

2018 3d836750 Guido Trotter
    """
2019 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2020 3d836750 Guido Trotter
2021 fac489a5 Helga Velroyen
  def GetNodeInfo(self, hvparams=None):
2022 eb58f9b1 Guido Trotter
    """Return information about the node.
2023 eb58f9b1 Guido Trotter

2024 fac489a5 Helga Velroyen
    @type hvparams: dict of strings
2025 fac489a5 Helga Velroyen
    @param hvparams: hypervisor parameters, not used in this class
2026 fac489a5 Helga Velroyen

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

2032 eb58f9b1 Guido Trotter
    """
2033 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
2034 25bce647 Santi Raffa
    kvmpath = constants.KVM_PATH
2035 25bce647 Santi Raffa
    if hvparams is not None:
2036 25bce647 Santi Raffa
      kvmpath = hvparams.get(constants.HV_KVM_PATH, constants.KVM_PATH)
2037 25bce647 Santi Raffa
    _, v_major, v_min, v_rev = self._GetKVMVersion(kvmpath)
2038 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2039 34fbc862 Andrea Spadaccini
    return result
2040 eb58f9b1 Guido Trotter
2041 637ce7f9 Guido Trotter
  @classmethod
2042 1c3231aa Thomas Thrainer
  def GetInstanceConsole(cls, instance, primary_node, hvparams, beparams):
2043 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
2044 eb58f9b1 Guido Trotter

2045 eb58f9b1 Guido Trotter
    """
2046 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2047 9d9bded1 Michael Hanselmann
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2048 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2049 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2050 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
2051 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2052 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2053 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
2054 1c3231aa Thomas Thrainer
                                     host=primary_node.name,
2055 052783ff Michael Hanselmann
                                     user=constants.SSH_CONSOLE_USER,
2056 55cc0a44 Michael Hanselmann
                                     command=cmd)
2057 3be34f57 Guido Trotter
2058 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2059 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2060 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
2061 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2062 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
2063 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
2064 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
2065 55cc0a44 Michael Hanselmann
                                     display=display)
2066 55cc0a44 Michael Hanselmann
2067 4d2cdb5a Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2068 4d2cdb5a Andrea Spadaccini
    if spice_bind:
2069 4d2cdb5a Andrea Spadaccini
      return objects.InstanceConsole(instance=instance.name,
2070 4d2cdb5a Andrea Spadaccini
                                     kind=constants.CONS_SPICE,
2071 4d2cdb5a Andrea Spadaccini
                                     host=spice_bind,
2072 4d2cdb5a Andrea Spadaccini
                                     port=instance.network_port)
2073 4d2cdb5a Andrea Spadaccini
2074 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
2075 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
2076 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
2077 55cc0a44 Michael Hanselmann
                                            instance.name))
2078 eb58f9b1 Guido Trotter
2079 75bf3149 Helga Velroyen
  def Verify(self, hvparams=None):
2080 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
2081 eb58f9b1 Guido Trotter

2082 cd04dfd2 Michael Hanselmann
    Check that the required binaries exist.
2083 cd04dfd2 Michael Hanselmann

2084 75bf3149 Helga Velroyen
    @type hvparams: dict of strings
2085 75bf3149 Helga Velroyen
    @param hvparams: hypervisor parameters to be verified against, not used here
2086 75bf3149 Helga Velroyen

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

2089 eb58f9b1 Guido Trotter
    """
2090 1f4b9d39 Iustin Pop
    msgs = []
2091 25bce647 Santi Raffa
    kvmpath = constants.KVM_PATH
2092 25bce647 Santi Raffa
    if hvparams is not None:
2093 25bce647 Santi Raffa
      kvmpath = hvparams.get(constants.HV_KVM_PATH, constants.KVM_PATH)
2094 25bce647 Santi Raffa
    if not os.path.exists(kvmpath):
2095 25bce647 Santi Raffa
      msgs.append("The KVM binary ('%s') does not exist" % kvmpath)
2096 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2097 1f4b9d39 Iustin Pop
      msgs.append("The socat binary ('%s') does not exist" %
2098 1f4b9d39 Iustin Pop
                  constants.SOCAT_PATH)
2099 1f4b9d39 Iustin Pop
2100 1f4b9d39 Iustin Pop
    return self._FormatVerifyResults(msgs)
2101 14aa53cb Guido Trotter
2102 6b5605e8 Iustin Pop
  @classmethod
2103 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2104 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2105 6b5605e8 Iustin Pop

2106 6b5605e8 Iustin Pop
    @type hvparams:  dict
2107 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2108 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2109 6b5605e8 Iustin Pop

2110 6b5605e8 Iustin Pop
    """
2111 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2112 6b5605e8 Iustin Pop
2113 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
2114 df5ab9f0 Guido Trotter
    if kernel_path:
2115 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
2116 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
2117 205ab586 Iustin Pop
                                     " if a kernel is defined")
2118 6b5605e8 Iustin Pop
2119 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
2120 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
2121 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
2122 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
2123 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
2124 66d5dbef Guido Trotter
2125 14fd6c81 Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2126 14fd6c81 Guido Trotter
      serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2127 14fd6c81 Guido Trotter
      valid_speeds = constants.VALID_SERIAL_SPEEDS
2128 14fd6c81 Guido Trotter
      if not serial_speed or serial_speed not in valid_speeds:
2129 14fd6c81 Guido Trotter
        raise errors.HypervisorError("Invalid serial console speed, must be"
2130 14fd6c81 Guido Trotter
                                     " one of: %s" %
2131 14fd6c81 Guido Trotter
                                     utils.CommaJoin(valid_speeds))
2132 14fd6c81 Guido Trotter
2133 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2134 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
2135 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2136 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2137 835528af Iustin Pop
                                   " ISO path")
2138 f5118ade Iustin Pop
2139 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2140 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2141 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
2142 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
2143 d19d94db Guido Trotter
                                     " must be specified")
2144 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
2145 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
2146 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
2147 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
2148 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
2149 d19d94db Guido Trotter
2150 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2151 b451c4c7 Andrea Spadaccini
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2152 b1cb62bd Andrea Spadaccini
    if spice_bind:
2153 b1cb62bd Andrea Spadaccini
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2154 b1cb62bd Andrea Spadaccini
        # if an IP version is specified, the spice_bind parameter must be an
2155 b1cb62bd Andrea Spadaccini
        # IP of that family
2156 b1cb62bd Andrea Spadaccini
        if (netutils.IP4Address.IsValid(spice_bind) and
2157 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP4_VERSION):
2158 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv4 address (%s), but"
2159 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2160 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2161 b1cb62bd Andrea Spadaccini
2162 b1cb62bd Andrea Spadaccini
        if (netutils.IP6Address.IsValid(spice_bind) and
2163 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP6_VERSION):
2164 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: Got an IPv6 address (%s), but"
2165 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2166 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2167 b451c4c7 Andrea Spadaccini
    else:
2168 0e1b03b9 Andrea Spadaccini
      # All the other SPICE parameters depend on spice_bind being set. Raise an
2169 0e1b03b9 Andrea Spadaccini
      # error if any of them is set without it.
2170 07788a0b Michael Hanselmann
      for param in _SPICE_ADDITIONAL_PARAMS:
2171 0e1b03b9 Andrea Spadaccini
        if hvparams[param]:
2172 afa9bb2e Michael Hanselmann
          raise errors.HypervisorError("SPICE: %s requires %s to be set" %
2173 0e1b03b9 Andrea Spadaccini
                                       (param, constants.HV_KVM_SPICE_BIND))
2174 b1cb62bd Andrea Spadaccini
2175 d19d94db Guido Trotter
  @classmethod
2176 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
2177 d19d94db Guido Trotter
    """Check the given parameters for validity.
2178 d19d94db Guido Trotter

2179 d19d94db Guido Trotter
    @type hvparams:  dict
2180 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2181 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2182 d19d94db Guido Trotter

2183 d19d94db Guido Trotter
    """
2184 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2185 d19d94db Guido Trotter
2186 82e3bf85 Dimitris Aragiorgis
    kvm_path = hvparams[constants.HV_KVM_PATH]
2187 82e3bf85 Dimitris Aragiorgis
2188 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2189 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2190 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2191 d19d94db Guido Trotter
      try:
2192 1feb39ec Guido Trotter
        pwd.getpwnam(username)
2193 d19d94db Guido Trotter
      except KeyError:
2194 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
2195 d19d94db Guido Trotter
                                     % username)
2196 d6e5767e Klaus Aehlig
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2197 d6e5767e Klaus Aehlig
    if vnc_bind_address:
2198 d6e5767e Klaus Aehlig
      bound_to_addr = netutils.IP4Address.IsValid(vnc_bind_address)
2199 d6e5767e Klaus Aehlig
      is_interface = netutils.IsValidInterface(vnc_bind_address)
2200 d6e5767e Klaus Aehlig
      is_path = utils.IsNormAbsPath(vnc_bind_address)
2201 d6e5767e Klaus Aehlig
      if not bound_to_addr and not is_interface and not is_path:
2202 d6e5767e Klaus Aehlig
        raise errors.HypervisorError("VNC: The %s parameter must be either"
2203 d6e5767e Klaus Aehlig
                                     " a valid IP address, an interface name,"
2204 d6e5767e Klaus Aehlig
                                     " or an absolute path" %
2205 d6e5767e Klaus Aehlig
                                     constants.HV_KVM_SPICE_BIND)
2206 d19d94db Guido Trotter
2207 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2208 b1cb62bd Andrea Spadaccini
    if spice_bind:
2209 b1cb62bd Andrea Spadaccini
      # only one of VNC and SPICE can be used currently.
2210 b1cb62bd Andrea Spadaccini
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2211 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("Both SPICE and VNC are configured, but"
2212 b1cb62bd Andrea Spadaccini
                                     " only one of them can be used at a"
2213 afa9bb2e Michael Hanselmann
                                     " given time")
2214 b1cb62bd Andrea Spadaccini
2215 3b59ec02 Guido Trotter
      # check that KVM supports SPICE
2216 6e043e60 Guido Trotter
      kvmhelp = cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP)
2217 0ad7f5d8 Guido Trotter
      if not cls._SPICE_RE.search(kvmhelp):
2218 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE is configured, but it is not"
2219 afa9bb2e Michael Hanselmann
                                     " supported according to 'kvm --help'")
2220 b1cb62bd Andrea Spadaccini
2221 b1cb62bd Andrea Spadaccini
      # if spice_bind is not an IP address, it must be a valid interface
2222 afa9bb2e Michael Hanselmann
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind) or
2223 afa9bb2e Michael Hanselmann
                       netutils.IP6Address.IsValid(spice_bind))
2224 b1cb62bd Andrea Spadaccini
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2225 afa9bb2e Michael Hanselmann
        raise errors.HypervisorError("SPICE: The %s parameter must be either"
2226 b1cb62bd Andrea Spadaccini
                                     " a valid IP address or interface name" %
2227 b1cb62bd Andrea Spadaccini
                                     constants.HV_KVM_SPICE_BIND)
2228 b1cb62bd Andrea Spadaccini
2229 82e3bf85 Dimitris Aragiorgis
    machine_version = hvparams[constants.HV_KVM_MACHINE_VERSION]
2230 82e3bf85 Dimitris Aragiorgis
    if machine_version:
2231 6e043e60 Guido Trotter
      output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2232 82e3bf85 Dimitris Aragiorgis
      if not cls._CHECK_MACHINE_VERSION_RE(machine_version).search(output):
2233 82e3bf85 Dimitris Aragiorgis
        raise errors.HypervisorError("Unsupported machine version: %s" %
2234 82e3bf85 Dimitris Aragiorgis
                                     machine_version)
2235 82e3bf85 Dimitris Aragiorgis
2236 f5118ade Iustin Pop
  @classmethod
2237 8ef418bb Helga Velroyen
  def PowercycleNode(cls, hvparams=None):
2238 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
2239 f5118ade Iustin Pop

2240 8ef418bb Helga Velroyen
    @type hvparams: dict of strings
2241 8ef418bb Helga Velroyen
    @param hvparams: hypervisor params to be used on this node
2242 8ef418bb Helga Velroyen

2243 f5118ade Iustin Pop
    """
2244 f5118ade Iustin Pop
    cls.LinuxPowercycle()