Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 78f99abb

History | View | Annotate | Download (81.4 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 91c10532 Andrea Spadaccini
  @staticmethod
198 91c10532 Andrea Spadaccini
  def BuildFromJsonString(json_string):
199 91c10532 Andrea Spadaccini
    """Build a QmpMessage from a JSON encoded string.
200 91c10532 Andrea Spadaccini

201 91c10532 Andrea Spadaccini
    @type json_string: str
202 91c10532 Andrea Spadaccini
    @param json_string: JSON string representing the message
203 91c10532 Andrea Spadaccini
    @rtype: L{QmpMessage}
204 91c10532 Andrea Spadaccini
    @return: a L{QmpMessage} built from json_string
205 91c10532 Andrea Spadaccini

206 91c10532 Andrea Spadaccini
    """
207 91c10532 Andrea Spadaccini
    # Parse the string
208 91c10532 Andrea Spadaccini
    data = serializer.LoadJson(json_string)
209 91c10532 Andrea Spadaccini
    return QmpMessage(data)
210 91c10532 Andrea Spadaccini
211 91c10532 Andrea Spadaccini
  def __str__(self):
212 a182a3ed Michael Hanselmann
    # The protocol expects the JSON object to be sent as a single line.
213 a182a3ed Michael Hanselmann
    return serializer.DumpJson(self.data)
214 91c10532 Andrea Spadaccini
215 91c10532 Andrea Spadaccini
  def __eq__(self, other):
216 91c10532 Andrea Spadaccini
    # When comparing two QmpMessages, we are interested in comparing
217 91c10532 Andrea Spadaccini
    # their internal representation of the message data
218 91c10532 Andrea Spadaccini
    return self.data == other.data
219 91c10532 Andrea Spadaccini
220 91c10532 Andrea Spadaccini
221 91c10532 Andrea Spadaccini
class QmpConnection:
222 91c10532 Andrea Spadaccini
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
223 91c10532 Andrea Spadaccini

224 91c10532 Andrea Spadaccini
  """
225 91c10532 Andrea Spadaccini
  _FIRST_MESSAGE_KEY = "QMP"
226 91c10532 Andrea Spadaccini
  _EVENT_KEY = "event"
227 91c10532 Andrea Spadaccini
  _ERROR_KEY = "error"
228 89da2ff3 Guido Trotter
  _RETURN_KEY = RETURN_KEY = "return"
229 89da2ff3 Guido Trotter
  _ACTUAL_KEY = ACTUAL_KEY = "actual"
230 91c10532 Andrea Spadaccini
  _ERROR_CLASS_KEY = "class"
231 91c10532 Andrea Spadaccini
  _ERROR_DATA_KEY = "data"
232 91c10532 Andrea Spadaccini
  _ERROR_DESC_KEY = "desc"
233 91c10532 Andrea Spadaccini
  _EXECUTE_KEY = "execute"
234 91c10532 Andrea Spadaccini
  _ARGUMENTS_KEY = "arguments"
235 91c10532 Andrea Spadaccini
  _CAPABILITIES_COMMAND = "qmp_capabilities"
236 91c10532 Andrea Spadaccini
  _MESSAGE_END_TOKEN = "\r\n"
237 91c10532 Andrea Spadaccini
  _SOCKET_TIMEOUT = 5
238 91c10532 Andrea Spadaccini
239 91c10532 Andrea Spadaccini
  def __init__(self, monitor_filename):
240 91c10532 Andrea Spadaccini
    """Instantiates the QmpConnection object.
241 91c10532 Andrea Spadaccini

242 91c10532 Andrea Spadaccini
    @type monitor_filename: string
243 91c10532 Andrea Spadaccini
    @param monitor_filename: the filename of the UNIX raw socket on which the
244 91c10532 Andrea Spadaccini
                             QMP monitor is listening
245 91c10532 Andrea Spadaccini

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

271 91c10532 Andrea Spadaccini
    """
272 91c10532 Andrea Spadaccini
    if not self._connected:
273 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("To use a QmpConnection you need to first"
274 91c10532 Andrea Spadaccini
                                   " invoke connect() on it")
275 91c10532 Andrea Spadaccini
276 91c10532 Andrea Spadaccini
  def connect(self):
277 91c10532 Andrea Spadaccini
    """Connects to the QMP monitor.
278 91c10532 Andrea Spadaccini

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

282 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
283 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
284 91c10532 Andrea Spadaccini

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

314 91c10532 Andrea Spadaccini
    Seeks for a QMP message in the given buf. If found, it parses it and
315 91c10532 Andrea Spadaccini
    returns it together with the rest of the characters in the buf.
316 91c10532 Andrea Spadaccini
    If no message is found, returns None and the whole buffer.
317 91c10532 Andrea Spadaccini

318 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
319 91c10532 Andrea Spadaccini

320 91c10532 Andrea Spadaccini
    """
321 91c10532 Andrea Spadaccini
    message = None
322 91c10532 Andrea Spadaccini
    # Check if we got the message end token (CRLF, as per the QEMU Protocol
323 91c10532 Andrea Spadaccini
    # Specification 0.1 - Section 2.1.1)
324 91c10532 Andrea Spadaccini
    pos = buf.find(self._MESSAGE_END_TOKEN)
325 91c10532 Andrea Spadaccini
    if pos >= 0:
326 91c10532 Andrea Spadaccini
      try:
327 91c10532 Andrea Spadaccini
        message = QmpMessage.BuildFromJsonString(buf[:pos + 1])
328 91c10532 Andrea Spadaccini
      except Exception, err:
329 91c10532 Andrea Spadaccini
        raise errors.ProgrammerError("QMP data serialization error: %s" % err)
330 91c10532 Andrea Spadaccini
      buf = buf[pos + 1:]
331 91c10532 Andrea Spadaccini
332 91c10532 Andrea Spadaccini
    return (message, buf)
333 91c10532 Andrea Spadaccini
334 91c10532 Andrea Spadaccini
  def _Recv(self):
335 91c10532 Andrea Spadaccini
    """Receives a message from QMP and decodes the received JSON object.
336 91c10532 Andrea Spadaccini

337 91c10532 Andrea Spadaccini
    @rtype: QmpMessage
338 91c10532 Andrea Spadaccini
    @return: the received message
339 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
340 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
341 91c10532 Andrea Spadaccini

342 91c10532 Andrea Spadaccini
    """
343 91c10532 Andrea Spadaccini
    self._check_connection()
344 91c10532 Andrea Spadaccini
345 91c10532 Andrea Spadaccini
    # Check if there is already a message in the buffer
346 91c10532 Andrea Spadaccini
    (message, self._buf) = self._ParseMessage(self._buf)
347 91c10532 Andrea Spadaccini
    if message:
348 91c10532 Andrea Spadaccini
      return message
349 91c10532 Andrea Spadaccini
350 91c10532 Andrea Spadaccini
    recv_buffer = StringIO.StringIO(self._buf)
351 91c10532 Andrea Spadaccini
    recv_buffer.seek(len(self._buf))
352 91c10532 Andrea Spadaccini
    try:
353 91c10532 Andrea Spadaccini
      while True:
354 91c10532 Andrea Spadaccini
        data = self.sock.recv(4096)
355 91c10532 Andrea Spadaccini
        if not data:
356 91c10532 Andrea Spadaccini
          break
357 91c10532 Andrea Spadaccini
        recv_buffer.write(data)
358 91c10532 Andrea Spadaccini
359 91c10532 Andrea Spadaccini
        (message, self._buf) = self._ParseMessage(recv_buffer.getvalue())
360 91c10532 Andrea Spadaccini
        if message:
361 91c10532 Andrea Spadaccini
          return message
362 91c10532 Andrea Spadaccini
363 91c10532 Andrea Spadaccini
    except socket.timeout, err:
364 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while receiving a QMP message: "
365 91c10532 Andrea Spadaccini
                                   "%s" % (err))
366 91c10532 Andrea Spadaccini
    except socket.error, err:
367 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to receive data from KVM using the"
368 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
369 91c10532 Andrea Spadaccini
370 91c10532 Andrea Spadaccini
  def _Send(self, message):
371 91c10532 Andrea Spadaccini
    """Encodes and sends a message to KVM using QMP.
372 91c10532 Andrea Spadaccini

373 91c10532 Andrea Spadaccini
    @type message: QmpMessage
374 91c10532 Andrea Spadaccini
    @param message: message to send to KVM
375 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
376 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
377 91c10532 Andrea Spadaccini

378 91c10532 Andrea Spadaccini
    """
379 91c10532 Andrea Spadaccini
    self._check_connection()
380 91c10532 Andrea Spadaccini
    try:
381 91c10532 Andrea Spadaccini
      message_str = str(message)
382 91c10532 Andrea Spadaccini
    except Exception, err:
383 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("QMP data deserialization error: %s" % err)
384 91c10532 Andrea Spadaccini
385 91c10532 Andrea Spadaccini
    try:
386 91c10532 Andrea Spadaccini
      self.sock.sendall(message_str)
387 91c10532 Andrea Spadaccini
    except socket.timeout, err:
388 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while sending a QMP message: "
389 91c10532 Andrea Spadaccini
                                   "%s (%s)" % (err.string, err.errno))
390 91c10532 Andrea Spadaccini
    except socket.error, err:
391 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to send data from KVM using the"
392 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
393 91c10532 Andrea Spadaccini
394 91c10532 Andrea Spadaccini
  def Execute(self, command, arguments=None):
395 91c10532 Andrea Spadaccini
    """Executes a QMP command and returns the response of the server.
396 91c10532 Andrea Spadaccini

397 91c10532 Andrea Spadaccini
    @type command: str
398 91c10532 Andrea Spadaccini
    @param command: the command to execute
399 91c10532 Andrea Spadaccini
    @type arguments: dict
400 91c10532 Andrea Spadaccini
    @param arguments: dictionary of arguments to be passed to the command
401 91c10532 Andrea Spadaccini
    @rtype: dict
402 91c10532 Andrea Spadaccini
    @return: dictionary representing the received JSON object
403 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
404 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
405 91c10532 Andrea Spadaccini

406 91c10532 Andrea Spadaccini
    """
407 91c10532 Andrea Spadaccini
    self._check_connection()
408 91c10532 Andrea Spadaccini
    message = QmpMessage({self._EXECUTE_KEY: command})
409 91c10532 Andrea Spadaccini
    if arguments:
410 91c10532 Andrea Spadaccini
      message[self._ARGUMENTS_KEY] = arguments
411 91c10532 Andrea Spadaccini
    self._Send(message)
412 91c10532 Andrea Spadaccini
413 91c10532 Andrea Spadaccini
    # Events can occur between the sending of the command and the reception
414 91c10532 Andrea Spadaccini
    # of the response, so we need to filter out messages with the event key.
415 91c10532 Andrea Spadaccini
    while True:
416 91c10532 Andrea Spadaccini
      response = self._Recv()
417 91c10532 Andrea Spadaccini
      err = response[self._ERROR_KEY]
418 91c10532 Andrea Spadaccini
      if err:
419 91c10532 Andrea Spadaccini
        raise errors.HypervisorError("kvm: error executing the %s"
420 91c10532 Andrea Spadaccini
                                     " command: %s (%s, %s):" %
421 91c10532 Andrea Spadaccini
                                     (command,
422 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DESC_KEY],
423 91c10532 Andrea Spadaccini
                                      err[self._ERROR_CLASS_KEY],
424 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DATA_KEY]))
425 91c10532 Andrea Spadaccini
426 91c10532 Andrea Spadaccini
      elif not response[self._EVENT_KEY]:
427 91c10532 Andrea Spadaccini
        return response
428 91c10532 Andrea Spadaccini
429 91c10532 Andrea Spadaccini
430 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
431 65107a2f Michael Hanselmann
  """KVM hypervisor interface
432 65107a2f Michael Hanselmann

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

604 98ec75d6 Iustin Pop
    """
605 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
606 98ec75d6 Iustin Pop
607 263b8de6 Guido Trotter
  @classmethod
608 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
609 7548396c Guido Trotter
    """Returns the instance uidfile.
610 7548396c Guido Trotter

611 7548396c Guido Trotter
    """
612 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
613 7548396c Guido Trotter
614 7548396c Guido Trotter
  @classmethod
615 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
616 263b8de6 Guido Trotter
    """Check pid file for instance information.
617 263b8de6 Guido Trotter

618 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
619 263b8de6 Guido Trotter
    information from its command line.
620 263b8de6 Guido Trotter

621 263b8de6 Guido Trotter
    @type pid: string or int
622 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
623 263b8de6 Guido Trotter
    @rtype: tuple
624 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
625 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
626 263b8de6 Guido Trotter

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

662 263b8de6 Guido Trotter
    @type instance_name: string
663 263b8de6 Guido Trotter
    @param instance_name: instance name
664 263b8de6 Guido Trotter
    @rtype: tuple
665 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
666 1f8b3a27 Guido Trotter

667 1f8b3a27 Guido Trotter
    """
668 98ec75d6 Iustin Pop
    pidfile = self._InstancePidFile(instance_name)
669 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
670 263b8de6 Guido Trotter
671 263b8de6 Guido Trotter
    alive = False
672 263b8de6 Guido Trotter
    try:
673 263b8de6 Guido Trotter
      cmd_instance = self._InstancePidInfo(pid)[0]
674 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
675 263b8de6 Guido Trotter
    except errors.HypervisorError:
676 263b8de6 Guido Trotter
      pass
677 1f8b3a27 Guido Trotter
678 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
679 1f8b3a27 Guido Trotter
680 5905901c Iustin Pop
  def _CheckDown(self, instance_name):
681 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
682 5905901c Iustin Pop

683 5905901c Iustin Pop
    """
684 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
685 5905901c Iustin Pop
    if alive:
686 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
687 5905901c Iustin Pop
                                   (instance_name, "already running"))
688 5905901c Iustin Pop
689 0df4d98a Guido Trotter
  @classmethod
690 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
691 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
692 c4fbefc8 Guido Trotter

693 c4fbefc8 Guido Trotter
    """
694 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
695 c4fbefc8 Guido Trotter
696 0df4d98a Guido Trotter
  @classmethod
697 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
698 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
699 c4fbefc8 Guido Trotter

700 c4fbefc8 Guido Trotter
    """
701 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
702 c4fbefc8 Guido Trotter
703 91c10532 Andrea Spadaccini
  @classmethod
704 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
705 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
706 91c10532 Andrea Spadaccini

707 91c10532 Andrea Spadaccini
    """
708 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
709 91c10532 Andrea Spadaccini
710 86d6bc2a Guido Trotter
  @staticmethod
711 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
712 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
713 86d6bc2a Guido Trotter

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

716 86d6bc2a Guido Trotter
    """
717 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
718 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
719 86d6bc2a Guido Trotter
    else:
720 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
721 86d6bc2a Guido Trotter
722 0df4d98a Guido Trotter
  @classmethod
723 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
724 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
725 38e250ba Guido Trotter

726 38e250ba Guido Trotter
    """
727 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
728 38e250ba Guido Trotter
729 7e66c35b Guido Trotter
  @classmethod
730 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
731 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
732 547a63b7 Balazs Lecz

733 547a63b7 Balazs Lecz
    """
734 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
735 547a63b7 Balazs Lecz
736 547a63b7 Balazs Lecz
  @classmethod
737 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
738 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
739 5d9bfd87 Apollon Oikonomopoulos
    given instance.
740 5d9bfd87 Apollon Oikonomopoulos

741 5d9bfd87 Apollon Oikonomopoulos
    """
742 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
743 5d9bfd87 Apollon Oikonomopoulos
744 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
745 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
746 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
747 5d9bfd87 Apollon Oikonomopoulos

748 5d9bfd87 Apollon Oikonomopoulos
    """
749 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
750 5d9bfd87 Apollon Oikonomopoulos
751 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
752 4f580fef Sรฉbastien Bocahu
  def _InstanceKeymapFile(cls, instance_name):
753 4f580fef Sรฉbastien Bocahu
    """Returns the name of the file containing the keymap for a given instance
754 4f580fef Sรฉbastien Bocahu

755 4f580fef Sรฉbastien Bocahu
    """
756 4f580fef Sรฉbastien Bocahu
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
757 4f580fef Sรฉbastien Bocahu
758 4f580fef Sรฉbastien Bocahu
  @classmethod
759 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
760 7548396c Guido Trotter
    """Try to read a uid file
761 7548396c Guido Trotter

762 7548396c Guido Trotter
    """
763 7548396c Guido Trotter
    if os.path.exists(uid_file):
764 7548396c Guido Trotter
      try:
765 682f7601 Guido Trotter
        uid = int(utils.ReadOneLineFile(uid_file))
766 aa0b600b Guido Trotter
        return uid
767 7548396c Guido Trotter
      except EnvironmentError:
768 7548396c Guido Trotter
        logging.warning("Can't read uid file", exc_info=True)
769 7548396c Guido Trotter
      except (TypeError, ValueError):
770 7548396c Guido Trotter
        logging.warning("Can't parse uid file contents", exc_info=True)
771 aa0b600b Guido Trotter
    return None
772 7548396c Guido Trotter
773 7548396c Guido Trotter
  @classmethod
774 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
775 547a63b7 Balazs Lecz
    """Removes an instance's rutime sockets/files/dirs.
776 7e66c35b Guido Trotter

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

817 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
818 eb58f9b1 Guido Trotter
    @type instance: instance object
819 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
820 eb58f9b1 Guido Trotter
    @type seq: int
821 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
822 eb58f9b1 Guido Trotter
    @type nic: nic object
823 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
824 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
825 eb58f9b1 Guido Trotter

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

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

875 b693125f Tsachy Shacham
    @type cpu_list: list of int
876 b693125f Tsachy Shacham
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
877 b693125f Tsachy Shacham
    @rtype: int
878 b693125f Tsachy Shacham
    @return: a bit mask of CPU affinities
879 b693125f Tsachy Shacham

880 b693125f Tsachy Shacham
    """
881 b693125f Tsachy Shacham
    if cpu_list == constants.CPU_PINNING_OFF:
882 b693125f Tsachy Shacham
      return constants.CPU_PINNING_ALL_KVM
883 b693125f Tsachy Shacham
    else:
884 b693125f Tsachy Shacham
      return sum(2 ** cpu for cpu in cpu_list)
885 b693125f Tsachy Shacham
886 b693125f Tsachy Shacham
  @classmethod
887 b693125f Tsachy Shacham
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
888 b693125f Tsachy Shacham
    """Change CPU affinity for running VM according to given CPU mask.
889 b693125f Tsachy Shacham

890 b693125f Tsachy Shacham
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
891 b693125f Tsachy Shacham
    @type cpu_mask: string
892 b693125f Tsachy Shacham
    @param process_id: process ID of KVM process. Used to pin entire VM
893 b693125f Tsachy Shacham
                       to physical CPUs.
894 b693125f Tsachy Shacham
    @type process_id: int
895 b693125f Tsachy Shacham
    @param thread_dict: map of virtual CPUs to KVM thread IDs
896 b693125f Tsachy Shacham
    @type thread_dict: dict int:int
897 b693125f Tsachy Shacham

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

928 b693125f Tsachy Shacham
    @type instance_name: string
929 b693125f Tsachy Shacham
    @param instance_name: instance in question
930 b693125f Tsachy Shacham
    @rtype: dictionary of int:int
931 b693125f Tsachy Shacham
    @return: a dictionary mapping vCPU numbers to thread IDs
932 b693125f Tsachy Shacham

933 b693125f Tsachy Shacham
    """
934 b693125f Tsachy Shacham
    result = {}
935 b693125f Tsachy Shacham
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
936 b693125f Tsachy Shacham
    for line in output.stdout.splitlines():
937 b693125f Tsachy Shacham
      match = self._CPU_INFO_RE.search(line)
938 b693125f Tsachy Shacham
      if not match:
939 b693125f Tsachy Shacham
        continue
940 b693125f Tsachy Shacham
      grp = map(int, match.groups())
941 b693125f Tsachy Shacham
      result[grp[0]] = grp[1]
942 b693125f Tsachy Shacham
943 b693125f Tsachy Shacham
    return result
944 b693125f Tsachy Shacham
945 1d8a7812 Andrea Spadaccini
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
946 1d8a7812 Andrea Spadaccini
    """Complete CPU pinning.
947 b693125f Tsachy Shacham

948 b693125f Tsachy Shacham
    @type instance_name: string
949 b693125f Tsachy Shacham
    @param instance_name: name of instance
950 b693125f Tsachy Shacham
    @type cpu_mask: string
951 b693125f Tsachy Shacham
    @param cpu_mask: CPU pinning mask as entered by user
952 b693125f Tsachy Shacham

953 b693125f Tsachy Shacham
    """
954 1d8a7812 Andrea Spadaccini
    # Get KVM process ID, to be used if need to pin entire VM
955 1d8a7812 Andrea Spadaccini
    _, pid, _ = self._InstancePidAlive(instance_name)
956 1d8a7812 Andrea Spadaccini
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
957 1d8a7812 Andrea Spadaccini
    thread_dict = self._GetVcpuThreadIds(instance_name)
958 1d8a7812 Andrea Spadaccini
    # Run CPU pinning, based on configured mask
959 1d8a7812 Andrea Spadaccini
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
960 b693125f Tsachy Shacham
961 58e356a9 Helga Velroyen
  def ListInstances(self, hvparams=None):
962 eb58f9b1 Guido Trotter
    """Get the list of running instances.
963 eb58f9b1 Guido Trotter

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

967 eb58f9b1 Guido Trotter
    """
968 eb58f9b1 Guido Trotter
    result = []
969 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
970 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
971 eb58f9b1 Guido Trotter
        result.append(name)
972 eb58f9b1 Guido Trotter
    return result
973 eb58f9b1 Guido Trotter
974 0bbec3af Helga Velroyen
  def GetInstanceInfo(self, instance_name, hvparams=None):
975 eb58f9b1 Guido Trotter
    """Get instance properties.
976 eb58f9b1 Guido Trotter

977 4fbb3c60 Guido Trotter
    @type instance_name: string
978 c41eea6e Iustin Pop
    @param instance_name: the instance name
979 0bbec3af Helga Velroyen
    @type hvparams: dict of strings
980 0bbec3af Helga Velroyen
    @param hvparams: hvparams to be used with this instance
981 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
982 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
983 eb58f9b1 Guido Trotter

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

1009 0200a1af Helga Velroyen
    @type hvparams: dict of strings
1010 0200a1af Helga Velroyen
    @param hvparams: hypervisor parameter
1011 c41eea6e Iustin Pop
    @return: list of tuples (name, id, memory, vcpus, stat, times)
1012 c41eea6e Iustin Pop

1013 eb58f9b1 Guido Trotter
    """
1014 eb58f9b1 Guido Trotter
    data = []
1015 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1016 263b8de6 Guido Trotter
      try:
1017 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
1018 263b8de6 Guido Trotter
      except errors.HypervisorError:
1019 3bc145d8 Bernardo Dal Seno
        # Ignore exceptions due to instances being shut down
1020 263b8de6 Guido Trotter
        continue
1021 263b8de6 Guido Trotter
      if info:
1022 263b8de6 Guido Trotter
        data.append(info)
1023 eb58f9b1 Guido Trotter
    return data
1024 eb58f9b1 Guido Trotter
1025 b73f1c59 Guido Trotter
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused,
1026 b73f1c59 Guido Trotter
                          kvmhelp):
1027 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
1028 eb58f9b1 Guido Trotter

1029 b73f1c59 Guido Trotter
    @type kvmhelp: string
1030 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1031 839642c2 Iustin Pop
    @attention: this function must not have any side-effects; for
1032 839642c2 Iustin Pop
        example, it must not write to the filesystem, or read values
1033 839642c2 Iustin Pop
        from the current system the are expected to differ between
1034 839642c2 Iustin Pop
        nodes, since it is only run once at instance startup;
1035 839642c2 Iustin Pop
        actions/kvm arguments that can vary between systems should be
1036 839642c2 Iustin Pop
        done in L{_ExecuteKVMRuntime}
1037 839642c2 Iustin Pop

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

1416 38e250ba Guido Trotter
    """
1417 38e250ba Guido Trotter
    try:
1418 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1419 38e250ba Guido Trotter
                      data=data)
1420 90c024f6 Guido Trotter
    except EnvironmentError, err:
1421 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1422 38e250ba Guido Trotter
1423 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
1424 38e250ba Guido Trotter
    """Read an instance's KVM runtime
1425 38e250ba Guido Trotter

1426 38e250ba Guido Trotter
    """
1427 38e250ba Guido Trotter
    try:
1428 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1429 90c024f6 Guido Trotter
    except EnvironmentError, err:
1430 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1431 38e250ba Guido Trotter
    return file_content
1432 38e250ba Guido Trotter
1433 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1434 38e250ba Guido Trotter
    """Save an instance's KVM runtime
1435 38e250ba Guido Trotter

1436 38e250ba Guido Trotter
    """
1437 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
1438 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1439 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
1440 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
1441 38e250ba Guido Trotter
1442 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1443 38e250ba Guido Trotter
    """Load an instance's KVM runtime
1444 38e250ba Guido Trotter

1445 38e250ba Guido Trotter
    """
1446 30e42c4e Guido Trotter
    if not serialized_runtime:
1447 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1448 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
1449 c2672466 Guido Trotter
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
1450 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
1451 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
1452 38e250ba Guido Trotter
1453 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1454 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
1455 76431533 Guido Trotter

1456 76431533 Guido Trotter
    @type name: string
1457 76431533 Guido Trotter
    @param name: instance name
1458 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1459 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1460 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1461 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1462 76431533 Guido Trotter

1463 76431533 Guido Trotter
    """
1464 5d9bfd87 Apollon Oikonomopoulos
    try:
1465 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1466 5d9bfd87 Apollon Oikonomopoulos
    finally:
1467 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
1468 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
1469 5d9bfd87 Apollon Oikonomopoulos
1470 76431533 Guido Trotter
    if result.failed:
1471 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1472 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
1473 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
1474 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
1475 76431533 Guido Trotter
1476 b73f1c59 Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1477 839642c2 Iustin Pop
    """Execute a KVM cmd, after completing it with some last minute data.
1478 ee5f20b0 Guido Trotter

1479 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1480 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1481 b73f1c59 Guido Trotter
    @type kvmhelp: string
1482 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1483 30e42c4e Guido Trotter

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

1687 ee5f20b0 Guido Trotter
    """
1688 5905901c Iustin Pop
    self._CheckDown(instance.name)
1689 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1690 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1691 7238edb5 Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1692 b73f1c59 Guido Trotter
                                           startup_paused, kvmhelp)
1693 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1694 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1695 ee5f20b0 Guido Trotter
1696 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
1697 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
1698 6567aff3 Guido Trotter

1699 6567aff3 Guido Trotter
    """
1700 eace6157 Michael Hanselmann
    # TODO: Replace monitor calls with QMP once KVM >= 0.14 is the minimum
1701 eace6157 Michael Hanselmann
    # version. The monitor protocol is designed for human consumption, whereas
1702 eace6157 Michael Hanselmann
    # QMP is made for programmatic usage. In the worst case QMP can also
1703 eace6157 Michael Hanselmann
    # execute monitor commands. As it is, all calls to socat take at least
1704 eace6157 Michael Hanselmann
    # 500ms and likely more: socat can't detect the end of the reply and waits
1705 eace6157 Michael Hanselmann
    # for 500ms of no data received before exiting (500 ms is the default for
1706 eace6157 Michael Hanselmann
    # the "-t" parameter).
1707 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1708 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
1709 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
1710 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1711 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
1712 6567aff3 Guido Trotter
    if result.failed:
1713 afa9bb2e Michael Hanselmann
      msg = ("Failed to send command '%s' to instance '%s', reason '%s',"
1714 afa9bb2e Michael Hanselmann
             " output: %s" %
1715 afa9bb2e Michael Hanselmann
             (command, instance_name, result.fail_reason, result.output))
1716 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
1717 6567aff3 Guido Trotter
1718 6567aff3 Guido Trotter
    return result
1719 6567aff3 Guido Trotter
1720 b52d85c1 Guido Trotter
  @classmethod
1721 585c8187 Guido Trotter
  def _ParseKVMVersion(cls, text):
1722 585c8187 Guido Trotter
    """Parse the KVM version from the --help output.
1723 585c8187 Guido Trotter

1724 585c8187 Guido Trotter
    @type text: string
1725 585c8187 Guido Trotter
    @param text: output of kvm --help
1726 585c8187 Guido Trotter
    @return: (version, v_maj, v_min, v_rev)
1727 5c3d5dfd Iustin Pop
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1728 585c8187 Guido Trotter

1729 585c8187 Guido Trotter
    """
1730 585c8187 Guido Trotter
    match = cls._VERSION_RE.search(text.splitlines()[0])
1731 585c8187 Guido Trotter
    if not match:
1732 585c8187 Guido Trotter
      raise errors.HypervisorError("Unable to get KVM version")
1733 585c8187 Guido Trotter
1734 585c8187 Guido Trotter
    v_all = match.group(0)
1735 585c8187 Guido Trotter
    v_maj = int(match.group(1))
1736 585c8187 Guido Trotter
    v_min = int(match.group(2))
1737 585c8187 Guido Trotter
    if match.group(4):
1738 585c8187 Guido Trotter
      v_rev = int(match.group(4))
1739 585c8187 Guido Trotter
    else:
1740 585c8187 Guido Trotter
      v_rev = 0
1741 585c8187 Guido Trotter
    return (v_all, v_maj, v_min, v_rev)
1742 585c8187 Guido Trotter
1743 585c8187 Guido Trotter
  @classmethod
1744 6e043e60 Guido Trotter
  def _GetKVMOutput(cls, kvm_path, option):
1745 6e043e60 Guido Trotter
    """Return the output of a kvm invocation
1746 e3b89628 Guido Trotter

1747 bc0fed4b Guido Trotter
    @type kvm_path: string
1748 bc0fed4b Guido Trotter
    @param kvm_path: path to the kvm executable
1749 bc0fed4b Guido Trotter
    @type option: a key of _KVMOPTS_CMDS
1750 bc0fed4b Guido Trotter
    @param option: kvm option to fetch the output from
1751 6e043e60 Guido Trotter
    @return: output a supported kvm invocation
1752 e3b89628 Guido Trotter
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
1753 e3b89628 Guido Trotter

1754 e3b89628 Guido Trotter
    """
1755 6e043e60 Guido Trotter
    assert option in cls._KVMOPTS_CMDS, "Invalid output option"
1756 6e043e60 Guido Trotter
1757 bc0fed4b Guido Trotter
    optlist, can_fail = cls._KVMOPTS_CMDS[option]
1758 bc0fed4b Guido Trotter
1759 bc0fed4b Guido Trotter
    result = utils.RunCmd([kvm_path] + optlist)
1760 bc0fed4b Guido Trotter
    if result.failed and not can_fail:
1761 af89fa76 Helga Velroyen
      raise errors.HypervisorError("Unable to get KVM %s output" %
1762 af89fa76 Helga Velroyen
                                    " ".join(cls._KVMOPTS_CMDS[option]))
1763 e3b89628 Guido Trotter
    return result.output
1764 e3b89628 Guido Trotter
1765 e3b89628 Guido Trotter
  @classmethod
1766 3b59ec02 Guido Trotter
  def _GetKVMVersion(cls, kvm_path):
1767 d7e4a2b1 Andrea Spadaccini
    """Return the installed KVM version.
1768 b52d85c1 Guido Trotter

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

1772 b52d85c1 Guido Trotter
    """
1773 6e043e60 Guido Trotter
    return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
1774 82e3bf85 Dimitris Aragiorgis
1775 82e3bf85 Dimitris Aragiorgis
  @classmethod
1776 82e3bf85 Dimitris Aragiorgis
  def _GetDefaultMachineVersion(cls, kvm_path):
1777 82e3bf85 Dimitris Aragiorgis
    """Return the default hardware revision (e.g. pc-1.1)
1778 82e3bf85 Dimitris Aragiorgis

1779 82e3bf85 Dimitris Aragiorgis
    """
1780 6e043e60 Guido Trotter
    output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
1781 82e3bf85 Dimitris Aragiorgis
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
1782 82e3bf85 Dimitris Aragiorgis
    if match:
1783 82e3bf85 Dimitris Aragiorgis
      return match.group(1)
1784 82e3bf85 Dimitris Aragiorgis
    else:
1785 82e3bf85 Dimitris Aragiorgis
      return "pc"
1786 82e3bf85 Dimitris Aragiorgis
1787 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
1788 eb58f9b1 Guido Trotter
    """Stop an instance.
1789 eb58f9b1 Guido Trotter

1790 eb58f9b1 Guido Trotter
    """
1791 bbcf7ad0 Iustin Pop
    if name is not None and not force:
1792 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
1793 bbcf7ad0 Iustin Pop
    if name is None:
1794 bbcf7ad0 Iustin Pop
      name = instance.name
1795 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
1796 bbcf7ad0 Iustin Pop
    else:
1797 bbcf7ad0 Iustin Pop
      acpi = False
1798 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
1799 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
1800 bbcf7ad0 Iustin Pop
      if force or not acpi:
1801 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
1802 eb58f9b1 Guido Trotter
      else:
1803 d0c8c01d Iustin Pop
        self._CallMonitorCommand(name, "system_powerdown")
1804 eb58f9b1 Guido Trotter
1805 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
1806 8904b35c Guido Trotter
    """Cleanup after a stopped instance
1807 8904b35c Guido Trotter

1808 8904b35c Guido Trotter
    """
1809 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1810 8904b35c Guido Trotter
    if pid > 0 and alive:
1811 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
1812 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1813 eb58f9b1 Guido Trotter
1814 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
1815 eb58f9b1 Guido Trotter
    """Reboot an instance.
1816 eb58f9b1 Guido Trotter

1817 eb58f9b1 Guido Trotter
    """
1818 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
1819 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
1820 eb58f9b1 Guido Trotter
    # to shutdown and restart.
1821 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
1822 1f8b3a27 Guido Trotter
    if not alive:
1823 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
1824 78411c60 Iustin Pop
                                   " not running" % instance.name)
1825 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
1826 f02881e0 Guido Trotter
    # ...first load it...
1827 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
1828 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
1829 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
1830 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
1831 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
1832 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1833 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1834 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1835 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1836 eb58f9b1 Guido Trotter
1837 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
1838 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
1839 30e42c4e Guido Trotter

1840 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1841 30e42c4e Guido Trotter
    @param instance: instance to be migrated
1842 30e42c4e Guido Trotter
    @rtype: string
1843 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
1844 30e42c4e Guido Trotter

1845 30e42c4e Guido Trotter
    """
1846 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
1847 30e42c4e Guido Trotter
1848 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
1849 30e42c4e Guido Trotter
    """Prepare to accept an instance.
1850 30e42c4e Guido Trotter

1851 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1852 30e42c4e Guido Trotter
    @param instance: instance to be accepted
1853 30e42c4e Guido Trotter
    @type info: string
1854 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
1855 30e42c4e Guido Trotter
    @type target: string
1856 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
1857 30e42c4e Guido Trotter

1858 30e42c4e Guido Trotter
    """
1859 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1860 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1861 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1862 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1863 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
1864 b73f1c59 Guido Trotter
                            incoming=incoming_address)
1865 30e42c4e Guido Trotter
1866 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
1867 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
1868 30e42c4e Guido Trotter

1869 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
1870 30e42c4e Guido Trotter

1871 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1872 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
1873 30e42c4e Guido Trotter

1874 30e42c4e Guido Trotter
    """
1875 30e42c4e Guido Trotter
    if success:
1876 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1877 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
1878 5d9bfd87 Apollon Oikonomopoulos
1879 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
1880 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1881 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
1882 cc8a8ed7 Apollon Oikonomopoulos
          continue
1883 5d9bfd87 Apollon Oikonomopoulos
        try:
1884 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
1885 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
1886 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
1887 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
1888 5d9bfd87 Apollon Oikonomopoulos
          continue
1889 5d9bfd87 Apollon Oikonomopoulos
        try:
1890 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
1891 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
1892 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
1893 5d9bfd87 Apollon Oikonomopoulos
1894 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
1895 30e42c4e Guido Trotter
    else:
1896 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
1897 30e42c4e Guido Trotter
1898 bc0a2284 Helga Velroyen
  def MigrateInstance(self, cluster_name, instance, target, live):
1899 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
1900 30e42c4e Guido Trotter

1901 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
1902 30e42c4e Guido Trotter
    currently running.
1903 30e42c4e Guido Trotter

1904 bc0a2284 Helga Velroyen
    @type cluster_name: string
1905 bc0a2284 Helga Velroyen
    @param cluster_name: name of the cluster
1906 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
1907 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
1908 30e42c4e Guido Trotter
    @type target: string
1909 30e42c4e Guido Trotter
    @param target: ip address of the target node
1910 30e42c4e Guido Trotter
    @type live: boolean
1911 30e42c4e Guido Trotter
    @param live: perform a live migration
1912 30e42c4e Guido Trotter

1913 30e42c4e Guido Trotter
    """
1914 58d38b02 Iustin Pop
    instance_name = instance.name
1915 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
1916 6a1434d7 Andrea Spadaccini
    _, _, alive = self._InstancePidAlive(instance_name)
1917 30e42c4e Guido Trotter
    if not alive:
1918 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
1919 30e42c4e Guido Trotter
1920 30e42c4e Guido Trotter
    if not live:
1921 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
1922 30e42c4e Guido Trotter
1923 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
1924 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1925 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
1926 e43d4f9f Apollon Oikonomopoulos
1927 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
1928 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
1929 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
1930 e43d4f9f Apollon Oikonomopoulos
1931 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
1932 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
1933 30e42c4e Guido Trotter
1934 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
1935 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
1936 6a1434d7 Andrea Spadaccini

1937 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
1938 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
1939 6a1434d7 Andrea Spadaccini
    @type success: bool
1940 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
1941 6a1434d7 Andrea Spadaccini
    @type live: bool
1942 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
1943 6a1434d7 Andrea Spadaccini

1944 6a1434d7 Andrea Spadaccini
    """
1945 6a1434d7 Andrea Spadaccini
    if success:
1946 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
1947 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
1948 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
1949 6a1434d7 Andrea Spadaccini
    elif live:
1950 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1951 6a1434d7 Andrea Spadaccini
1952 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
1953 6a1434d7 Andrea Spadaccini
    """Get the migration status
1954 6a1434d7 Andrea Spadaccini

1955 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
1956 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
1957 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
1958 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
1959 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
1960 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
1961 6a1434d7 Andrea Spadaccini

1962 6a1434d7 Andrea Spadaccini
    """
1963 d0c8c01d Iustin Pop
    info_command = "info migrate"
1964 6a1434d7 Andrea Spadaccini
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
1965 6a1434d7 Andrea Spadaccini
      result = self._CallMonitorCommand(instance.name, info_command)
1966 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
1967 30e42c4e Guido Trotter
      if not match:
1968 c4e388a5 Guido Trotter
        if not result.stdout:
1969 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
1970 c4e388a5 Guido Trotter
        else:
1971 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
1972 c4e388a5 Guido Trotter
                          result.stdout)
1973 30e42c4e Guido Trotter
      else:
1974 30e42c4e Guido Trotter
        status = match.group(1)
1975 6a1434d7 Andrea Spadaccini
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
1976 6a1434d7 Andrea Spadaccini
          migration_status = objects.MigrationStatus(status=status)
1977 61643226 Andrea Spadaccini
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
1978 61643226 Andrea Spadaccini
          if match:
1979 61643226 Andrea Spadaccini
            migration_status.transferred_ram = match.group("transferred")
1980 61643226 Andrea Spadaccini
            migration_status.total_ram = match.group("total")
1981 61643226 Andrea Spadaccini
1982 6a1434d7 Andrea Spadaccini
          return migration_status
1983 30e42c4e Guido Trotter
1984 6a1434d7 Andrea Spadaccini
        logging.warning("KVM: unknown migration status '%s'", status)
1985 6a1434d7 Andrea Spadaccini
1986 6a1434d7 Andrea Spadaccini
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1987 6a1434d7 Andrea Spadaccini
1988 62457f51 Iustin Pop
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
1989 30e42c4e Guido Trotter
1990 3d836750 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
1991 3d836750 Guido Trotter
    """Balloon an instance memory to a certain value.
1992 3d836750 Guido Trotter

1993 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
1994 3d836750 Guido Trotter
    @param instance: instance to be accepted
1995 3d836750 Guido Trotter
    @type mem: int
1996 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
1997 3d836750 Guido Trotter

1998 3d836750 Guido Trotter
    """
1999 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2000 3d836750 Guido Trotter
2001 fac489a5 Helga Velroyen
  def GetNodeInfo(self, hvparams=None):
2002 eb58f9b1 Guido Trotter
    """Return information about the node.
2003 eb58f9b1 Guido Trotter

2004 fac489a5 Helga Velroyen
    @type hvparams: dict of strings
2005 fac489a5 Helga Velroyen
    @param hvparams: hypervisor parameters, not used in this class
2006 fac489a5 Helga Velroyen

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

2012 eb58f9b1 Guido Trotter
    """
2013 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
2014 4b9638dc Guido Trotter
    # FIXME: this is the global kvm version, but the actual version can be
2015 4b9638dc Guido Trotter
    # customized as an hv parameter. we should use the nodegroup's default kvm
2016 4b9638dc Guido Trotter
    # path parameter here.
2017 3b59ec02 Guido Trotter
    _, v_major, v_min, v_rev = self._GetKVMVersion(constants.KVM_PATH)
2018 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2019 34fbc862 Andrea Spadaccini
    return result
2020 eb58f9b1 Guido Trotter
2021 637ce7f9 Guido Trotter
  @classmethod
2022 1c3231aa Thomas Thrainer
  def GetInstanceConsole(cls, instance, primary_node, hvparams, beparams):
2023 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
2024 eb58f9b1 Guido Trotter

2025 eb58f9b1 Guido Trotter
    """
2026 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2027 9d9bded1 Michael Hanselmann
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2028 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2029 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2030 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
2031 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2032 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2033 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
2034 1c3231aa Thomas Thrainer
                                     host=primary_node.name,
2035 052783ff Michael Hanselmann
                                     user=constants.SSH_CONSOLE_USER,
2036 55cc0a44 Michael Hanselmann
                                     command=cmd)
2037 3be34f57 Guido Trotter
2038 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2039 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2040 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
2041 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2042 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
2043 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
2044 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
2045 55cc0a44 Michael Hanselmann
                                     display=display)
2046 55cc0a44 Michael Hanselmann
2047 4d2cdb5a Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2048 4d2cdb5a Andrea Spadaccini
    if spice_bind:
2049 4d2cdb5a Andrea Spadaccini
      return objects.InstanceConsole(instance=instance.name,
2050 4d2cdb5a Andrea Spadaccini
                                     kind=constants.CONS_SPICE,
2051 4d2cdb5a Andrea Spadaccini
                                     host=spice_bind,
2052 4d2cdb5a Andrea Spadaccini
                                     port=instance.network_port)
2053 4d2cdb5a Andrea Spadaccini
2054 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
2055 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
2056 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
2057 55cc0a44 Michael Hanselmann
                                            instance.name))
2058 eb58f9b1 Guido Trotter
2059 75bf3149 Helga Velroyen
  def Verify(self, hvparams=None):
2060 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
2061 eb58f9b1 Guido Trotter

2062 cd04dfd2 Michael Hanselmann
    Check that the required binaries exist.
2063 cd04dfd2 Michael Hanselmann

2064 75bf3149 Helga Velroyen
    @type hvparams: dict of strings
2065 75bf3149 Helga Velroyen
    @param hvparams: hypervisor parameters to be verified against, not used here
2066 75bf3149 Helga Velroyen

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

2069 eb58f9b1 Guido Trotter
    """
2070 1f4b9d39 Iustin Pop
    msgs = []
2071 1f4b9d39 Iustin Pop
    # FIXME: this is the global kvm binary, but the actual path can be
2072 1f4b9d39 Iustin Pop
    # customized as an hv parameter; we should use the nodegroup's
2073 1f4b9d39 Iustin Pop
    # default kvm path parameter here.
2074 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
2075 1f4b9d39 Iustin Pop
      msgs.append("The KVM binary ('%s') does not exist" % constants.KVM_PATH)
2076 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2077 1f4b9d39 Iustin Pop
      msgs.append("The socat binary ('%s') does not exist" %
2078 1f4b9d39 Iustin Pop
                  constants.SOCAT_PATH)
2079 1f4b9d39 Iustin Pop
2080 1f4b9d39 Iustin Pop
    return self._FormatVerifyResults(msgs)
2081 14aa53cb Guido Trotter
2082 6b5605e8 Iustin Pop
  @classmethod
2083 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2084 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2085 6b5605e8 Iustin Pop

2086 6b5605e8 Iustin Pop
    @type hvparams:  dict
2087 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2088 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2089 6b5605e8 Iustin Pop

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

2159 d19d94db Guido Trotter
    @type hvparams:  dict
2160 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2161 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2162 d19d94db Guido Trotter

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

2220 8ef418bb Helga Velroyen
    @type hvparams: dict of strings
2221 8ef418bb Helga Velroyen
    @param hvparams: hypervisor params to be used on this node
2222 8ef418bb Helga Velroyen

2223 f5118ade Iustin Pop
    """
2224 f5118ade Iustin Pop
    cls.LinuxPowercycle()