Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ ea2bcb82

History | View | Annotate | Download (79.2 kB)

1 eb58f9b1 Guido Trotter
#
2 eb58f9b1 Guido Trotter
#
3 eb58f9b1 Guido Trotter
4 2911f46c Iustin Pop
# Copyright (C) 2008, 2009, 2010, 2011, 2012 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 ea2bcb82 Michael Hanselmann
    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 8df21834 Dimitris Aragiorgis
def _BuildNetworkEnv(name, network, gateway, network6, gateway6,
168 8df21834 Dimitris Aragiorgis
                     network_type, mac_prefix, tags, env):
169 8df21834 Dimitris Aragiorgis
  """Build environment variables concerning a Network.
170 8df21834 Dimitris Aragiorgis

171 8df21834 Dimitris Aragiorgis
  """
172 8df21834 Dimitris Aragiorgis
  if name:
173 8df21834 Dimitris Aragiorgis
    env["NETWORK_NAME"] = name
174 8df21834 Dimitris Aragiorgis
  if network:
175 8df21834 Dimitris Aragiorgis
    env["NETWORK_SUBNET"] = network
176 8df21834 Dimitris Aragiorgis
  if gateway:
177 8df21834 Dimitris Aragiorgis
    env["NETWORK_GATEWAY"] = gateway
178 8df21834 Dimitris Aragiorgis
  if network6:
179 8df21834 Dimitris Aragiorgis
    env["NETWORK_SUBNET6"] = network6
180 8df21834 Dimitris Aragiorgis
  if gateway6:
181 8df21834 Dimitris Aragiorgis
    env["NETWORK_GATEWAY6"] = gateway6
182 8df21834 Dimitris Aragiorgis
  if mac_prefix:
183 8df21834 Dimitris Aragiorgis
    env["NETWORK_MAC_PREFIX"] = mac_prefix
184 8df21834 Dimitris Aragiorgis
  if network_type:
185 8df21834 Dimitris Aragiorgis
    env["NETWORK_TYPE"] = network_type
186 8df21834 Dimitris Aragiorgis
  if tags:
187 8df21834 Dimitris Aragiorgis
    env["NETWORK_TAGS"] = " ".join(tags)
188 8df21834 Dimitris Aragiorgis
189 8df21834 Dimitris Aragiorgis
  return env
190 8df21834 Dimitris Aragiorgis
191 8df21834 Dimitris Aragiorgis
192 91c10532 Andrea Spadaccini
class QmpMessage:
193 91c10532 Andrea Spadaccini
  """QEMU Messaging Protocol (QMP) message.
194 91c10532 Andrea Spadaccini

195 91c10532 Andrea Spadaccini
  """
196 91c10532 Andrea Spadaccini
  def __init__(self, data):
197 91c10532 Andrea Spadaccini
    """Creates a new QMP message based on the passed data.
198 91c10532 Andrea Spadaccini

199 91c10532 Andrea Spadaccini
    """
200 91c10532 Andrea Spadaccini
    if not isinstance(data, dict):
201 91c10532 Andrea Spadaccini
      raise TypeError("QmpMessage must be initialized with a dict")
202 91c10532 Andrea Spadaccini
203 91c10532 Andrea Spadaccini
    self.data = data
204 91c10532 Andrea Spadaccini
205 91c10532 Andrea Spadaccini
  def __getitem__(self, field_name):
206 91c10532 Andrea Spadaccini
    """Get the value of the required field if present, or None.
207 91c10532 Andrea Spadaccini

208 91c10532 Andrea Spadaccini
    Overrides the [] operator to provide access to the message data,
209 91c10532 Andrea Spadaccini
    returning None if the required item is not in the message
210 91c10532 Andrea Spadaccini
    @return: the value of the field_name field, or None if field_name
211 91c10532 Andrea Spadaccini
             is not contained in the message
212 91c10532 Andrea Spadaccini

213 91c10532 Andrea Spadaccini
    """
214 9b87c2cf Michael Hanselmann
    return self.data.get(field_name, None)
215 91c10532 Andrea Spadaccini
216 91c10532 Andrea Spadaccini
  def __setitem__(self, field_name, field_value):
217 91c10532 Andrea Spadaccini
    """Set the value of the required field_name to field_value.
218 91c10532 Andrea Spadaccini

219 91c10532 Andrea Spadaccini
    """
220 91c10532 Andrea Spadaccini
    self.data[field_name] = field_value
221 91c10532 Andrea Spadaccini
222 91c10532 Andrea Spadaccini
  @staticmethod
223 91c10532 Andrea Spadaccini
  def BuildFromJsonString(json_string):
224 91c10532 Andrea Spadaccini
    """Build a QmpMessage from a JSON encoded string.
225 91c10532 Andrea Spadaccini

226 91c10532 Andrea Spadaccini
    @type json_string: str
227 91c10532 Andrea Spadaccini
    @param json_string: JSON string representing the message
228 91c10532 Andrea Spadaccini
    @rtype: L{QmpMessage}
229 91c10532 Andrea Spadaccini
    @return: a L{QmpMessage} built from json_string
230 91c10532 Andrea Spadaccini

231 91c10532 Andrea Spadaccini
    """
232 91c10532 Andrea Spadaccini
    # Parse the string
233 91c10532 Andrea Spadaccini
    data = serializer.LoadJson(json_string)
234 91c10532 Andrea Spadaccini
    return QmpMessage(data)
235 91c10532 Andrea Spadaccini
236 91c10532 Andrea Spadaccini
  def __str__(self):
237 a182a3ed Michael Hanselmann
    # The protocol expects the JSON object to be sent as a single line.
238 a182a3ed Michael Hanselmann
    return serializer.DumpJson(self.data)
239 91c10532 Andrea Spadaccini
240 91c10532 Andrea Spadaccini
  def __eq__(self, other):
241 91c10532 Andrea Spadaccini
    # When comparing two QmpMessages, we are interested in comparing
242 91c10532 Andrea Spadaccini
    # their internal representation of the message data
243 91c10532 Andrea Spadaccini
    return self.data == other.data
244 91c10532 Andrea Spadaccini
245 91c10532 Andrea Spadaccini
246 91c10532 Andrea Spadaccini
class QmpConnection:
247 91c10532 Andrea Spadaccini
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
248 91c10532 Andrea Spadaccini

249 91c10532 Andrea Spadaccini
  """
250 91c10532 Andrea Spadaccini
  _FIRST_MESSAGE_KEY = "QMP"
251 91c10532 Andrea Spadaccini
  _EVENT_KEY = "event"
252 91c10532 Andrea Spadaccini
  _ERROR_KEY = "error"
253 89da2ff3 Guido Trotter
  _RETURN_KEY = RETURN_KEY = "return"
254 89da2ff3 Guido Trotter
  _ACTUAL_KEY = ACTUAL_KEY = "actual"
255 91c10532 Andrea Spadaccini
  _ERROR_CLASS_KEY = "class"
256 91c10532 Andrea Spadaccini
  _ERROR_DATA_KEY = "data"
257 91c10532 Andrea Spadaccini
  _ERROR_DESC_KEY = "desc"
258 91c10532 Andrea Spadaccini
  _EXECUTE_KEY = "execute"
259 91c10532 Andrea Spadaccini
  _ARGUMENTS_KEY = "arguments"
260 91c10532 Andrea Spadaccini
  _CAPABILITIES_COMMAND = "qmp_capabilities"
261 91c10532 Andrea Spadaccini
  _MESSAGE_END_TOKEN = "\r\n"
262 91c10532 Andrea Spadaccini
  _SOCKET_TIMEOUT = 5
263 91c10532 Andrea Spadaccini
264 91c10532 Andrea Spadaccini
  def __init__(self, monitor_filename):
265 91c10532 Andrea Spadaccini
    """Instantiates the QmpConnection object.
266 91c10532 Andrea Spadaccini

267 91c10532 Andrea Spadaccini
    @type monitor_filename: string
268 91c10532 Andrea Spadaccini
    @param monitor_filename: the filename of the UNIX raw socket on which the
269 91c10532 Andrea Spadaccini
                             QMP monitor is listening
270 91c10532 Andrea Spadaccini

271 91c10532 Andrea Spadaccini
    """
272 91c10532 Andrea Spadaccini
    self.monitor_filename = monitor_filename
273 91c10532 Andrea Spadaccini
    self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
274 91c10532 Andrea Spadaccini
    # We want to fail if the server doesn't send a complete message
275 91c10532 Andrea Spadaccini
    # in a reasonable amount of time
276 91c10532 Andrea Spadaccini
    self.sock.settimeout(self._SOCKET_TIMEOUT)
277 91c10532 Andrea Spadaccini
    self._connected = False
278 91c10532 Andrea Spadaccini
    self._buf = ""
279 91c10532 Andrea Spadaccini
280 fc84cd5d Guido Trotter
  def _check_socket(self):
281 fc84cd5d Guido Trotter
    sock_stat = None
282 fc84cd5d Guido Trotter
    try:
283 fc84cd5d Guido Trotter
      sock_stat = os.stat(self.monitor_filename)
284 fc84cd5d Guido Trotter
    except EnvironmentError, err:
285 fc84cd5d Guido Trotter
      if err.errno == errno.ENOENT:
286 fc84cd5d Guido Trotter
        raise errors.HypervisorError("No qmp socket found")
287 fc84cd5d Guido Trotter
      else:
288 fc84cd5d Guido Trotter
        raise errors.HypervisorError("Error checking qmp socket: %s",
289 fc84cd5d Guido Trotter
                                     utils.ErrnoOrStr(err))
290 fc84cd5d Guido Trotter
    if not stat.S_ISSOCK(sock_stat.st_mode):
291 fc84cd5d Guido Trotter
      raise errors.HypervisorError("Qmp socket is not a socket")
292 fc84cd5d Guido Trotter
293 91c10532 Andrea Spadaccini
  def _check_connection(self):
294 91c10532 Andrea Spadaccini
    """Make sure that the connection is established.
295 91c10532 Andrea Spadaccini

296 91c10532 Andrea Spadaccini
    """
297 91c10532 Andrea Spadaccini
    if not self._connected:
298 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("To use a QmpConnection you need to first"
299 91c10532 Andrea Spadaccini
                                   " invoke connect() on it")
300 91c10532 Andrea Spadaccini
301 91c10532 Andrea Spadaccini
  def connect(self):
302 91c10532 Andrea Spadaccini
    """Connects to the QMP monitor.
303 91c10532 Andrea Spadaccini

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

307 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
308 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
309 91c10532 Andrea Spadaccini

310 91c10532 Andrea Spadaccini
    """
311 fc84cd5d Guido Trotter
    if self._connected:
312 fc84cd5d Guido Trotter
      raise errors.ProgrammerError("Cannot connect twice")
313 fc84cd5d Guido Trotter
314 fc84cd5d Guido Trotter
    self._check_socket()
315 fc84cd5d Guido Trotter
316 fc84cd5d Guido Trotter
    # Check file existance/stuff
317 fc84cd5d Guido Trotter
    try:
318 fc84cd5d Guido Trotter
      self.sock.connect(self.monitor_filename)
319 fc84cd5d Guido Trotter
    except EnvironmentError:
320 fc84cd5d Guido Trotter
      raise errors.HypervisorError("Can't connect to qmp socket")
321 91c10532 Andrea Spadaccini
    self._connected = True
322 91c10532 Andrea Spadaccini
323 91c10532 Andrea Spadaccini
    # Check if we receive a correct greeting message from the server
324 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 2.2)
325 91c10532 Andrea Spadaccini
    greeting = self._Recv()
326 91c10532 Andrea Spadaccini
    if not greeting[self._FIRST_MESSAGE_KEY]:
327 91c10532 Andrea Spadaccini
      self._connected = False
328 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("kvm: qmp communication error (wrong"
329 91c10532 Andrea Spadaccini
                                   " server greeting")
330 91c10532 Andrea Spadaccini
331 91c10532 Andrea Spadaccini
    # Let's put the monitor in command mode using the qmp_capabilities
332 91c10532 Andrea Spadaccini
    # command, or else no command will be executable.
333 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 4)
334 91c10532 Andrea Spadaccini
    self.Execute(self._CAPABILITIES_COMMAND)
335 91c10532 Andrea Spadaccini
336 91c10532 Andrea Spadaccini
  def _ParseMessage(self, buf):
337 91c10532 Andrea Spadaccini
    """Extract and parse a QMP message from the given buffer.
338 91c10532 Andrea Spadaccini

339 91c10532 Andrea Spadaccini
    Seeks for a QMP message in the given buf. If found, it parses it and
340 91c10532 Andrea Spadaccini
    returns it together with the rest of the characters in the buf.
341 91c10532 Andrea Spadaccini
    If no message is found, returns None and the whole buffer.
342 91c10532 Andrea Spadaccini

343 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
344 91c10532 Andrea Spadaccini

345 91c10532 Andrea Spadaccini
    """
346 91c10532 Andrea Spadaccini
    message = None
347 91c10532 Andrea Spadaccini
    # Check if we got the message end token (CRLF, as per the QEMU Protocol
348 91c10532 Andrea Spadaccini
    # Specification 0.1 - Section 2.1.1)
349 91c10532 Andrea Spadaccini
    pos = buf.find(self._MESSAGE_END_TOKEN)
350 91c10532 Andrea Spadaccini
    if pos >= 0:
351 91c10532 Andrea Spadaccini
      try:
352 91c10532 Andrea Spadaccini
        message = QmpMessage.BuildFromJsonString(buf[:pos + 1])
353 91c10532 Andrea Spadaccini
      except Exception, err:
354 91c10532 Andrea Spadaccini
        raise errors.ProgrammerError("QMP data serialization error: %s" % err)
355 91c10532 Andrea Spadaccini
      buf = buf[pos + 1:]
356 91c10532 Andrea Spadaccini
357 91c10532 Andrea Spadaccini
    return (message, buf)
358 91c10532 Andrea Spadaccini
359 91c10532 Andrea Spadaccini
  def _Recv(self):
360 91c10532 Andrea Spadaccini
    """Receives a message from QMP and decodes the received JSON object.
361 91c10532 Andrea Spadaccini

362 91c10532 Andrea Spadaccini
    @rtype: QmpMessage
363 91c10532 Andrea Spadaccini
    @return: the received message
364 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
365 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
366 91c10532 Andrea Spadaccini

367 91c10532 Andrea Spadaccini
    """
368 91c10532 Andrea Spadaccini
    self._check_connection()
369 91c10532 Andrea Spadaccini
370 91c10532 Andrea Spadaccini
    # Check if there is already a message in the buffer
371 91c10532 Andrea Spadaccini
    (message, self._buf) = self._ParseMessage(self._buf)
372 91c10532 Andrea Spadaccini
    if message:
373 91c10532 Andrea Spadaccini
      return message
374 91c10532 Andrea Spadaccini
375 91c10532 Andrea Spadaccini
    recv_buffer = StringIO.StringIO(self._buf)
376 91c10532 Andrea Spadaccini
    recv_buffer.seek(len(self._buf))
377 91c10532 Andrea Spadaccini
    try:
378 91c10532 Andrea Spadaccini
      while True:
379 91c10532 Andrea Spadaccini
        data = self.sock.recv(4096)
380 91c10532 Andrea Spadaccini
        if not data:
381 91c10532 Andrea Spadaccini
          break
382 91c10532 Andrea Spadaccini
        recv_buffer.write(data)
383 91c10532 Andrea Spadaccini
384 91c10532 Andrea Spadaccini
        (message, self._buf) = self._ParseMessage(recv_buffer.getvalue())
385 91c10532 Andrea Spadaccini
        if message:
386 91c10532 Andrea Spadaccini
          return message
387 91c10532 Andrea Spadaccini
388 91c10532 Andrea Spadaccini
    except socket.timeout, err:
389 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while receiving a QMP message: "
390 91c10532 Andrea Spadaccini
                                   "%s" % (err))
391 91c10532 Andrea Spadaccini
    except socket.error, err:
392 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to receive data from KVM using the"
393 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
394 91c10532 Andrea Spadaccini
395 91c10532 Andrea Spadaccini
  def _Send(self, message):
396 91c10532 Andrea Spadaccini
    """Encodes and sends a message to KVM using QMP.
397 91c10532 Andrea Spadaccini

398 91c10532 Andrea Spadaccini
    @type message: QmpMessage
399 91c10532 Andrea Spadaccini
    @param message: message to send to KVM
400 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
401 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
402 91c10532 Andrea Spadaccini

403 91c10532 Andrea Spadaccini
    """
404 91c10532 Andrea Spadaccini
    self._check_connection()
405 91c10532 Andrea Spadaccini
    try:
406 91c10532 Andrea Spadaccini
      message_str = str(message)
407 91c10532 Andrea Spadaccini
    except Exception, err:
408 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("QMP data deserialization error: %s" % err)
409 91c10532 Andrea Spadaccini
410 91c10532 Andrea Spadaccini
    try:
411 91c10532 Andrea Spadaccini
      self.sock.sendall(message_str)
412 91c10532 Andrea Spadaccini
    except socket.timeout, err:
413 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while sending a QMP message: "
414 91c10532 Andrea Spadaccini
                                   "%s (%s)" % (err.string, err.errno))
415 91c10532 Andrea Spadaccini
    except socket.error, err:
416 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to send data from KVM using the"
417 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
418 91c10532 Andrea Spadaccini
419 91c10532 Andrea Spadaccini
  def Execute(self, command, arguments=None):
420 91c10532 Andrea Spadaccini
    """Executes a QMP command and returns the response of the server.
421 91c10532 Andrea Spadaccini

422 91c10532 Andrea Spadaccini
    @type command: str
423 91c10532 Andrea Spadaccini
    @param command: the command to execute
424 91c10532 Andrea Spadaccini
    @type arguments: dict
425 91c10532 Andrea Spadaccini
    @param arguments: dictionary of arguments to be passed to the command
426 91c10532 Andrea Spadaccini
    @rtype: dict
427 91c10532 Andrea Spadaccini
    @return: dictionary representing the received JSON object
428 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
429 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
430 91c10532 Andrea Spadaccini

431 91c10532 Andrea Spadaccini
    """
432 91c10532 Andrea Spadaccini
    self._check_connection()
433 91c10532 Andrea Spadaccini
    message = QmpMessage({self._EXECUTE_KEY: command})
434 91c10532 Andrea Spadaccini
    if arguments:
435 91c10532 Andrea Spadaccini
      message[self._ARGUMENTS_KEY] = arguments
436 91c10532 Andrea Spadaccini
    self._Send(message)
437 91c10532 Andrea Spadaccini
438 91c10532 Andrea Spadaccini
    # Events can occur between the sending of the command and the reception
439 91c10532 Andrea Spadaccini
    # of the response, so we need to filter out messages with the event key.
440 91c10532 Andrea Spadaccini
    while True:
441 91c10532 Andrea Spadaccini
      response = self._Recv()
442 91c10532 Andrea Spadaccini
      err = response[self._ERROR_KEY]
443 91c10532 Andrea Spadaccini
      if err:
444 91c10532 Andrea Spadaccini
        raise errors.HypervisorError("kvm: error executing the %s"
445 91c10532 Andrea Spadaccini
                                     " command: %s (%s, %s):" %
446 91c10532 Andrea Spadaccini
                                     (command,
447 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DESC_KEY],
448 91c10532 Andrea Spadaccini
                                      err[self._ERROR_CLASS_KEY],
449 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DATA_KEY]))
450 91c10532 Andrea Spadaccini
451 91c10532 Andrea Spadaccini
      elif not response[self._EVENT_KEY]:
452 91c10532 Andrea Spadaccini
        return response
453 91c10532 Andrea Spadaccini
454 91c10532 Andrea Spadaccini
455 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
456 65107a2f Michael Hanselmann
  """KVM hypervisor interface
457 65107a2f Michael Hanselmann

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

629 98ec75d6 Iustin Pop
    """
630 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
631 98ec75d6 Iustin Pop
632 263b8de6 Guido Trotter
  @classmethod
633 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
634 7548396c Guido Trotter
    """Returns the instance uidfile.
635 7548396c Guido Trotter

636 7548396c Guido Trotter
    """
637 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
638 7548396c Guido Trotter
639 7548396c Guido Trotter
  @classmethod
640 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
641 263b8de6 Guido Trotter
    """Check pid file for instance information.
642 263b8de6 Guido Trotter

643 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
644 263b8de6 Guido Trotter
    information from its command line.
645 263b8de6 Guido Trotter

646 263b8de6 Guido Trotter
    @type pid: string or int
647 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
648 263b8de6 Guido Trotter
    @rtype: tuple
649 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
650 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
651 263b8de6 Guido Trotter

652 263b8de6 Guido Trotter
    """
653 263b8de6 Guido Trotter
    alive = utils.IsProcessAlive(pid)
654 263b8de6 Guido Trotter
    if not alive:
655 263b8de6 Guido Trotter
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
656 263b8de6 Guido Trotter
657 263b8de6 Guido Trotter
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
658 263b8de6 Guido Trotter
    try:
659 263b8de6 Guido Trotter
      cmdline = utils.ReadFile(cmdline_file)
660 263b8de6 Guido Trotter
    except EnvironmentError, err:
661 263b8de6 Guido Trotter
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
662 263b8de6 Guido Trotter
                                   (pid, err))
663 263b8de6 Guido Trotter
664 263b8de6 Guido Trotter
    instance = None
665 263b8de6 Guido Trotter
    memory = 0
666 263b8de6 Guido Trotter
    vcpus = 0
667 263b8de6 Guido Trotter
668 d0c8c01d Iustin Pop
    arg_list = cmdline.split("\x00")
669 263b8de6 Guido Trotter
    while arg_list:
670 e687ec01 Michael Hanselmann
      arg = arg_list.pop(0)
671 263b8de6 Guido Trotter
      if arg == "-name":
672 263b8de6 Guido Trotter
        instance = arg_list.pop(0)
673 263b8de6 Guido Trotter
      elif arg == "-m":
674 263b8de6 Guido Trotter
        memory = int(arg_list.pop(0))
675 263b8de6 Guido Trotter
      elif arg == "-smp":
676 4888a609 Guido Trotter
        vcpus = int(arg_list.pop(0).split(",")[0])
677 263b8de6 Guido Trotter
678 263b8de6 Guido Trotter
    if instance is None:
679 263b8de6 Guido Trotter
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
680 263b8de6 Guido Trotter
                                   " instance" % pid)
681 263b8de6 Guido Trotter
682 263b8de6 Guido Trotter
    return (instance, memory, vcpus)
683 263b8de6 Guido Trotter
684 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
685 263b8de6 Guido Trotter
    """Returns the instance pidfile, pid, and liveness.
686 263b8de6 Guido Trotter

687 263b8de6 Guido Trotter
    @type instance_name: string
688 263b8de6 Guido Trotter
    @param instance_name: instance name
689 263b8de6 Guido Trotter
    @rtype: tuple
690 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
691 1f8b3a27 Guido Trotter

692 1f8b3a27 Guido Trotter
    """
693 98ec75d6 Iustin Pop
    pidfile = self._InstancePidFile(instance_name)
694 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
695 263b8de6 Guido Trotter
696 263b8de6 Guido Trotter
    alive = False
697 263b8de6 Guido Trotter
    try:
698 263b8de6 Guido Trotter
      cmd_instance = self._InstancePidInfo(pid)[0]
699 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
700 263b8de6 Guido Trotter
    except errors.HypervisorError:
701 263b8de6 Guido Trotter
      pass
702 1f8b3a27 Guido Trotter
703 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
704 1f8b3a27 Guido Trotter
705 5905901c Iustin Pop
  def _CheckDown(self, instance_name):
706 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
707 5905901c Iustin Pop

708 5905901c Iustin Pop
    """
709 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
710 5905901c Iustin Pop
    if alive:
711 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
712 5905901c Iustin Pop
                                   (instance_name, "already running"))
713 5905901c Iustin Pop
714 0df4d98a Guido Trotter
  @classmethod
715 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
716 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
717 c4fbefc8 Guido Trotter

718 c4fbefc8 Guido Trotter
    """
719 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
720 c4fbefc8 Guido Trotter
721 0df4d98a Guido Trotter
  @classmethod
722 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
723 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
724 c4fbefc8 Guido Trotter

725 c4fbefc8 Guido Trotter
    """
726 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
727 c4fbefc8 Guido Trotter
728 91c10532 Andrea Spadaccini
  @classmethod
729 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
730 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
731 91c10532 Andrea Spadaccini

732 91c10532 Andrea Spadaccini
    """
733 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
734 91c10532 Andrea Spadaccini
735 86d6bc2a Guido Trotter
  @staticmethod
736 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
737 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
738 86d6bc2a Guido Trotter

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

741 86d6bc2a Guido Trotter
    """
742 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
743 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
744 86d6bc2a Guido Trotter
    else:
745 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
746 86d6bc2a Guido Trotter
747 0df4d98a Guido Trotter
  @classmethod
748 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
749 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
750 38e250ba Guido Trotter

751 38e250ba Guido Trotter
    """
752 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
753 38e250ba Guido Trotter
754 7e66c35b Guido Trotter
  @classmethod
755 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
756 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
757 547a63b7 Balazs Lecz

758 547a63b7 Balazs Lecz
    """
759 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
760 547a63b7 Balazs Lecz
761 547a63b7 Balazs Lecz
  @classmethod
762 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
763 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
764 5d9bfd87 Apollon Oikonomopoulos
    given instance.
765 5d9bfd87 Apollon Oikonomopoulos

766 5d9bfd87 Apollon Oikonomopoulos
    """
767 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
768 5d9bfd87 Apollon Oikonomopoulos
769 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
770 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
771 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
772 5d9bfd87 Apollon Oikonomopoulos

773 5d9bfd87 Apollon Oikonomopoulos
    """
774 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
775 5d9bfd87 Apollon Oikonomopoulos
776 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
777 4f580fef Sébastien Bocahu
  def _InstanceKeymapFile(cls, instance_name):
778 4f580fef Sébastien Bocahu
    """Returns the name of the file containing the keymap for a given instance
779 4f580fef Sébastien Bocahu

780 4f580fef Sébastien Bocahu
    """
781 4f580fef Sébastien Bocahu
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
782 4f580fef Sébastien Bocahu
783 4f580fef Sébastien Bocahu
  @classmethod
784 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
785 7548396c Guido Trotter
    """Try to read a uid file
786 7548396c Guido Trotter

787 7548396c Guido Trotter
    """
788 7548396c Guido Trotter
    if os.path.exists(uid_file):
789 7548396c Guido Trotter
      try:
790 682f7601 Guido Trotter
        uid = int(utils.ReadOneLineFile(uid_file))
791 aa0b600b Guido Trotter
        return uid
792 7548396c Guido Trotter
      except EnvironmentError:
793 7548396c Guido Trotter
        logging.warning("Can't read uid file", exc_info=True)
794 7548396c Guido Trotter
      except (TypeError, ValueError):
795 7548396c Guido Trotter
        logging.warning("Can't parse uid file contents", exc_info=True)
796 aa0b600b Guido Trotter
    return None
797 7548396c Guido Trotter
798 7548396c Guido Trotter
  @classmethod
799 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
800 547a63b7 Balazs Lecz
    """Removes an instance's rutime sockets/files/dirs.
801 7e66c35b Guido Trotter

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

842 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
843 eb58f9b1 Guido Trotter
    @type instance: instance object
844 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
845 eb58f9b1 Guido Trotter
    @type seq: int
846 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
847 eb58f9b1 Guido Trotter
    @type nic: nic object
848 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
849 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
850 eb58f9b1 Guido Trotter

851 eb58f9b1 Guido Trotter
    """
852 5d9bfd87 Apollon Oikonomopoulos
    if instance.tags:
853 5d9bfd87 Apollon Oikonomopoulos
      tags = " ".join(instance.tags)
854 5d9bfd87 Apollon Oikonomopoulos
    else:
855 5d9bfd87 Apollon Oikonomopoulos
      tags = ""
856 5d9bfd87 Apollon Oikonomopoulos
857 5d9bfd87 Apollon Oikonomopoulos
    env = {
858 5d9bfd87 Apollon Oikonomopoulos
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
859 5d9bfd87 Apollon Oikonomopoulos
      "INSTANCE": instance.name,
860 5d9bfd87 Apollon Oikonomopoulos
      "MAC": nic.mac,
861 5d9bfd87 Apollon Oikonomopoulos
      "MODE": nic.nicparams[constants.NIC_MODE],
862 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE": tap,
863 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE_INDEX": str(seq),
864 5d9bfd87 Apollon Oikonomopoulos
      "TAGS": tags,
865 5d9bfd87 Apollon Oikonomopoulos
    }
866 5d9bfd87 Apollon Oikonomopoulos
867 5d9bfd87 Apollon Oikonomopoulos
    if nic.ip:
868 5d9bfd87 Apollon Oikonomopoulos
      env["IP"] = nic.ip
869 5d9bfd87 Apollon Oikonomopoulos
870 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_LINK]:
871 5d9bfd87 Apollon Oikonomopoulos
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
872 5d9bfd87 Apollon Oikonomopoulos
873 a5ad5e58 Apollon Oikonomopoulos
    if nic.network:
874 cbe4a0a5 Dimitris Aragiorgis
      n = objects.Network.FromDict(nic.netinfo)
875 cbe4a0a5 Dimitris Aragiorgis
      _BuildNetworkEnv(nic.network, n.network, n.gateway,
876 cbe4a0a5 Dimitris Aragiorgis
                       n.network6, n.gateway6, n.network_type,
877 cbe4a0a5 Dimitris Aragiorgis
                       n.mac_prefix, n.tags, env)
878 a5ad5e58 Apollon Oikonomopoulos
879 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
880 5d9bfd87 Apollon Oikonomopoulos
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
881 5d9bfd87 Apollon Oikonomopoulos
882 9d9bded1 Michael Hanselmann
    result = utils.RunCmd([pathutils.KVM_IFUP, tap], env=env)
883 5d9bfd87 Apollon Oikonomopoulos
    if result.failed:
884 5d9bfd87 Apollon Oikonomopoulos
      raise errors.HypervisorError("Failed to configure interface %s: %s."
885 5d9bfd87 Apollon Oikonomopoulos
                                   " Network configuration script output: %s" %
886 5d9bfd87 Apollon Oikonomopoulos
                                   (tap, result.fail_reason, result.output))
887 eb58f9b1 Guido Trotter
888 b693125f Tsachy Shacham
  @staticmethod
889 b693125f Tsachy Shacham
  def _VerifyAffinityPackage():
890 b693125f Tsachy Shacham
    if affinity is None:
891 b693125f Tsachy Shacham
      raise errors.HypervisorError("affinity Python package not"
892 5ae4945a Iustin Pop
                                   " found; cannot use CPU pinning under KVM")
893 b693125f Tsachy Shacham
894 b693125f Tsachy Shacham
  @staticmethod
895 b693125f Tsachy Shacham
  def _BuildAffinityCpuMask(cpu_list):
896 b693125f Tsachy Shacham
    """Create a CPU mask suitable for sched_setaffinity from a list of
897 b693125f Tsachy Shacham
    CPUs.
898 b693125f Tsachy Shacham

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

902 b693125f Tsachy Shacham
    @type cpu_list: list of int
903 b693125f Tsachy Shacham
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
904 b693125f Tsachy Shacham
    @rtype: int
905 b693125f Tsachy Shacham
    @return: a bit mask of CPU affinities
906 b693125f Tsachy Shacham

907 b693125f Tsachy Shacham
    """
908 b693125f Tsachy Shacham
    if cpu_list == constants.CPU_PINNING_OFF:
909 b693125f Tsachy Shacham
      return constants.CPU_PINNING_ALL_KVM
910 b693125f Tsachy Shacham
    else:
911 b693125f Tsachy Shacham
      return sum(2 ** cpu for cpu in cpu_list)
912 b693125f Tsachy Shacham
913 b693125f Tsachy Shacham
  @classmethod
914 b693125f Tsachy Shacham
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
915 b693125f Tsachy Shacham
    """Change CPU affinity for running VM according to given CPU mask.
916 b693125f Tsachy Shacham

917 b693125f Tsachy Shacham
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
918 b693125f Tsachy Shacham
    @type cpu_mask: string
919 b693125f Tsachy Shacham
    @param process_id: process ID of KVM process. Used to pin entire VM
920 b693125f Tsachy Shacham
                       to physical CPUs.
921 b693125f Tsachy Shacham
    @type process_id: int
922 b693125f Tsachy Shacham
    @param thread_dict: map of virtual CPUs to KVM thread IDs
923 b693125f Tsachy Shacham
    @type thread_dict: dict int:int
924 b693125f Tsachy Shacham

925 b693125f Tsachy Shacham
    """
926 b693125f Tsachy Shacham
    # Convert the string CPU mask to a list of list of int's
927 b693125f Tsachy Shacham
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
928 b693125f Tsachy Shacham
929 b693125f Tsachy Shacham
    if len(cpu_list) == 1:
930 b693125f Tsachy Shacham
      all_cpu_mapping = cpu_list[0]
931 b693125f Tsachy Shacham
      if all_cpu_mapping == constants.CPU_PINNING_OFF:
932 b693125f Tsachy Shacham
        # If CPU pinning has 1 entry that's "all", then do nothing
933 b693125f Tsachy Shacham
        pass
934 b693125f Tsachy Shacham
      else:
935 b693125f Tsachy Shacham
        # If CPU pinning has one non-all entry, map the entire VM to
936 b693125f Tsachy Shacham
        # one set of physical CPUs
937 b693125f Tsachy Shacham
        cls._VerifyAffinityPackage()
938 5ae4945a Iustin Pop
        affinity.set_process_affinity_mask(
939 5ae4945a Iustin Pop
          process_id, cls._BuildAffinityCpuMask(all_cpu_mapping))
940 b693125f Tsachy Shacham
    else:
941 b693125f Tsachy Shacham
      # The number of vCPUs mapped should match the number of vCPUs
942 b693125f Tsachy Shacham
      # reported by KVM. This was already verified earlier, so
943 b693125f Tsachy Shacham
      # here only as a sanity check.
944 b693125f Tsachy Shacham
      assert len(thread_dict) == len(cpu_list)
945 b693125f Tsachy Shacham
      cls._VerifyAffinityPackage()
946 b693125f Tsachy Shacham
947 b693125f Tsachy Shacham
      # For each vCPU, map it to the proper list of physical CPUs
948 b693125f Tsachy Shacham
      for vcpu, i in zip(cpu_list, range(len(cpu_list))):
949 b693125f Tsachy Shacham
        affinity.set_process_affinity_mask(thread_dict[i],
950 5ae4945a Iustin Pop
                                           cls._BuildAffinityCpuMask(vcpu))
951 b693125f Tsachy Shacham
952 b693125f Tsachy Shacham
  def _GetVcpuThreadIds(self, instance_name):
953 b693125f Tsachy Shacham
    """Get a mapping of vCPU no. to thread IDs for the instance
954 b693125f Tsachy Shacham

955 b693125f Tsachy Shacham
    @type instance_name: string
956 b693125f Tsachy Shacham
    @param instance_name: instance in question
957 b693125f Tsachy Shacham
    @rtype: dictionary of int:int
958 b693125f Tsachy Shacham
    @return: a dictionary mapping vCPU numbers to thread IDs
959 b693125f Tsachy Shacham

960 b693125f Tsachy Shacham
    """
961 b693125f Tsachy Shacham
    result = {}
962 b693125f Tsachy Shacham
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
963 b693125f Tsachy Shacham
    for line in output.stdout.splitlines():
964 b693125f Tsachy Shacham
      match = self._CPU_INFO_RE.search(line)
965 b693125f Tsachy Shacham
      if not match:
966 b693125f Tsachy Shacham
        continue
967 b693125f Tsachy Shacham
      grp = map(int, match.groups())
968 b693125f Tsachy Shacham
      result[grp[0]] = grp[1]
969 b693125f Tsachy Shacham
970 b693125f Tsachy Shacham
    return result
971 b693125f Tsachy Shacham
972 1d8a7812 Andrea Spadaccini
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
973 1d8a7812 Andrea Spadaccini
    """Complete CPU pinning.
974 b693125f Tsachy Shacham

975 b693125f Tsachy Shacham
    @type instance_name: string
976 b693125f Tsachy Shacham
    @param instance_name: name of instance
977 b693125f Tsachy Shacham
    @type cpu_mask: string
978 b693125f Tsachy Shacham
    @param cpu_mask: CPU pinning mask as entered by user
979 b693125f Tsachy Shacham

980 b693125f Tsachy Shacham
    """
981 1d8a7812 Andrea Spadaccini
    # Get KVM process ID, to be used if need to pin entire VM
982 1d8a7812 Andrea Spadaccini
    _, pid, _ = self._InstancePidAlive(instance_name)
983 1d8a7812 Andrea Spadaccini
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
984 1d8a7812 Andrea Spadaccini
    thread_dict = self._GetVcpuThreadIds(instance_name)
985 1d8a7812 Andrea Spadaccini
    # Run CPU pinning, based on configured mask
986 1d8a7812 Andrea Spadaccini
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
987 b693125f Tsachy Shacham
988 eb58f9b1 Guido Trotter
  def ListInstances(self):
989 eb58f9b1 Guido Trotter
    """Get the list of running instances.
990 eb58f9b1 Guido Trotter

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

994 eb58f9b1 Guido Trotter
    """
995 eb58f9b1 Guido Trotter
    result = []
996 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
997 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
998 eb58f9b1 Guido Trotter
        result.append(name)
999 eb58f9b1 Guido Trotter
    return result
1000 eb58f9b1 Guido Trotter
1001 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
1002 eb58f9b1 Guido Trotter
    """Get instance properties.
1003 eb58f9b1 Guido Trotter

1004 4fbb3c60 Guido Trotter
    @type instance_name: string
1005 c41eea6e Iustin Pop
    @param instance_name: the instance name
1006 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
1007 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
1008 eb58f9b1 Guido Trotter

1009 eb58f9b1 Guido Trotter
    """
1010 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
1011 1f8b3a27 Guido Trotter
    if not alive:
1012 eb58f9b1 Guido Trotter
      return None
1013 eb58f9b1 Guido Trotter
1014 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
1015 fc84cd5d Guido Trotter
    istat = "---b-"
1016 eb58f9b1 Guido Trotter
    times = "0"
1017 eb58f9b1 Guido Trotter
1018 89da2ff3 Guido Trotter
    try:
1019 89da2ff3 Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
1020 89da2ff3 Guido Trotter
      qmp.connect()
1021 89da2ff3 Guido Trotter
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
1022 89da2ff3 Guido Trotter
      # Will fail if ballooning is not enabled, but we can then just resort to
1023 89da2ff3 Guido Trotter
      # the value above.
1024 89da2ff3 Guido Trotter
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
1025 89da2ff3 Guido Trotter
      memory = mem_bytes / 1048576
1026 89da2ff3 Guido Trotter
    except errors.HypervisorError:
1027 89da2ff3 Guido Trotter
      pass
1028 89da2ff3 Guido Trotter
1029 fc84cd5d Guido Trotter
    return (instance_name, pid, memory, vcpus, istat, times)
1030 eb58f9b1 Guido Trotter
1031 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
1032 eb58f9b1 Guido Trotter
    """Get properties of all instances.
1033 eb58f9b1 Guido Trotter

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

1036 eb58f9b1 Guido Trotter
    """
1037 eb58f9b1 Guido Trotter
    data = []
1038 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
1039 263b8de6 Guido Trotter
      try:
1040 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
1041 263b8de6 Guido Trotter
      except errors.HypervisorError:
1042 3bc145d8 Bernardo Dal Seno
        # Ignore exceptions due to instances being shut down
1043 263b8de6 Guido Trotter
        continue
1044 263b8de6 Guido Trotter
      if info:
1045 263b8de6 Guido Trotter
        data.append(info)
1046 eb58f9b1 Guido Trotter
    return data
1047 eb58f9b1 Guido Trotter
1048 b73f1c59 Guido Trotter
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused,
1049 b73f1c59 Guido Trotter
                          kvmhelp):
1050 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
1051 eb58f9b1 Guido Trotter

1052 b73f1c59 Guido Trotter
    @type kvmhelp: string
1053 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1054 839642c2 Iustin Pop
    @attention: this function must not have any side-effects; for
1055 839642c2 Iustin Pop
        example, it must not write to the filesystem, or read values
1056 839642c2 Iustin Pop
        from the current system the are expected to differ between
1057 839642c2 Iustin Pop
        nodes, since it is only run once at instance startup;
1058 839642c2 Iustin Pop
        actions/kvm arguments that can vary between systems should be
1059 839642c2 Iustin Pop
        done in L{_ExecuteKVMRuntime}
1060 839642c2 Iustin Pop

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

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

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

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

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

1451 76431533 Guido Trotter
    @type name: string
1452 76431533 Guido Trotter
    @param name: instance name
1453 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1454 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1455 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1456 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1457 76431533 Guido Trotter

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

1474 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1475 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1476 b73f1c59 Guido Trotter
    @type kvmhelp: string
1477 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1478 30e42c4e Guido Trotter

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

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

1694 6567aff3 Guido Trotter
    """
1695 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1696 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
1697 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
1698 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1699 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
1700 6567aff3 Guido Trotter
    if result.failed:
1701 6567aff3 Guido Trotter
      msg = ("Failed to send command '%s' to instance %s."
1702 6567aff3 Guido Trotter
             " output: %s, error: %s, fail_reason: %s" %
1703 9798fcae Guido Trotter
             (command, instance_name,
1704 9798fcae Guido Trotter
              result.stdout, result.stderr, result.fail_reason))
1705 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
1706 6567aff3 Guido Trotter
1707 6567aff3 Guido Trotter
    return result
1708 6567aff3 Guido Trotter
1709 b52d85c1 Guido Trotter
  @classmethod
1710 585c8187 Guido Trotter
  def _ParseKVMVersion(cls, text):
1711 585c8187 Guido Trotter
    """Parse the KVM version from the --help output.
1712 585c8187 Guido Trotter

1713 585c8187 Guido Trotter
    @type text: string
1714 585c8187 Guido Trotter
    @param text: output of kvm --help
1715 585c8187 Guido Trotter
    @return: (version, v_maj, v_min, v_rev)
1716 5c3d5dfd Iustin Pop
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1717 585c8187 Guido Trotter

1718 585c8187 Guido Trotter
    """
1719 585c8187 Guido Trotter
    match = cls._VERSION_RE.search(text.splitlines()[0])
1720 585c8187 Guido Trotter
    if not match:
1721 585c8187 Guido Trotter
      raise errors.HypervisorError("Unable to get KVM version")
1722 585c8187 Guido Trotter
1723 585c8187 Guido Trotter
    v_all = match.group(0)
1724 585c8187 Guido Trotter
    v_maj = int(match.group(1))
1725 585c8187 Guido Trotter
    v_min = int(match.group(2))
1726 585c8187 Guido Trotter
    if match.group(4):
1727 585c8187 Guido Trotter
      v_rev = int(match.group(4))
1728 585c8187 Guido Trotter
    else:
1729 585c8187 Guido Trotter
      v_rev = 0
1730 585c8187 Guido Trotter
    return (v_all, v_maj, v_min, v_rev)
1731 585c8187 Guido Trotter
1732 585c8187 Guido Trotter
  @classmethod
1733 6e043e60 Guido Trotter
  def _GetKVMOutput(cls, kvm_path, option):
1734 6e043e60 Guido Trotter
    """Return the output of a kvm invocation
1735 e3b89628 Guido Trotter

1736 bc0fed4b Guido Trotter
    @type kvm_path: string
1737 bc0fed4b Guido Trotter
    @param kvm_path: path to the kvm executable
1738 bc0fed4b Guido Trotter
    @type option: a key of _KVMOPTS_CMDS
1739 bc0fed4b Guido Trotter
    @param option: kvm option to fetch the output from
1740 6e043e60 Guido Trotter
    @return: output a supported kvm invocation
1741 e3b89628 Guido Trotter
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
1742 e3b89628 Guido Trotter

1743 e3b89628 Guido Trotter
    """
1744 6e043e60 Guido Trotter
    assert option in cls._KVMOPTS_CMDS, "Invalid output option"
1745 6e043e60 Guido Trotter
1746 bc0fed4b Guido Trotter
    optlist, can_fail = cls._KVMOPTS_CMDS[option]
1747 bc0fed4b Guido Trotter
1748 bc0fed4b Guido Trotter
    result = utils.RunCmd([kvm_path] + optlist)
1749 bc0fed4b Guido Trotter
    if result.failed and not can_fail:
1750 af89fa76 Helga Velroyen
      raise errors.HypervisorError("Unable to get KVM %s output" %
1751 af89fa76 Helga Velroyen
                                    " ".join(cls._KVMOPTS_CMDS[option]))
1752 e3b89628 Guido Trotter
    return result.output
1753 e3b89628 Guido Trotter
1754 e3b89628 Guido Trotter
  @classmethod
1755 3b59ec02 Guido Trotter
  def _GetKVMVersion(cls, kvm_path):
1756 d7e4a2b1 Andrea Spadaccini
    """Return the installed KVM version.
1757 b52d85c1 Guido Trotter

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

1761 b52d85c1 Guido Trotter
    """
1762 6e043e60 Guido Trotter
    return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
1763 82e3bf85 Dimitris Aragiorgis
1764 82e3bf85 Dimitris Aragiorgis
  @classmethod
1765 82e3bf85 Dimitris Aragiorgis
  def _GetDefaultMachineVersion(cls, kvm_path):
1766 82e3bf85 Dimitris Aragiorgis
    """Return the default hardware revision (e.g. pc-1.1)
1767 82e3bf85 Dimitris Aragiorgis

1768 82e3bf85 Dimitris Aragiorgis
    """
1769 6e043e60 Guido Trotter
    output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
1770 82e3bf85 Dimitris Aragiorgis
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
1771 82e3bf85 Dimitris Aragiorgis
    if match:
1772 82e3bf85 Dimitris Aragiorgis
      return match.group(1)
1773 82e3bf85 Dimitris Aragiorgis
    else:
1774 82e3bf85 Dimitris Aragiorgis
      return "pc"
1775 82e3bf85 Dimitris Aragiorgis
1776 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
1777 eb58f9b1 Guido Trotter
    """Stop an instance.
1778 eb58f9b1 Guido Trotter

1779 eb58f9b1 Guido Trotter
    """
1780 bbcf7ad0 Iustin Pop
    if name is not None and not force:
1781 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
1782 bbcf7ad0 Iustin Pop
    if name is None:
1783 bbcf7ad0 Iustin Pop
      name = instance.name
1784 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
1785 bbcf7ad0 Iustin Pop
    else:
1786 bbcf7ad0 Iustin Pop
      acpi = False
1787 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
1788 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
1789 bbcf7ad0 Iustin Pop
      if force or not acpi:
1790 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
1791 eb58f9b1 Guido Trotter
      else:
1792 d0c8c01d Iustin Pop
        self._CallMonitorCommand(name, "system_powerdown")
1793 eb58f9b1 Guido Trotter
1794 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
1795 8904b35c Guido Trotter
    """Cleanup after a stopped instance
1796 8904b35c Guido Trotter

1797 8904b35c Guido Trotter
    """
1798 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1799 8904b35c Guido Trotter
    if pid > 0 and alive:
1800 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
1801 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1802 eb58f9b1 Guido Trotter
1803 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
1804 eb58f9b1 Guido Trotter
    """Reboot an instance.
1805 eb58f9b1 Guido Trotter

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

1829 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1830 30e42c4e Guido Trotter
    @param instance: instance to be migrated
1831 30e42c4e Guido Trotter
    @rtype: string
1832 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
1833 30e42c4e Guido Trotter

1834 30e42c4e Guido Trotter
    """
1835 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
1836 30e42c4e Guido Trotter
1837 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
1838 30e42c4e Guido Trotter
    """Prepare to accept an instance.
1839 30e42c4e Guido Trotter

1840 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1841 30e42c4e Guido Trotter
    @param instance: instance to be accepted
1842 30e42c4e Guido Trotter
    @type info: string
1843 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
1844 30e42c4e Guido Trotter
    @type target: string
1845 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
1846 30e42c4e Guido Trotter

1847 30e42c4e Guido Trotter
    """
1848 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1849 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1850 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1851 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1852 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
1853 b73f1c59 Guido Trotter
                            incoming=incoming_address)
1854 30e42c4e Guido Trotter
1855 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
1856 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
1857 30e42c4e Guido Trotter

1858 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
1859 30e42c4e Guido Trotter

1860 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1861 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
1862 30e42c4e Guido Trotter

1863 30e42c4e Guido Trotter
    """
1864 30e42c4e Guido Trotter
    if success:
1865 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1866 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
1867 5d9bfd87 Apollon Oikonomopoulos
1868 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
1869 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1870 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
1871 cc8a8ed7 Apollon Oikonomopoulos
          continue
1872 5d9bfd87 Apollon Oikonomopoulos
        try:
1873 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
1874 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
1875 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
1876 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
1877 5d9bfd87 Apollon Oikonomopoulos
          continue
1878 5d9bfd87 Apollon Oikonomopoulos
        try:
1879 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
1880 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
1881 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
1882 5d9bfd87 Apollon Oikonomopoulos
1883 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
1884 30e42c4e Guido Trotter
    else:
1885 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
1886 30e42c4e Guido Trotter
1887 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
1888 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
1889 30e42c4e Guido Trotter

1890 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
1891 30e42c4e Guido Trotter
    currently running.
1892 30e42c4e Guido Trotter

1893 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
1894 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
1895 30e42c4e Guido Trotter
    @type target: string
1896 30e42c4e Guido Trotter
    @param target: ip address of the target node
1897 30e42c4e Guido Trotter
    @type live: boolean
1898 30e42c4e Guido Trotter
    @param live: perform a live migration
1899 30e42c4e Guido Trotter

1900 30e42c4e Guido Trotter
    """
1901 58d38b02 Iustin Pop
    instance_name = instance.name
1902 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
1903 6a1434d7 Andrea Spadaccini
    _, _, alive = self._InstancePidAlive(instance_name)
1904 30e42c4e Guido Trotter
    if not alive:
1905 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
1906 30e42c4e Guido Trotter
1907 30e42c4e Guido Trotter
    if not live:
1908 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
1909 30e42c4e Guido Trotter
1910 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
1911 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1912 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
1913 e43d4f9f Apollon Oikonomopoulos
1914 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
1915 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
1916 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
1917 e43d4f9f Apollon Oikonomopoulos
1918 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
1919 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
1920 30e42c4e Guido Trotter
1921 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
1922 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
1923 6a1434d7 Andrea Spadaccini

1924 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
1925 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
1926 6a1434d7 Andrea Spadaccini
    @type success: bool
1927 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
1928 6a1434d7 Andrea Spadaccini
    @type live: bool
1929 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
1930 6a1434d7 Andrea Spadaccini

1931 6a1434d7 Andrea Spadaccini
    """
1932 6a1434d7 Andrea Spadaccini
    if success:
1933 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
1934 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
1935 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
1936 6a1434d7 Andrea Spadaccini
    elif live:
1937 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1938 6a1434d7 Andrea Spadaccini
1939 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
1940 6a1434d7 Andrea Spadaccini
    """Get the migration status
1941 6a1434d7 Andrea Spadaccini

1942 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
1943 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
1944 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
1945 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
1946 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
1947 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
1948 6a1434d7 Andrea Spadaccini

1949 6a1434d7 Andrea Spadaccini
    """
1950 d0c8c01d Iustin Pop
    info_command = "info migrate"
1951 6a1434d7 Andrea Spadaccini
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
1952 6a1434d7 Andrea Spadaccini
      result = self._CallMonitorCommand(instance.name, info_command)
1953 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
1954 30e42c4e Guido Trotter
      if not match:
1955 c4e388a5 Guido Trotter
        if not result.stdout:
1956 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
1957 c4e388a5 Guido Trotter
        else:
1958 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
1959 c4e388a5 Guido Trotter
                          result.stdout)
1960 30e42c4e Guido Trotter
      else:
1961 30e42c4e Guido Trotter
        status = match.group(1)
1962 6a1434d7 Andrea Spadaccini
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
1963 6a1434d7 Andrea Spadaccini
          migration_status = objects.MigrationStatus(status=status)
1964 61643226 Andrea Spadaccini
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
1965 61643226 Andrea Spadaccini
          if match:
1966 61643226 Andrea Spadaccini
            migration_status.transferred_ram = match.group("transferred")
1967 61643226 Andrea Spadaccini
            migration_status.total_ram = match.group("total")
1968 61643226 Andrea Spadaccini
1969 6a1434d7 Andrea Spadaccini
          return migration_status
1970 30e42c4e Guido Trotter
1971 6a1434d7 Andrea Spadaccini
        logging.warning("KVM: unknown migration status '%s'", status)
1972 6a1434d7 Andrea Spadaccini
1973 6a1434d7 Andrea Spadaccini
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1974 6a1434d7 Andrea Spadaccini
1975 62457f51 Iustin Pop
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
1976 30e42c4e Guido Trotter
1977 3d836750 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
1978 3d836750 Guido Trotter
    """Balloon an instance memory to a certain value.
1979 3d836750 Guido Trotter

1980 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
1981 3d836750 Guido Trotter
    @param instance: instance to be accepted
1982 3d836750 Guido Trotter
    @type mem: int
1983 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
1984 3d836750 Guido Trotter

1985 3d836750 Guido Trotter
    """
1986 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
1987 3d836750 Guido Trotter
1988 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
1989 eb58f9b1 Guido Trotter
    """Return information about the node.
1990 eb58f9b1 Guido Trotter

1991 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
1992 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
1993 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
1994 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
1995 34fbc862 Andrea Spadaccini
          - hv_version: the hypervisor version in the form (major, minor,
1996 34fbc862 Andrea Spadaccini
                        revision)
1997 eb58f9b1 Guido Trotter

1998 eb58f9b1 Guido Trotter
    """
1999 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
2000 4b9638dc Guido Trotter
    # FIXME: this is the global kvm version, but the actual version can be
2001 4b9638dc Guido Trotter
    # customized as an hv parameter. we should use the nodegroup's default kvm
2002 4b9638dc Guido Trotter
    # path parameter here.
2003 3b59ec02 Guido Trotter
    _, v_major, v_min, v_rev = self._GetKVMVersion(constants.KVM_PATH)
2004 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2005 34fbc862 Andrea Spadaccini
    return result
2006 eb58f9b1 Guido Trotter
2007 637ce7f9 Guido Trotter
  @classmethod
2008 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
2009 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
2010 eb58f9b1 Guido Trotter

2011 eb58f9b1 Guido Trotter
    """
2012 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2013 9d9bded1 Michael Hanselmann
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
2014 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2015 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2016 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
2017 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2018 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2019 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
2020 55cc0a44 Michael Hanselmann
                                     host=instance.primary_node,
2021 052783ff Michael Hanselmann
                                     user=constants.SSH_CONSOLE_USER,
2022 55cc0a44 Michael Hanselmann
                                     command=cmd)
2023 3be34f57 Guido Trotter
2024 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2025 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2026 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
2027 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2028 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
2029 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
2030 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
2031 55cc0a44 Michael Hanselmann
                                     display=display)
2032 55cc0a44 Michael Hanselmann
2033 4d2cdb5a Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2034 4d2cdb5a Andrea Spadaccini
    if spice_bind:
2035 4d2cdb5a Andrea Spadaccini
      return objects.InstanceConsole(instance=instance.name,
2036 4d2cdb5a Andrea Spadaccini
                                     kind=constants.CONS_SPICE,
2037 4d2cdb5a Andrea Spadaccini
                                     host=spice_bind,
2038 4d2cdb5a Andrea Spadaccini
                                     port=instance.network_port)
2039 4d2cdb5a Andrea Spadaccini
2040 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
2041 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
2042 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
2043 55cc0a44 Michael Hanselmann
                                            instance.name))
2044 eb58f9b1 Guido Trotter
2045 eb58f9b1 Guido Trotter
  def Verify(self):
2046 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
2047 eb58f9b1 Guido Trotter

2048 cd04dfd2 Michael Hanselmann
    Check that the required binaries exist.
2049 cd04dfd2 Michael Hanselmann

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

2052 eb58f9b1 Guido Trotter
    """
2053 4b9638dc Guido Trotter
    # FIXME: this is the global kvm version, but the actual version can be
2054 4b9638dc Guido Trotter
    # customized as an hv parameter. we should use the nodegroup's default kvm
2055 4b9638dc Guido Trotter
    # path parameter here.
2056 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
2057 cd04dfd2 Michael Hanselmann
      return "The KVM binary ('%s') does not exist" % constants.KVM_PATH
2058 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2059 cd04dfd2 Michael Hanselmann
      return "The socat binary ('%s') does not exist" % constants.SOCAT_PATH
2060 cd04dfd2 Michael Hanselmann
    return None
2061 14aa53cb Guido Trotter
2062 6b5605e8 Iustin Pop
  @classmethod
2063 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2064 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2065 6b5605e8 Iustin Pop

2066 6b5605e8 Iustin Pop
    @type hvparams:  dict
2067 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2068 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2069 6b5605e8 Iustin Pop

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

2139 d19d94db Guido Trotter
    @type hvparams:  dict
2140 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2141 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2142 d19d94db Guido Trotter

2143 d19d94db Guido Trotter
    """
2144 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2145 d19d94db Guido Trotter
2146 82e3bf85 Dimitris Aragiorgis
    kvm_path = hvparams[constants.HV_KVM_PATH]
2147 82e3bf85 Dimitris Aragiorgis
2148 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2149 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2150 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2151 d19d94db Guido Trotter
      try:
2152 1feb39ec Guido Trotter
        pwd.getpwnam(username)
2153 d19d94db Guido Trotter
      except KeyError:
2154 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
2155 d19d94db Guido Trotter
                                     % username)
2156 d19d94db Guido Trotter
2157 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2158 b1cb62bd Andrea Spadaccini
    if spice_bind:
2159 b1cb62bd Andrea Spadaccini
      # only one of VNC and SPICE can be used currently.
2160 b1cb62bd Andrea Spadaccini
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2161 b1cb62bd Andrea Spadaccini
        raise errors.HypervisorError("both SPICE and VNC are configured, but"
2162 b1cb62bd Andrea Spadaccini
                                     " only one of them can be used at a"
2163 b1cb62bd Andrea Spadaccini
                                     " given time.")
2164 b1cb62bd Andrea Spadaccini
2165 3b59ec02 Guido Trotter
      # check that KVM supports SPICE
2166 6e043e60 Guido Trotter
      kvmhelp = cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP)
2167 0ad7f5d8 Guido Trotter
      if not cls._SPICE_RE.search(kvmhelp):
2168 b1cb62bd Andrea Spadaccini
        raise errors.HypervisorError("spice is configured, but it is not"
2169 0ad7f5d8 Guido Trotter
                                     " supported according to kvm --help")
2170 b1cb62bd Andrea Spadaccini
2171 b1cb62bd Andrea Spadaccini
      # if spice_bind is not an IP address, it must be a valid interface
2172 b1cb62bd Andrea Spadaccini
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind)
2173 b1cb62bd Andrea Spadaccini
                       or netutils.IP6Address.IsValid(spice_bind))
2174 b1cb62bd Andrea Spadaccini
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2175 b1cb62bd Andrea Spadaccini
        raise errors.HypervisorError("spice: the %s parameter must be either"
2176 b1cb62bd Andrea Spadaccini
                                     " a valid IP address or interface name" %
2177 b1cb62bd Andrea Spadaccini
                                     constants.HV_KVM_SPICE_BIND)
2178 b1cb62bd Andrea Spadaccini
2179 82e3bf85 Dimitris Aragiorgis
    machine_version = hvparams[constants.HV_KVM_MACHINE_VERSION]
2180 82e3bf85 Dimitris Aragiorgis
    if machine_version:
2181 6e043e60 Guido Trotter
      output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2182 82e3bf85 Dimitris Aragiorgis
      if not cls._CHECK_MACHINE_VERSION_RE(machine_version).search(output):
2183 82e3bf85 Dimitris Aragiorgis
        raise errors.HypervisorError("Unsupported machine version: %s" %
2184 82e3bf85 Dimitris Aragiorgis
                                     machine_version)
2185 82e3bf85 Dimitris Aragiorgis
2186 f5118ade Iustin Pop
  @classmethod
2187 f5118ade Iustin Pop
  def PowercycleNode(cls):
2188 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
2189 f5118ade Iustin Pop

2190 f5118ade Iustin Pop
    """
2191 f5118ade Iustin Pop
    cls.LinuxPowercycle()