Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ af89fa76

History | View | Annotate | Download (78.4 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 199b2053 Apollon Oikonomopoulos
def _ProbeTapVnetHdr(fd):
84 199b2053 Apollon Oikonomopoulos
  """Check whether to enable the IFF_VNET_HDR flag.
85 199b2053 Apollon Oikonomopoulos

86 199b2053 Apollon Oikonomopoulos
  To do this, _all_ of the following conditions must be met:
87 199b2053 Apollon Oikonomopoulos
   1. TUNGETFEATURES ioctl() *must* be implemented
88 199b2053 Apollon Oikonomopoulos
   2. TUNGETFEATURES ioctl() result *must* contain the IFF_VNET_HDR flag
89 199b2053 Apollon Oikonomopoulos
   3. TUNGETIFF ioctl() *must* be implemented; reading the kernel code in
90 199b2053 Apollon Oikonomopoulos
      drivers/net/tun.c there is no way to test this until after the tap device
91 199b2053 Apollon Oikonomopoulos
      has been created using TUNSETIFF, and there is no way to change the
92 199b2053 Apollon Oikonomopoulos
      IFF_VNET_HDR flag after creating the interface, catch-22! However both
93 199b2053 Apollon Oikonomopoulos
      TUNGETIFF and TUNGETFEATURES were introduced in kernel version 2.6.27,
94 199b2053 Apollon Oikonomopoulos
      thus we can expect TUNGETIFF to be present if TUNGETFEATURES is.
95 199b2053 Apollon Oikonomopoulos

96 199b2053 Apollon Oikonomopoulos
   @type fd: int
97 199b2053 Apollon Oikonomopoulos
   @param fd: the file descriptor of /dev/net/tun
98 199b2053 Apollon Oikonomopoulos

99 199b2053 Apollon Oikonomopoulos
  """
100 199b2053 Apollon Oikonomopoulos
  req = struct.pack("I", 0)
101 199b2053 Apollon Oikonomopoulos
  try:
102 199b2053 Apollon Oikonomopoulos
    res = fcntl.ioctl(fd, TUNGETFEATURES, req)
103 199b2053 Apollon Oikonomopoulos
  except EnvironmentError:
104 199b2053 Apollon Oikonomopoulos
    logging.warning("TUNGETFEATURES ioctl() not implemented")
105 199b2053 Apollon Oikonomopoulos
    return False
106 199b2053 Apollon Oikonomopoulos
107 199b2053 Apollon Oikonomopoulos
  tunflags = struct.unpack("I", res)[0]
108 199b2053 Apollon Oikonomopoulos
  if tunflags & IFF_VNET_HDR:
109 199b2053 Apollon Oikonomopoulos
    return True
110 199b2053 Apollon Oikonomopoulos
  else:
111 199b2053 Apollon Oikonomopoulos
    logging.warning("Host does not support IFF_VNET_HDR, not enabling")
112 199b2053 Apollon Oikonomopoulos
    return False
113 199b2053 Apollon Oikonomopoulos
114 199b2053 Apollon Oikonomopoulos
115 199b2053 Apollon Oikonomopoulos
def _OpenTap(vnet_hdr=True):
116 199b2053 Apollon Oikonomopoulos
  """Open a new tap device and return its file descriptor.
117 199b2053 Apollon Oikonomopoulos

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

121 199b2053 Apollon Oikonomopoulos
  @type vnet_hdr: boolean
122 199b2053 Apollon Oikonomopoulos
  @param vnet_hdr: Enable the VNET Header
123 199b2053 Apollon Oikonomopoulos
  @return: (ifname, tapfd)
124 199b2053 Apollon Oikonomopoulos
  @rtype: tuple
125 199b2053 Apollon Oikonomopoulos

126 199b2053 Apollon Oikonomopoulos
  """
127 199b2053 Apollon Oikonomopoulos
  try:
128 199b2053 Apollon Oikonomopoulos
    tapfd = os.open("/dev/net/tun", os.O_RDWR)
129 199b2053 Apollon Oikonomopoulos
  except EnvironmentError:
130 199b2053 Apollon Oikonomopoulos
    raise errors.HypervisorError("Failed to open /dev/net/tun")
131 199b2053 Apollon Oikonomopoulos
132 199b2053 Apollon Oikonomopoulos
  flags = IFF_TAP | IFF_NO_PI
133 199b2053 Apollon Oikonomopoulos
134 199b2053 Apollon Oikonomopoulos
  if vnet_hdr and _ProbeTapVnetHdr(tapfd):
135 199b2053 Apollon Oikonomopoulos
    flags |= IFF_VNET_HDR
136 199b2053 Apollon Oikonomopoulos
137 199b2053 Apollon Oikonomopoulos
  # The struct ifreq ioctl request (see netdevice(7))
138 199b2053 Apollon Oikonomopoulos
  ifr = struct.pack("16sh", "", flags)
139 199b2053 Apollon Oikonomopoulos
140 199b2053 Apollon Oikonomopoulos
  try:
141 199b2053 Apollon Oikonomopoulos
    res = fcntl.ioctl(tapfd, TUNSETIFF, ifr)
142 199b2053 Apollon Oikonomopoulos
  except EnvironmentError:
143 199b2053 Apollon Oikonomopoulos
    raise errors.HypervisorError("Failed to allocate a new TAP device")
144 199b2053 Apollon Oikonomopoulos
145 199b2053 Apollon Oikonomopoulos
  # Get the interface name from the ioctl
146 199b2053 Apollon Oikonomopoulos
  ifname = struct.unpack("16sh", res)[0].strip("\x00")
147 199b2053 Apollon Oikonomopoulos
  return (ifname, tapfd)
148 199b2053 Apollon Oikonomopoulos
149 748e4b5a Michael Hanselmann
150 8df21834 Dimitris Aragiorgis
def _BuildNetworkEnv(name, network, gateway, network6, gateway6,
151 8df21834 Dimitris Aragiorgis
                     network_type, mac_prefix, tags, env):
152 8df21834 Dimitris Aragiorgis
  """Build environment variables concerning a Network.
153 8df21834 Dimitris Aragiorgis

154 8df21834 Dimitris Aragiorgis
  """
155 8df21834 Dimitris Aragiorgis
  if name:
156 8df21834 Dimitris Aragiorgis
    env["NETWORK_NAME"] = name
157 8df21834 Dimitris Aragiorgis
  if network:
158 8df21834 Dimitris Aragiorgis
    env["NETWORK_SUBNET"] = network
159 8df21834 Dimitris Aragiorgis
  if gateway:
160 8df21834 Dimitris Aragiorgis
    env["NETWORK_GATEWAY"] = gateway
161 8df21834 Dimitris Aragiorgis
  if network6:
162 8df21834 Dimitris Aragiorgis
    env["NETWORK_SUBNET6"] = network6
163 8df21834 Dimitris Aragiorgis
  if gateway6:
164 8df21834 Dimitris Aragiorgis
    env["NETWORK_GATEWAY6"] = gateway6
165 8df21834 Dimitris Aragiorgis
  if mac_prefix:
166 8df21834 Dimitris Aragiorgis
    env["NETWORK_MAC_PREFIX"] = mac_prefix
167 8df21834 Dimitris Aragiorgis
  if network_type:
168 8df21834 Dimitris Aragiorgis
    env["NETWORK_TYPE"] = network_type
169 8df21834 Dimitris Aragiorgis
  if tags:
170 8df21834 Dimitris Aragiorgis
    env["NETWORK_TAGS"] = " ".join(tags)
171 8df21834 Dimitris Aragiorgis
172 8df21834 Dimitris Aragiorgis
  return env
173 8df21834 Dimitris Aragiorgis
174 8df21834 Dimitris Aragiorgis
175 91c10532 Andrea Spadaccini
class QmpMessage:
176 91c10532 Andrea Spadaccini
  """QEMU Messaging Protocol (QMP) message.
177 91c10532 Andrea Spadaccini

178 91c10532 Andrea Spadaccini
  """
179 91c10532 Andrea Spadaccini
  def __init__(self, data):
180 91c10532 Andrea Spadaccini
    """Creates a new QMP message based on the passed data.
181 91c10532 Andrea Spadaccini

182 91c10532 Andrea Spadaccini
    """
183 91c10532 Andrea Spadaccini
    if not isinstance(data, dict):
184 91c10532 Andrea Spadaccini
      raise TypeError("QmpMessage must be initialized with a dict")
185 91c10532 Andrea Spadaccini
186 91c10532 Andrea Spadaccini
    self.data = data
187 91c10532 Andrea Spadaccini
188 91c10532 Andrea Spadaccini
  def __getitem__(self, field_name):
189 91c10532 Andrea Spadaccini
    """Get the value of the required field if present, or None.
190 91c10532 Andrea Spadaccini

191 91c10532 Andrea Spadaccini
    Overrides the [] operator to provide access to the message data,
192 91c10532 Andrea Spadaccini
    returning None if the required item is not in the message
193 91c10532 Andrea Spadaccini
    @return: the value of the field_name field, or None if field_name
194 91c10532 Andrea Spadaccini
             is not contained in the message
195 91c10532 Andrea Spadaccini

196 91c10532 Andrea Spadaccini
    """
197 9b87c2cf Michael Hanselmann
    return self.data.get(field_name, None)
198 91c10532 Andrea Spadaccini
199 91c10532 Andrea Spadaccini
  def __setitem__(self, field_name, field_value):
200 91c10532 Andrea Spadaccini
    """Set the value of the required field_name to field_value.
201 91c10532 Andrea Spadaccini

202 91c10532 Andrea Spadaccini
    """
203 91c10532 Andrea Spadaccini
    self.data[field_name] = field_value
204 91c10532 Andrea Spadaccini
205 91c10532 Andrea Spadaccini
  @staticmethod
206 91c10532 Andrea Spadaccini
  def BuildFromJsonString(json_string):
207 91c10532 Andrea Spadaccini
    """Build a QmpMessage from a JSON encoded string.
208 91c10532 Andrea Spadaccini

209 91c10532 Andrea Spadaccini
    @type json_string: str
210 91c10532 Andrea Spadaccini
    @param json_string: JSON string representing the message
211 91c10532 Andrea Spadaccini
    @rtype: L{QmpMessage}
212 91c10532 Andrea Spadaccini
    @return: a L{QmpMessage} built from json_string
213 91c10532 Andrea Spadaccini

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

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

250 91c10532 Andrea Spadaccini
    @type monitor_filename: string
251 91c10532 Andrea Spadaccini
    @param monitor_filename: the filename of the UNIX raw socket on which the
252 91c10532 Andrea Spadaccini
                             QMP monitor is listening
253 91c10532 Andrea Spadaccini

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

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

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

290 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
291 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
292 91c10532 Andrea Spadaccini

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

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

326 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
327 91c10532 Andrea Spadaccini

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

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

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

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

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

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

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

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

609 98ec75d6 Iustin Pop
    """
610 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
611 98ec75d6 Iustin Pop
612 263b8de6 Guido Trotter
  @classmethod
613 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
614 7548396c Guido Trotter
    """Returns the instance uidfile.
615 7548396c Guido Trotter

616 7548396c Guido Trotter
    """
617 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
618 7548396c Guido Trotter
619 7548396c Guido Trotter
  @classmethod
620 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
621 263b8de6 Guido Trotter
    """Check pid file for instance information.
622 263b8de6 Guido Trotter

623 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
624 263b8de6 Guido Trotter
    information from its command line.
625 263b8de6 Guido Trotter

626 263b8de6 Guido Trotter
    @type pid: string or int
627 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
628 263b8de6 Guido Trotter
    @rtype: tuple
629 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
630 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
631 263b8de6 Guido Trotter

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

667 263b8de6 Guido Trotter
    @type instance_name: string
668 263b8de6 Guido Trotter
    @param instance_name: instance name
669 263b8de6 Guido Trotter
    @rtype: tuple
670 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
671 1f8b3a27 Guido Trotter

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

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

698 c4fbefc8 Guido Trotter
    """
699 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
700 c4fbefc8 Guido Trotter
701 0df4d98a Guido Trotter
  @classmethod
702 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
703 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
704 c4fbefc8 Guido Trotter

705 c4fbefc8 Guido Trotter
    """
706 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
707 c4fbefc8 Guido Trotter
708 91c10532 Andrea Spadaccini
  @classmethod
709 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
710 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
711 91c10532 Andrea Spadaccini

712 91c10532 Andrea Spadaccini
    """
713 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
714 91c10532 Andrea Spadaccini
715 86d6bc2a Guido Trotter
  @staticmethod
716 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
717 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
718 86d6bc2a Guido Trotter

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

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

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

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

746 5d9bfd87 Apollon Oikonomopoulos
    """
747 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
748 5d9bfd87 Apollon Oikonomopoulos
749 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
750 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
751 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
752 5d9bfd87 Apollon Oikonomopoulos

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

760 4f580fef Sรฉbastien Bocahu
    """
761 4f580fef Sรฉbastien Bocahu
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
762 4f580fef Sรฉbastien Bocahu
763 4f580fef Sรฉbastien Bocahu
  @classmethod
764 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
765 7548396c Guido Trotter
    """Try to read a uid file
766 7548396c Guido Trotter

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

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

822 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
823 eb58f9b1 Guido Trotter
    @type instance: instance object
824 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
825 eb58f9b1 Guido Trotter
    @type seq: int
826 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
827 eb58f9b1 Guido Trotter
    @type nic: nic object
828 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
829 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
830 eb58f9b1 Guido Trotter

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

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

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

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

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

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

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

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

955 b693125f Tsachy Shacham
    @type instance_name: string
956 b693125f Tsachy Shacham
    @param instance_name: name of instance
957 b693125f Tsachy Shacham
    @type cpu_mask: string
958 b693125f Tsachy Shacham
    @param cpu_mask: CPU pinning mask as entered by user
959 b693125f Tsachy Shacham

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

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

974 eb58f9b1 Guido Trotter
    """
975 eb58f9b1 Guido Trotter
    result = []
976 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
977 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
978 eb58f9b1 Guido Trotter
        result.append(name)
979 eb58f9b1 Guido Trotter
    return result
980 eb58f9b1 Guido Trotter
981 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
982 eb58f9b1 Guido Trotter
    """Get instance properties.
983 eb58f9b1 Guido Trotter

984 4fbb3c60 Guido Trotter
    @type instance_name: string
985 c41eea6e Iustin Pop
    @param instance_name: the instance name
986 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
987 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
988 eb58f9b1 Guido Trotter

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

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

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

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

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

1391 38e250ba Guido Trotter
    """
1392 38e250ba Guido Trotter
    try:
1393 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1394 38e250ba Guido Trotter
                      data=data)
1395 90c024f6 Guido Trotter
    except EnvironmentError, err:
1396 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1397 38e250ba Guido Trotter
1398 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
1399 38e250ba Guido Trotter
    """Read an instance's KVM runtime
1400 38e250ba Guido Trotter

1401 38e250ba Guido Trotter
    """
1402 38e250ba Guido Trotter
    try:
1403 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1404 90c024f6 Guido Trotter
    except EnvironmentError, err:
1405 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1406 38e250ba Guido Trotter
    return file_content
1407 38e250ba Guido Trotter
1408 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1409 38e250ba Guido Trotter
    """Save an instance's KVM runtime
1410 38e250ba Guido Trotter

1411 38e250ba Guido Trotter
    """
1412 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
1413 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1414 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
1415 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
1416 38e250ba Guido Trotter
1417 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1418 38e250ba Guido Trotter
    """Load an instance's KVM runtime
1419 38e250ba Guido Trotter

1420 38e250ba Guido Trotter
    """
1421 30e42c4e Guido Trotter
    if not serialized_runtime:
1422 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1423 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
1424 c2672466 Guido Trotter
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
1425 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
1426 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
1427 38e250ba Guido Trotter
1428 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1429 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
1430 76431533 Guido Trotter

1431 76431533 Guido Trotter
    @type name: string
1432 76431533 Guido Trotter
    @param name: instance name
1433 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1434 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1435 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1436 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1437 76431533 Guido Trotter

1438 76431533 Guido Trotter
    """
1439 5d9bfd87 Apollon Oikonomopoulos
    try:
1440 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1441 5d9bfd87 Apollon Oikonomopoulos
    finally:
1442 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
1443 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
1444 5d9bfd87 Apollon Oikonomopoulos
1445 76431533 Guido Trotter
    if result.failed:
1446 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1447 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
1448 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
1449 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
1450 76431533 Guido Trotter
1451 b73f1c59 Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1452 839642c2 Iustin Pop
    """Execute a KVM cmd, after completing it with some last minute data.
1453 ee5f20b0 Guido Trotter

1454 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1455 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1456 b73f1c59 Guido Trotter
    @type kvmhelp: string
1457 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1458 30e42c4e Guido Trotter

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

1662 ee5f20b0 Guido Trotter
    """
1663 5905901c Iustin Pop
    self._CheckDown(instance.name)
1664 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1665 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1666 7238edb5 Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1667 b73f1c59 Guido Trotter
                                           startup_paused, kvmhelp)
1668 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1669 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1670 ee5f20b0 Guido Trotter
1671 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
1672 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
1673 6567aff3 Guido Trotter

1674 6567aff3 Guido Trotter
    """
1675 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1676 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
1677 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
1678 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1679 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
1680 6567aff3 Guido Trotter
    if result.failed:
1681 6567aff3 Guido Trotter
      msg = ("Failed to send command '%s' to instance %s."
1682 6567aff3 Guido Trotter
             " output: %s, error: %s, fail_reason: %s" %
1683 9798fcae Guido Trotter
             (command, instance_name,
1684 9798fcae Guido Trotter
              result.stdout, result.stderr, result.fail_reason))
1685 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
1686 6567aff3 Guido Trotter
1687 6567aff3 Guido Trotter
    return result
1688 6567aff3 Guido Trotter
1689 b52d85c1 Guido Trotter
  @classmethod
1690 585c8187 Guido Trotter
  def _ParseKVMVersion(cls, text):
1691 585c8187 Guido Trotter
    """Parse the KVM version from the --help output.
1692 585c8187 Guido Trotter

1693 585c8187 Guido Trotter
    @type text: string
1694 585c8187 Guido Trotter
    @param text: output of kvm --help
1695 585c8187 Guido Trotter
    @return: (version, v_maj, v_min, v_rev)
1696 5c3d5dfd Iustin Pop
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1697 585c8187 Guido Trotter

1698 585c8187 Guido Trotter
    """
1699 585c8187 Guido Trotter
    match = cls._VERSION_RE.search(text.splitlines()[0])
1700 585c8187 Guido Trotter
    if not match:
1701 585c8187 Guido Trotter
      raise errors.HypervisorError("Unable to get KVM version")
1702 585c8187 Guido Trotter
1703 585c8187 Guido Trotter
    v_all = match.group(0)
1704 585c8187 Guido Trotter
    v_maj = int(match.group(1))
1705 585c8187 Guido Trotter
    v_min = int(match.group(2))
1706 585c8187 Guido Trotter
    if match.group(4):
1707 585c8187 Guido Trotter
      v_rev = int(match.group(4))
1708 585c8187 Guido Trotter
    else:
1709 585c8187 Guido Trotter
      v_rev = 0
1710 585c8187 Guido Trotter
    return (v_all, v_maj, v_min, v_rev)
1711 585c8187 Guido Trotter
1712 585c8187 Guido Trotter
  @classmethod
1713 6e043e60 Guido Trotter
  def _GetKVMOutput(cls, kvm_path, option):
1714 6e043e60 Guido Trotter
    """Return the output of a kvm invocation
1715 e3b89628 Guido Trotter

1716 6e043e60 Guido Trotter
    @return: output a supported kvm invocation
1717 e3b89628 Guido Trotter
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
1718 e3b89628 Guido Trotter

1719 e3b89628 Guido Trotter
    """
1720 6e043e60 Guido Trotter
    assert option in cls._KVMOPTS_CMDS, "Invalid output option"
1721 6e043e60 Guido Trotter
1722 6e043e60 Guido Trotter
    result = utils.RunCmd([kvm_path] + cls._KVMOPTS_CMDS[option])
1723 e3b89628 Guido Trotter
    if result.failed:
1724 af89fa76 Helga Velroyen
      raise errors.HypervisorError("Unable to get KVM %s output" %
1725 af89fa76 Helga Velroyen
                                    " ".join(cls._KVMOPTS_CMDS[option]))
1726 e3b89628 Guido Trotter
    return result.output
1727 e3b89628 Guido Trotter
1728 e3b89628 Guido Trotter
  @classmethod
1729 3b59ec02 Guido Trotter
  def _GetKVMVersion(cls, kvm_path):
1730 d7e4a2b1 Andrea Spadaccini
    """Return the installed KVM version.
1731 b52d85c1 Guido Trotter

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

1735 b52d85c1 Guido Trotter
    """
1736 6e043e60 Guido Trotter
    return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
1737 82e3bf85 Dimitris Aragiorgis
1738 82e3bf85 Dimitris Aragiorgis
  @classmethod
1739 82e3bf85 Dimitris Aragiorgis
  def _GetDefaultMachineVersion(cls, kvm_path):
1740 82e3bf85 Dimitris Aragiorgis
    """Return the default hardware revision (e.g. pc-1.1)
1741 82e3bf85 Dimitris Aragiorgis

1742 82e3bf85 Dimitris Aragiorgis
    """
1743 6e043e60 Guido Trotter
    output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
1744 82e3bf85 Dimitris Aragiorgis
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
1745 82e3bf85 Dimitris Aragiorgis
    if match:
1746 82e3bf85 Dimitris Aragiorgis
      return match.group(1)
1747 82e3bf85 Dimitris Aragiorgis
    else:
1748 82e3bf85 Dimitris Aragiorgis
      return "pc"
1749 82e3bf85 Dimitris Aragiorgis
1750 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
1751 eb58f9b1 Guido Trotter
    """Stop an instance.
1752 eb58f9b1 Guido Trotter

1753 eb58f9b1 Guido Trotter
    """
1754 bbcf7ad0 Iustin Pop
    if name is not None and not force:
1755 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
1756 bbcf7ad0 Iustin Pop
    if name is None:
1757 bbcf7ad0 Iustin Pop
      name = instance.name
1758 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
1759 bbcf7ad0 Iustin Pop
    else:
1760 bbcf7ad0 Iustin Pop
      acpi = False
1761 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
1762 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
1763 bbcf7ad0 Iustin Pop
      if force or not acpi:
1764 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
1765 eb58f9b1 Guido Trotter
      else:
1766 d0c8c01d Iustin Pop
        self._CallMonitorCommand(name, "system_powerdown")
1767 eb58f9b1 Guido Trotter
1768 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
1769 8904b35c Guido Trotter
    """Cleanup after a stopped instance
1770 8904b35c Guido Trotter

1771 8904b35c Guido Trotter
    """
1772 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1773 8904b35c Guido Trotter
    if pid > 0 and alive:
1774 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
1775 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1776 eb58f9b1 Guido Trotter
1777 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
1778 eb58f9b1 Guido Trotter
    """Reboot an instance.
1779 eb58f9b1 Guido Trotter

1780 eb58f9b1 Guido Trotter
    """
1781 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
1782 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
1783 eb58f9b1 Guido Trotter
    # to shutdown and restart.
1784 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
1785 1f8b3a27 Guido Trotter
    if not alive:
1786 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
1787 78411c60 Iustin Pop
                                   " not running" % instance.name)
1788 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
1789 f02881e0 Guido Trotter
    # ...first load it...
1790 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
1791 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
1792 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
1793 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
1794 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
1795 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1796 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1797 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1798 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp)
1799 eb58f9b1 Guido Trotter
1800 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
1801 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
1802 30e42c4e Guido Trotter

1803 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1804 30e42c4e Guido Trotter
    @param instance: instance to be migrated
1805 30e42c4e Guido Trotter
    @rtype: string
1806 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
1807 30e42c4e Guido Trotter

1808 30e42c4e Guido Trotter
    """
1809 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
1810 30e42c4e Guido Trotter
1811 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
1812 30e42c4e Guido Trotter
    """Prepare to accept an instance.
1813 30e42c4e Guido Trotter

1814 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1815 30e42c4e Guido Trotter
    @param instance: instance to be accepted
1816 30e42c4e Guido Trotter
    @type info: string
1817 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
1818 30e42c4e Guido Trotter
    @type target: string
1819 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
1820 30e42c4e Guido Trotter

1821 30e42c4e Guido Trotter
    """
1822 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1823 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1824 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1825 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1826 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
1827 b73f1c59 Guido Trotter
                            incoming=incoming_address)
1828 30e42c4e Guido Trotter
1829 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
1830 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
1831 30e42c4e Guido Trotter

1832 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
1833 30e42c4e Guido Trotter

1834 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1835 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
1836 30e42c4e Guido Trotter

1837 30e42c4e Guido Trotter
    """
1838 30e42c4e Guido Trotter
    if success:
1839 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1840 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
1841 5d9bfd87 Apollon Oikonomopoulos
1842 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
1843 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1844 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
1845 cc8a8ed7 Apollon Oikonomopoulos
          continue
1846 5d9bfd87 Apollon Oikonomopoulos
        try:
1847 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
1848 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
1849 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
1850 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
1851 5d9bfd87 Apollon Oikonomopoulos
          continue
1852 5d9bfd87 Apollon Oikonomopoulos
        try:
1853 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
1854 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
1855 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
1856 5d9bfd87 Apollon Oikonomopoulos
1857 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
1858 30e42c4e Guido Trotter
    else:
1859 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
1860 30e42c4e Guido Trotter
1861 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
1862 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
1863 30e42c4e Guido Trotter

1864 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
1865 30e42c4e Guido Trotter
    currently running.
1866 30e42c4e Guido Trotter

1867 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
1868 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
1869 30e42c4e Guido Trotter
    @type target: string
1870 30e42c4e Guido Trotter
    @param target: ip address of the target node
1871 30e42c4e Guido Trotter
    @type live: boolean
1872 30e42c4e Guido Trotter
    @param live: perform a live migration
1873 30e42c4e Guido Trotter

1874 30e42c4e Guido Trotter
    """
1875 58d38b02 Iustin Pop
    instance_name = instance.name
1876 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
1877 6a1434d7 Andrea Spadaccini
    _, _, alive = self._InstancePidAlive(instance_name)
1878 30e42c4e Guido Trotter
    if not alive:
1879 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
1880 30e42c4e Guido Trotter
1881 30e42c4e Guido Trotter
    if not live:
1882 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
1883 30e42c4e Guido Trotter
1884 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
1885 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1886 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
1887 e43d4f9f Apollon Oikonomopoulos
1888 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
1889 5ae4945a Iustin Pop
                       instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
1890 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
1891 e43d4f9f Apollon Oikonomopoulos
1892 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
1893 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
1894 30e42c4e Guido Trotter
1895 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
1896 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
1897 6a1434d7 Andrea Spadaccini

1898 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
1899 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
1900 6a1434d7 Andrea Spadaccini
    @type success: bool
1901 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
1902 6a1434d7 Andrea Spadaccini
    @type live: bool
1903 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
1904 6a1434d7 Andrea Spadaccini

1905 6a1434d7 Andrea Spadaccini
    """
1906 6a1434d7 Andrea Spadaccini
    if success:
1907 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
1908 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
1909 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
1910 6a1434d7 Andrea Spadaccini
    elif live:
1911 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1912 6a1434d7 Andrea Spadaccini
1913 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
1914 6a1434d7 Andrea Spadaccini
    """Get the migration status
1915 6a1434d7 Andrea Spadaccini

1916 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
1917 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
1918 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
1919 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
1920 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
1921 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
1922 6a1434d7 Andrea Spadaccini

1923 6a1434d7 Andrea Spadaccini
    """
1924 d0c8c01d Iustin Pop
    info_command = "info migrate"
1925 6a1434d7 Andrea Spadaccini
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
1926 6a1434d7 Andrea Spadaccini
      result = self._CallMonitorCommand(instance.name, info_command)
1927 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
1928 30e42c4e Guido Trotter
      if not match:
1929 c4e388a5 Guido Trotter
        if not result.stdout:
1930 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
1931 c4e388a5 Guido Trotter
        else:
1932 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
1933 c4e388a5 Guido Trotter
                          result.stdout)
1934 30e42c4e Guido Trotter
      else:
1935 30e42c4e Guido Trotter
        status = match.group(1)
1936 6a1434d7 Andrea Spadaccini
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
1937 6a1434d7 Andrea Spadaccini
          migration_status = objects.MigrationStatus(status=status)
1938 61643226 Andrea Spadaccini
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
1939 61643226 Andrea Spadaccini
          if match:
1940 61643226 Andrea Spadaccini
            migration_status.transferred_ram = match.group("transferred")
1941 61643226 Andrea Spadaccini
            migration_status.total_ram = match.group("total")
1942 61643226 Andrea Spadaccini
1943 6a1434d7 Andrea Spadaccini
          return migration_status
1944 30e42c4e Guido Trotter
1945 6a1434d7 Andrea Spadaccini
        logging.warning("KVM: unknown migration status '%s'", status)
1946 6a1434d7 Andrea Spadaccini
1947 6a1434d7 Andrea Spadaccini
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1948 6a1434d7 Andrea Spadaccini
1949 62457f51 Iustin Pop
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED)
1950 30e42c4e Guido Trotter
1951 3d836750 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
1952 3d836750 Guido Trotter
    """Balloon an instance memory to a certain value.
1953 3d836750 Guido Trotter

1954 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
1955 3d836750 Guido Trotter
    @param instance: instance to be accepted
1956 3d836750 Guido Trotter
    @type mem: int
1957 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
1958 3d836750 Guido Trotter

1959 3d836750 Guido Trotter
    """
1960 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
1961 3d836750 Guido Trotter
1962 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
1963 eb58f9b1 Guido Trotter
    """Return information about the node.
1964 eb58f9b1 Guido Trotter

1965 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
1966 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
1967 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
1968 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
1969 34fbc862 Andrea Spadaccini
          - hv_version: the hypervisor version in the form (major, minor,
1970 34fbc862 Andrea Spadaccini
                        revision)
1971 eb58f9b1 Guido Trotter

1972 eb58f9b1 Guido Trotter
    """
1973 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
1974 4b9638dc Guido Trotter
    # FIXME: this is the global kvm version, but the actual version can be
1975 4b9638dc Guido Trotter
    # customized as an hv parameter. we should use the nodegroup's default kvm
1976 4b9638dc Guido Trotter
    # path parameter here.
1977 3b59ec02 Guido Trotter
    _, v_major, v_min, v_rev = self._GetKVMVersion(constants.KVM_PATH)
1978 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
1979 34fbc862 Andrea Spadaccini
    return result
1980 eb58f9b1 Guido Trotter
1981 637ce7f9 Guido Trotter
  @classmethod
1982 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
1983 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
1984 eb58f9b1 Guido Trotter

1985 eb58f9b1 Guido Trotter
    """
1986 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
1987 9d9bded1 Michael Hanselmann
      cmd = [pathutils.KVM_CONSOLE_WRAPPER,
1988 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
1989 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
1990 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
1991 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
1992 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
1993 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
1994 55cc0a44 Michael Hanselmann
                                     host=instance.primary_node,
1995 052783ff Michael Hanselmann
                                     user=constants.SSH_CONSOLE_USER,
1996 55cc0a44 Michael Hanselmann
                                     command=cmd)
1997 3be34f57 Guido Trotter
1998 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
1999 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2000 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
2001 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2002 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
2003 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
2004 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
2005 55cc0a44 Michael Hanselmann
                                     display=display)
2006 55cc0a44 Michael Hanselmann
2007 4d2cdb5a Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2008 4d2cdb5a Andrea Spadaccini
    if spice_bind:
2009 4d2cdb5a Andrea Spadaccini
      return objects.InstanceConsole(instance=instance.name,
2010 4d2cdb5a Andrea Spadaccini
                                     kind=constants.CONS_SPICE,
2011 4d2cdb5a Andrea Spadaccini
                                     host=spice_bind,
2012 4d2cdb5a Andrea Spadaccini
                                     port=instance.network_port)
2013 4d2cdb5a Andrea Spadaccini
2014 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
2015 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
2016 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
2017 55cc0a44 Michael Hanselmann
                                            instance.name))
2018 eb58f9b1 Guido Trotter
2019 eb58f9b1 Guido Trotter
  def Verify(self):
2020 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
2021 eb58f9b1 Guido Trotter

2022 eb58f9b1 Guido Trotter
    Check that the binary exists.
2023 eb58f9b1 Guido Trotter

2024 eb58f9b1 Guido Trotter
    """
2025 4b9638dc Guido Trotter
    # FIXME: this is the global kvm version, but the actual version can be
2026 4b9638dc Guido Trotter
    # customized as an hv parameter. we should use the nodegroup's default kvm
2027 4b9638dc Guido Trotter
    # path parameter here.
2028 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
2029 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
2030 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2031 14aa53cb Guido Trotter
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
2032 14aa53cb Guido Trotter
2033 6b5605e8 Iustin Pop
  @classmethod
2034 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2035 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2036 6b5605e8 Iustin Pop

2037 6b5605e8 Iustin Pop
    @type hvparams:  dict
2038 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2039 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2040 6b5605e8 Iustin Pop

2041 6b5605e8 Iustin Pop
    """
2042 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2043 6b5605e8 Iustin Pop
2044 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
2045 df5ab9f0 Guido Trotter
    if kernel_path:
2046 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
2047 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
2048 205ab586 Iustin Pop
                                     " if a kernel is defined")
2049 6b5605e8 Iustin Pop
2050 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
2051 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
2052 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
2053 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
2054 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
2055 66d5dbef Guido Trotter
2056 14fd6c81 Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2057 14fd6c81 Guido Trotter
      serial_speed = hvparams[constants.HV_SERIAL_SPEED]
2058 14fd6c81 Guido Trotter
      valid_speeds = constants.VALID_SERIAL_SPEEDS
2059 14fd6c81 Guido Trotter
      if not serial_speed or serial_speed not in valid_speeds:
2060 14fd6c81 Guido Trotter
        raise errors.HypervisorError("Invalid serial console speed, must be"
2061 14fd6c81 Guido Trotter
                                     " one of: %s" %
2062 14fd6c81 Guido Trotter
                                     utils.CommaJoin(valid_speeds))
2063 14fd6c81 Guido Trotter
2064 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2065 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
2066 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2067 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2068 835528af Iustin Pop
                                   " ISO path")
2069 f5118ade Iustin Pop
2070 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2071 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2072 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
2073 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
2074 d19d94db Guido Trotter
                                     " must be specified")
2075 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
2076 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
2077 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
2078 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
2079 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
2080 d19d94db Guido Trotter
2081 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2082 b451c4c7 Andrea Spadaccini
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2083 b1cb62bd Andrea Spadaccini
    if spice_bind:
2084 b1cb62bd Andrea Spadaccini
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2085 b1cb62bd Andrea Spadaccini
        # if an IP version is specified, the spice_bind parameter must be an
2086 b1cb62bd Andrea Spadaccini
        # IP of that family
2087 b1cb62bd Andrea Spadaccini
        if (netutils.IP4Address.IsValid(spice_bind) and
2088 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP4_VERSION):
2089 b1cb62bd Andrea Spadaccini
          raise errors.HypervisorError("spice: got an IPv4 address (%s), but"
2090 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2091 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2092 b1cb62bd Andrea Spadaccini
2093 b1cb62bd Andrea Spadaccini
        if (netutils.IP6Address.IsValid(spice_bind) and
2094 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP6_VERSION):
2095 b1cb62bd Andrea Spadaccini
          raise errors.HypervisorError("spice: got an IPv6 address (%s), but"
2096 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2097 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2098 b451c4c7 Andrea Spadaccini
    else:
2099 0e1b03b9 Andrea Spadaccini
      # All the other SPICE parameters depend on spice_bind being set. Raise an
2100 0e1b03b9 Andrea Spadaccini
      # error if any of them is set without it.
2101 07788a0b Michael Hanselmann
      for param in _SPICE_ADDITIONAL_PARAMS:
2102 0e1b03b9 Andrea Spadaccini
        if hvparams[param]:
2103 0e1b03b9 Andrea Spadaccini
          raise errors.HypervisorError("spice: %s requires %s to be set" %
2104 0e1b03b9 Andrea Spadaccini
                                       (param, constants.HV_KVM_SPICE_BIND))
2105 b1cb62bd Andrea Spadaccini
2106 d19d94db Guido Trotter
  @classmethod
2107 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
2108 d19d94db Guido Trotter
    """Check the given parameters for validity.
2109 d19d94db Guido Trotter

2110 d19d94db Guido Trotter
    @type hvparams:  dict
2111 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2112 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2113 d19d94db Guido Trotter

2114 d19d94db Guido Trotter
    """
2115 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2116 d19d94db Guido Trotter
2117 82e3bf85 Dimitris Aragiorgis
    kvm_path = hvparams[constants.HV_KVM_PATH]
2118 82e3bf85 Dimitris Aragiorgis
2119 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2120 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2121 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2122 d19d94db Guido Trotter
      try:
2123 1feb39ec Guido Trotter
        pwd.getpwnam(username)
2124 d19d94db Guido Trotter
      except KeyError:
2125 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
2126 d19d94db Guido Trotter
                                     % username)
2127 d19d94db Guido Trotter
2128 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2129 b1cb62bd Andrea Spadaccini
    if spice_bind:
2130 b1cb62bd Andrea Spadaccini
      # only one of VNC and SPICE can be used currently.
2131 b1cb62bd Andrea Spadaccini
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2132 b1cb62bd Andrea Spadaccini
        raise errors.HypervisorError("both SPICE and VNC are configured, but"
2133 b1cb62bd Andrea Spadaccini
                                     " only one of them can be used at a"
2134 b1cb62bd Andrea Spadaccini
                                     " given time.")
2135 b1cb62bd Andrea Spadaccini
2136 3b59ec02 Guido Trotter
      # check that KVM supports SPICE
2137 6e043e60 Guido Trotter
      kvmhelp = cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP)
2138 0ad7f5d8 Guido Trotter
      if not cls._SPICE_RE.search(kvmhelp):
2139 b1cb62bd Andrea Spadaccini
        raise errors.HypervisorError("spice is configured, but it is not"
2140 0ad7f5d8 Guido Trotter
                                     " supported according to kvm --help")
2141 b1cb62bd Andrea Spadaccini
2142 b1cb62bd Andrea Spadaccini
      # if spice_bind is not an IP address, it must be a valid interface
2143 b1cb62bd Andrea Spadaccini
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind)
2144 b1cb62bd Andrea Spadaccini
                       or netutils.IP6Address.IsValid(spice_bind))
2145 b1cb62bd Andrea Spadaccini
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2146 b1cb62bd Andrea Spadaccini
        raise errors.HypervisorError("spice: the %s parameter must be either"
2147 b1cb62bd Andrea Spadaccini
                                     " a valid IP address or interface name" %
2148 b1cb62bd Andrea Spadaccini
                                     constants.HV_KVM_SPICE_BIND)
2149 b1cb62bd Andrea Spadaccini
2150 82e3bf85 Dimitris Aragiorgis
    machine_version = hvparams[constants.HV_KVM_MACHINE_VERSION]
2151 82e3bf85 Dimitris Aragiorgis
    if machine_version:
2152 6e043e60 Guido Trotter
      output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
2153 82e3bf85 Dimitris Aragiorgis
      if not cls._CHECK_MACHINE_VERSION_RE(machine_version).search(output):
2154 82e3bf85 Dimitris Aragiorgis
        raise errors.HypervisorError("Unsupported machine version: %s" %
2155 82e3bf85 Dimitris Aragiorgis
                                     machine_version)
2156 82e3bf85 Dimitris Aragiorgis
2157 f5118ade Iustin Pop
  @classmethod
2158 f5118ade Iustin Pop
  def PowercycleNode(cls):
2159 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
2160 f5118ade Iustin Pop

2161 f5118ade Iustin Pop
    """
2162 f5118ade Iustin Pop
    cls.LinuxPowercycle()