Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 360e6c08

History | View | Annotate | Download (79.1 kB)

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

24 eb58f9b1 Guido Trotter
"""
25 eb58f9b1 Guido Trotter
26 547a63b7 Balazs Lecz
import errno
27 eb58f9b1 Guido Trotter
import os
28 eb58f9b1 Guido Trotter
import os.path
29 eb58f9b1 Guido Trotter
import re
30 eb58f9b1 Guido Trotter
import tempfile
31 6567aff3 Guido Trotter
import time
32 30e42c4e Guido Trotter
import logging
33 d19d94db Guido Trotter
import pwd
34 199b2053 Apollon Oikonomopoulos
import struct
35 199b2053 Apollon Oikonomopoulos
import fcntl
36 5d9bfd87 Apollon Oikonomopoulos
import shutil
37 91c10532 Andrea Spadaccini
import socket
38 fc84cd5d Guido Trotter
import stat
39 91c10532 Andrea Spadaccini
import StringIO
40 b693125f Tsachy Shacham
try:
41 471a31b6 Andrea Spadaccini
  import affinity   # pylint: disable=F0401
42 b693125f Tsachy Shacham
except ImportError:
43 b693125f Tsachy Shacham
  affinity = None
44 eb58f9b1 Guido Trotter
45 eb58f9b1 Guido Trotter
from ganeti import utils
46 eb58f9b1 Guido Trotter
from ganeti import constants
47 eb58f9b1 Guido Trotter
from ganeti import errors
48 38e250ba Guido Trotter
from ganeti import serializer
49 38e250ba Guido Trotter
from ganeti import objects
50 76431533 Guido Trotter
from ganeti import uidpool
51 76431533 Guido Trotter
from ganeti import ssconf
52 a744b676 Manuel Franceschini
from ganeti import netutils
53 9d9bded1 Michael Hanselmann
from ganeti import pathutils
54 9d9bded1 Michael Hanselmann
from ganeti.hypervisor import hv_base
55 5d9bfd87 Apollon Oikonomopoulos
from ganeti.utils import wrapper as utils_wrapper
56 eb58f9b1 Guido Trotter
57 eb58f9b1 Guido Trotter
58 0e1e0b6a Michael Hanselmann
_KVM_NETWORK_SCRIPT = pathutils.CONF_DIR + "/kvm-vif-bridge"
59 b693125f Tsachy Shacham
_KVM_START_PAUSED_FLAG = "-S"
60 748e4b5a Michael Hanselmann
61 199b2053 Apollon Oikonomopoulos
# TUN/TAP driver constants, taken from <linux/if_tun.h>
62 199b2053 Apollon Oikonomopoulos
# They are architecture-independent and already hardcoded in qemu-kvm source,
63 199b2053 Apollon Oikonomopoulos
# so we can safely include them here.
64 199b2053 Apollon Oikonomopoulos
TUNSETIFF = 0x400454ca
65 199b2053 Apollon Oikonomopoulos
TUNGETIFF = 0x800454d2
66 199b2053 Apollon Oikonomopoulos
TUNGETFEATURES = 0x800454cf
67 199b2053 Apollon Oikonomopoulos
IFF_TAP = 0x0002
68 199b2053 Apollon Oikonomopoulos
IFF_NO_PI = 0x1000
69 199b2053 Apollon Oikonomopoulos
IFF_VNET_HDR = 0x4000
70 199b2053 Apollon Oikonomopoulos
71 07788a0b Michael Hanselmann
#: SPICE parameters which depend on L{constants.HV_KVM_SPICE_BIND}
72 07788a0b Michael Hanselmann
_SPICE_ADDITIONAL_PARAMS = frozenset([
73 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_IP_VERSION,
74 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_PASSWORD_FILE,
75 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR,
76 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_JPEG_IMG_COMPR,
77 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR,
78 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION,
79 07788a0b Michael Hanselmann
  constants.HV_KVM_SPICE_USE_TLS,
80 07788a0b Michael Hanselmann
  ])
81 07788a0b Michael Hanselmann
82 199b2053 Apollon Oikonomopoulos
83 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 6f1e1921 Michael Hanselmann
  except EnvironmentError, err:
143 6f1e1921 Michael Hanselmann
    raise errors.HypervisorError("Failed to allocate a new TAP device: %s" %
144 6f1e1921 Michael Hanselmann
                                 err)
145 199b2053 Apollon Oikonomopoulos
146 199b2053 Apollon Oikonomopoulos
  # Get the interface name from the ioctl
147 199b2053 Apollon Oikonomopoulos
  ifname = struct.unpack("16sh", res)[0].strip("\x00")
148 199b2053 Apollon Oikonomopoulos
  return (ifname, tapfd)
149 199b2053 Apollon Oikonomopoulos
150 748e4b5a Michael Hanselmann
151 91c10532 Andrea Spadaccini
class QmpMessage:
152 91c10532 Andrea Spadaccini
  """QEMU Messaging Protocol (QMP) message.
153 91c10532 Andrea Spadaccini

154 91c10532 Andrea Spadaccini
  """
155 91c10532 Andrea Spadaccini
  def __init__(self, data):
156 91c10532 Andrea Spadaccini
    """Creates a new QMP message based on the passed data.
157 91c10532 Andrea Spadaccini

158 91c10532 Andrea Spadaccini
    """
159 91c10532 Andrea Spadaccini
    if not isinstance(data, dict):
160 91c10532 Andrea Spadaccini
      raise TypeError("QmpMessage must be initialized with a dict")
161 91c10532 Andrea Spadaccini
162 91c10532 Andrea Spadaccini
    self.data = data
163 91c10532 Andrea Spadaccini
164 91c10532 Andrea Spadaccini
  def __getitem__(self, field_name):
165 91c10532 Andrea Spadaccini
    """Get the value of the required field if present, or None.
166 91c10532 Andrea Spadaccini

167 91c10532 Andrea Spadaccini
    Overrides the [] operator to provide access to the message data,
168 91c10532 Andrea Spadaccini
    returning None if the required item is not in the message
169 91c10532 Andrea Spadaccini
    @return: the value of the field_name field, or None if field_name
170 91c10532 Andrea Spadaccini
             is not contained in the message
171 91c10532 Andrea Spadaccini

172 91c10532 Andrea Spadaccini
    """
173 9b87c2cf Michael Hanselmann
    return self.data.get(field_name, None)
174 91c10532 Andrea Spadaccini
175 91c10532 Andrea Spadaccini
  def __setitem__(self, field_name, field_value):
176 91c10532 Andrea Spadaccini
    """Set the value of the required field_name to field_value.
177 91c10532 Andrea Spadaccini

178 91c10532 Andrea Spadaccini
    """
179 91c10532 Andrea Spadaccini
    self.data[field_name] = field_value
180 91c10532 Andrea Spadaccini
181 91c10532 Andrea Spadaccini
  @staticmethod
182 91c10532 Andrea Spadaccini
  def BuildFromJsonString(json_string):
183 91c10532 Andrea Spadaccini
    """Build a QmpMessage from a JSON encoded string.
184 91c10532 Andrea Spadaccini

185 91c10532 Andrea Spadaccini
    @type json_string: str
186 91c10532 Andrea Spadaccini
    @param json_string: JSON string representing the message
187 91c10532 Andrea Spadaccini
    @rtype: L{QmpMessage}
188 91c10532 Andrea Spadaccini
    @return: a L{QmpMessage} built from json_string
189 91c10532 Andrea Spadaccini

190 91c10532 Andrea Spadaccini
    """
191 91c10532 Andrea Spadaccini
    # Parse the string
192 91c10532 Andrea Spadaccini
    data = serializer.LoadJson(json_string)
193 91c10532 Andrea Spadaccini
    return QmpMessage(data)
194 91c10532 Andrea Spadaccini
195 91c10532 Andrea Spadaccini
  def __str__(self):
196 a182a3ed Michael Hanselmann
    # The protocol expects the JSON object to be sent as a single line.
197 a182a3ed Michael Hanselmann
    return serializer.DumpJson(self.data)
198 91c10532 Andrea Spadaccini
199 91c10532 Andrea Spadaccini
  def __eq__(self, other):
200 91c10532 Andrea Spadaccini
    # When comparing two QmpMessages, we are interested in comparing
201 91c10532 Andrea Spadaccini
    # their internal representation of the message data
202 91c10532 Andrea Spadaccini
    return self.data == other.data
203 91c10532 Andrea Spadaccini
204 91c10532 Andrea Spadaccini
205 91c10532 Andrea Spadaccini
class QmpConnection:
206 91c10532 Andrea Spadaccini
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
207 91c10532 Andrea Spadaccini

208 91c10532 Andrea Spadaccini
  """
209 91c10532 Andrea Spadaccini
  _FIRST_MESSAGE_KEY = "QMP"
210 91c10532 Andrea Spadaccini
  _EVENT_KEY = "event"
211 91c10532 Andrea Spadaccini
  _ERROR_KEY = "error"
212 89da2ff3 Guido Trotter
  _RETURN_KEY = RETURN_KEY = "return"
213 89da2ff3 Guido Trotter
  _ACTUAL_KEY = ACTUAL_KEY = "actual"
214 91c10532 Andrea Spadaccini
  _ERROR_CLASS_KEY = "class"
215 91c10532 Andrea Spadaccini
  _ERROR_DATA_KEY = "data"
216 91c10532 Andrea Spadaccini
  _ERROR_DESC_KEY = "desc"
217 91c10532 Andrea Spadaccini
  _EXECUTE_KEY = "execute"
218 91c10532 Andrea Spadaccini
  _ARGUMENTS_KEY = "arguments"
219 91c10532 Andrea Spadaccini
  _CAPABILITIES_COMMAND = "qmp_capabilities"
220 91c10532 Andrea Spadaccini
  _MESSAGE_END_TOKEN = "\r\n"
221 91c10532 Andrea Spadaccini
  _SOCKET_TIMEOUT = 5
222 91c10532 Andrea Spadaccini
223 91c10532 Andrea Spadaccini
  def __init__(self, monitor_filename):
224 91c10532 Andrea Spadaccini
    """Instantiates the QmpConnection object.
225 91c10532 Andrea Spadaccini

226 91c10532 Andrea Spadaccini
    @type monitor_filename: string
227 91c10532 Andrea Spadaccini
    @param monitor_filename: the filename of the UNIX raw socket on which the
228 91c10532 Andrea Spadaccini
                             QMP monitor is listening
229 91c10532 Andrea Spadaccini

230 91c10532 Andrea Spadaccini
    """
231 91c10532 Andrea Spadaccini
    self.monitor_filename = monitor_filename
232 91c10532 Andrea Spadaccini
    self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
233 91c10532 Andrea Spadaccini
    # We want to fail if the server doesn't send a complete message
234 91c10532 Andrea Spadaccini
    # in a reasonable amount of time
235 91c10532 Andrea Spadaccini
    self.sock.settimeout(self._SOCKET_TIMEOUT)
236 91c10532 Andrea Spadaccini
    self._connected = False
237 91c10532 Andrea Spadaccini
    self._buf = ""
238 91c10532 Andrea Spadaccini
239 fc84cd5d Guido Trotter
  def _check_socket(self):
240 fc84cd5d Guido Trotter
    sock_stat = None
241 fc84cd5d Guido Trotter
    try:
242 fc84cd5d Guido Trotter
      sock_stat = os.stat(self.monitor_filename)
243 fc84cd5d Guido Trotter
    except EnvironmentError, err:
244 fc84cd5d Guido Trotter
      if err.errno == errno.ENOENT:
245 fc84cd5d Guido Trotter
        raise errors.HypervisorError("No qmp socket found")
246 fc84cd5d Guido Trotter
      else:
247 fc84cd5d Guido Trotter
        raise errors.HypervisorError("Error checking qmp socket: %s",
248 fc84cd5d Guido Trotter
                                     utils.ErrnoOrStr(err))
249 fc84cd5d Guido Trotter
    if not stat.S_ISSOCK(sock_stat.st_mode):
250 fc84cd5d Guido Trotter
      raise errors.HypervisorError("Qmp socket is not a socket")
251 fc84cd5d Guido Trotter
252 91c10532 Andrea Spadaccini
  def _check_connection(self):
253 91c10532 Andrea Spadaccini
    """Make sure that the connection is established.
254 91c10532 Andrea Spadaccini

255 91c10532 Andrea Spadaccini
    """
256 91c10532 Andrea Spadaccini
    if not self._connected:
257 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("To use a QmpConnection you need to first"
258 91c10532 Andrea Spadaccini
                                   " invoke connect() on it")
259 91c10532 Andrea Spadaccini
260 91c10532 Andrea Spadaccini
  def connect(self):
261 91c10532 Andrea Spadaccini
    """Connects to the QMP monitor.
262 91c10532 Andrea Spadaccini

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

266 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
267 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
268 91c10532 Andrea Spadaccini

269 91c10532 Andrea Spadaccini
    """
270 fc84cd5d Guido Trotter
    if self._connected:
271 fc84cd5d Guido Trotter
      raise errors.ProgrammerError("Cannot connect twice")
272 fc84cd5d Guido Trotter
273 fc84cd5d Guido Trotter
    self._check_socket()
274 fc84cd5d Guido Trotter
275 fc84cd5d Guido Trotter
    # Check file existance/stuff
276 fc84cd5d Guido Trotter
    try:
277 fc84cd5d Guido Trotter
      self.sock.connect(self.monitor_filename)
278 fc84cd5d Guido Trotter
    except EnvironmentError:
279 fc84cd5d Guido Trotter
      raise errors.HypervisorError("Can't connect to qmp socket")
280 91c10532 Andrea Spadaccini
    self._connected = True
281 91c10532 Andrea Spadaccini
282 91c10532 Andrea Spadaccini
    # Check if we receive a correct greeting message from the server
283 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 2.2)
284 91c10532 Andrea Spadaccini
    greeting = self._Recv()
285 91c10532 Andrea Spadaccini
    if not greeting[self._FIRST_MESSAGE_KEY]:
286 91c10532 Andrea Spadaccini
      self._connected = False
287 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("kvm: qmp communication error (wrong"
288 91c10532 Andrea Spadaccini
                                   " server greeting")
289 91c10532 Andrea Spadaccini
290 91c10532 Andrea Spadaccini
    # Let's put the monitor in command mode using the qmp_capabilities
291 91c10532 Andrea Spadaccini
    # command, or else no command will be executable.
292 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 4)
293 91c10532 Andrea Spadaccini
    self.Execute(self._CAPABILITIES_COMMAND)
294 91c10532 Andrea Spadaccini
295 91c10532 Andrea Spadaccini
  def _ParseMessage(self, buf):
296 91c10532 Andrea Spadaccini
    """Extract and parse a QMP message from the given buffer.
297 91c10532 Andrea Spadaccini

298 91c10532 Andrea Spadaccini
    Seeks for a QMP message in the given buf. If found, it parses it and
299 91c10532 Andrea Spadaccini
    returns it together with the rest of the characters in the buf.
300 91c10532 Andrea Spadaccini
    If no message is found, returns None and the whole buffer.
301 91c10532 Andrea Spadaccini

302 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
303 91c10532 Andrea Spadaccini

304 91c10532 Andrea Spadaccini
    """
305 91c10532 Andrea Spadaccini
    message = None
306 91c10532 Andrea Spadaccini
    # Check if we got the message end token (CRLF, as per the QEMU Protocol
307 91c10532 Andrea Spadaccini
    # Specification 0.1 - Section 2.1.1)
308 91c10532 Andrea Spadaccini
    pos = buf.find(self._MESSAGE_END_TOKEN)
309 91c10532 Andrea Spadaccini
    if pos >= 0:
310 91c10532 Andrea Spadaccini
      try:
311 91c10532 Andrea Spadaccini
        message = QmpMessage.BuildFromJsonString(buf[:pos + 1])
312 91c10532 Andrea Spadaccini
      except Exception, err:
313 91c10532 Andrea Spadaccini
        raise errors.ProgrammerError("QMP data serialization error: %s" % err)
314 91c10532 Andrea Spadaccini
      buf = buf[pos + 1:]
315 91c10532 Andrea Spadaccini
316 91c10532 Andrea Spadaccini
    return (message, buf)
317 91c10532 Andrea Spadaccini
318 91c10532 Andrea Spadaccini
  def _Recv(self):
319 91c10532 Andrea Spadaccini
    """Receives a message from QMP and decodes the received JSON object.
320 91c10532 Andrea Spadaccini

321 91c10532 Andrea Spadaccini
    @rtype: QmpMessage
322 91c10532 Andrea Spadaccini
    @return: the received message
323 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
324 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
325 91c10532 Andrea Spadaccini

326 91c10532 Andrea Spadaccini
    """
327 91c10532 Andrea Spadaccini
    self._check_connection()
328 91c10532 Andrea Spadaccini
329 91c10532 Andrea Spadaccini
    # Check if there is already a message in the buffer
330 91c10532 Andrea Spadaccini
    (message, self._buf) = self._ParseMessage(self._buf)
331 91c10532 Andrea Spadaccini
    if message:
332 91c10532 Andrea Spadaccini
      return message
333 91c10532 Andrea Spadaccini
334 91c10532 Andrea Spadaccini
    recv_buffer = StringIO.StringIO(self._buf)
335 91c10532 Andrea Spadaccini
    recv_buffer.seek(len(self._buf))
336 91c10532 Andrea Spadaccini
    try:
337 91c10532 Andrea Spadaccini
      while True:
338 91c10532 Andrea Spadaccini
        data = self.sock.recv(4096)
339 91c10532 Andrea Spadaccini
        if not data:
340 91c10532 Andrea Spadaccini
          break
341 91c10532 Andrea Spadaccini
        recv_buffer.write(data)
342 91c10532 Andrea Spadaccini
343 91c10532 Andrea Spadaccini
        (message, self._buf) = self._ParseMessage(recv_buffer.getvalue())
344 91c10532 Andrea Spadaccini
        if message:
345 91c10532 Andrea Spadaccini
          return message
346 91c10532 Andrea Spadaccini
347 91c10532 Andrea Spadaccini
    except socket.timeout, err:
348 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while receiving a QMP message: "
349 91c10532 Andrea Spadaccini
                                   "%s" % (err))
350 91c10532 Andrea Spadaccini
    except socket.error, err:
351 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to receive data from KVM using the"
352 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
353 91c10532 Andrea Spadaccini
354 91c10532 Andrea Spadaccini
  def _Send(self, message):
355 91c10532 Andrea Spadaccini
    """Encodes and sends a message to KVM using QMP.
356 91c10532 Andrea Spadaccini

357 91c10532 Andrea Spadaccini
    @type message: QmpMessage
358 91c10532 Andrea Spadaccini
    @param message: message to send to KVM
359 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
360 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
361 91c10532 Andrea Spadaccini

362 91c10532 Andrea Spadaccini
    """
363 91c10532 Andrea Spadaccini
    self._check_connection()
364 91c10532 Andrea Spadaccini
    try:
365 91c10532 Andrea Spadaccini
      message_str = str(message)
366 91c10532 Andrea Spadaccini
    except Exception, err:
367 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("QMP data deserialization error: %s" % err)
368 91c10532 Andrea Spadaccini
369 91c10532 Andrea Spadaccini
    try:
370 91c10532 Andrea Spadaccini
      self.sock.sendall(message_str)
371 91c10532 Andrea Spadaccini
    except socket.timeout, err:
372 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while sending a QMP message: "
373 91c10532 Andrea Spadaccini
                                   "%s (%s)" % (err.string, err.errno))
374 91c10532 Andrea Spadaccini
    except socket.error, err:
375 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to send data from KVM using the"
376 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
377 91c10532 Andrea Spadaccini
378 91c10532 Andrea Spadaccini
  def Execute(self, command, arguments=None):
379 91c10532 Andrea Spadaccini
    """Executes a QMP command and returns the response of the server.
380 91c10532 Andrea Spadaccini

381 91c10532 Andrea Spadaccini
    @type command: str
382 91c10532 Andrea Spadaccini
    @param command: the command to execute
383 91c10532 Andrea Spadaccini
    @type arguments: dict
384 91c10532 Andrea Spadaccini
    @param arguments: dictionary of arguments to be passed to the command
385 91c10532 Andrea Spadaccini
    @rtype: dict
386 91c10532 Andrea Spadaccini
    @return: dictionary representing the received JSON object
387 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
388 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
389 91c10532 Andrea Spadaccini

390 91c10532 Andrea Spadaccini
    """
391 91c10532 Andrea Spadaccini
    self._check_connection()
392 91c10532 Andrea Spadaccini
    message = QmpMessage({self._EXECUTE_KEY: command})
393 91c10532 Andrea Spadaccini
    if arguments:
394 91c10532 Andrea Spadaccini
      message[self._ARGUMENTS_KEY] = arguments
395 91c10532 Andrea Spadaccini
    self._Send(message)
396 91c10532 Andrea Spadaccini
397 91c10532 Andrea Spadaccini
    # Events can occur between the sending of the command and the reception
398 91c10532 Andrea Spadaccini
    # of the response, so we need to filter out messages with the event key.
399 91c10532 Andrea Spadaccini
    while True:
400 91c10532 Andrea Spadaccini
      response = self._Recv()
401 91c10532 Andrea Spadaccini
      err = response[self._ERROR_KEY]
402 91c10532 Andrea Spadaccini
      if err:
403 91c10532 Andrea Spadaccini
        raise errors.HypervisorError("kvm: error executing the %s"
404 91c10532 Andrea Spadaccini
                                     " command: %s (%s, %s):" %
405 91c10532 Andrea Spadaccini
                                     (command,
406 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DESC_KEY],
407 91c10532 Andrea Spadaccini
                                      err[self._ERROR_CLASS_KEY],
408 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DATA_KEY]))
409 91c10532 Andrea Spadaccini
410 91c10532 Andrea Spadaccini
      elif not response[self._EVENT_KEY]:
411 91c10532 Andrea Spadaccini
        return response
412 91c10532 Andrea Spadaccini
413 91c10532 Andrea Spadaccini
414 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
415 65107a2f Michael Hanselmann
  """KVM hypervisor interface
416 65107a2f Michael Hanselmann

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

590 98ec75d6 Iustin Pop
    """
591 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
592 98ec75d6 Iustin Pop
593 263b8de6 Guido Trotter
  @classmethod
594 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
595 7548396c Guido Trotter
    """Returns the instance uidfile.
596 7548396c Guido Trotter

597 7548396c Guido Trotter
    """
598 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
599 7548396c Guido Trotter
600 7548396c Guido Trotter
  @classmethod
601 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
602 263b8de6 Guido Trotter
    """Check pid file for instance information.
603 263b8de6 Guido Trotter

604 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
605 263b8de6 Guido Trotter
    information from its command line.
606 263b8de6 Guido Trotter

607 263b8de6 Guido Trotter
    @type pid: string or int
608 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
609 263b8de6 Guido Trotter
    @rtype: tuple
610 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
611 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
612 263b8de6 Guido Trotter

613 263b8de6 Guido Trotter
    """
614 263b8de6 Guido Trotter
    alive = utils.IsProcessAlive(pid)
615 263b8de6 Guido Trotter
    if not alive:
616 263b8de6 Guido Trotter
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
617 263b8de6 Guido Trotter
618 263b8de6 Guido Trotter
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
619 263b8de6 Guido Trotter
    try:
620 263b8de6 Guido Trotter
      cmdline = utils.ReadFile(cmdline_file)
621 263b8de6 Guido Trotter
    except EnvironmentError, err:
622 263b8de6 Guido Trotter
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
623 263b8de6 Guido Trotter
                                   (pid, err))
624 263b8de6 Guido Trotter
625 263b8de6 Guido Trotter
    instance = None
626 263b8de6 Guido Trotter
    memory = 0
627 263b8de6 Guido Trotter
    vcpus = 0
628 263b8de6 Guido Trotter
629 d0c8c01d Iustin Pop
    arg_list = cmdline.split("\x00")
630 263b8de6 Guido Trotter
    while arg_list:
631 e687ec01 Michael Hanselmann
      arg = arg_list.pop(0)
632 263b8de6 Guido Trotter
      if arg == "-name":
633 263b8de6 Guido Trotter
        instance = arg_list.pop(0)
634 263b8de6 Guido Trotter
      elif arg == "-m":
635 263b8de6 Guido Trotter
        memory = int(arg_list.pop(0))
636 263b8de6 Guido Trotter
      elif arg == "-smp":
637 4888a609 Guido Trotter
        vcpus = int(arg_list.pop(0).split(",")[0])
638 263b8de6 Guido Trotter
639 263b8de6 Guido Trotter
    if instance is None:
640 263b8de6 Guido Trotter
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
641 263b8de6 Guido Trotter
                                   " instance" % pid)
642 263b8de6 Guido Trotter
643 263b8de6 Guido Trotter
    return (instance, memory, vcpus)
644 263b8de6 Guido Trotter
645 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
646 263b8de6 Guido Trotter
    """Returns the instance pidfile, pid, and liveness.
647 263b8de6 Guido Trotter

648 263b8de6 Guido Trotter
    @type instance_name: string
649 263b8de6 Guido Trotter
    @param instance_name: instance name
650 263b8de6 Guido Trotter
    @rtype: tuple
651 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
652 1f8b3a27 Guido Trotter

653 1f8b3a27 Guido Trotter
    """
654 98ec75d6 Iustin Pop
    pidfile = self._InstancePidFile(instance_name)
655 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
656 263b8de6 Guido Trotter
657 263b8de6 Guido Trotter
    alive = False
658 263b8de6 Guido Trotter
    try:
659 263b8de6 Guido Trotter
      cmd_instance = self._InstancePidInfo(pid)[0]
660 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
661 263b8de6 Guido Trotter
    except errors.HypervisorError:
662 263b8de6 Guido Trotter
      pass
663 1f8b3a27 Guido Trotter
664 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
665 1f8b3a27 Guido Trotter
666 5905901c Iustin Pop
  def _CheckDown(self, instance_name):
667 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
668 5905901c Iustin Pop

669 5905901c Iustin Pop
    """
670 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
671 5905901c Iustin Pop
    if alive:
672 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
673 5905901c Iustin Pop
                                   (instance_name, "already running"))
674 5905901c Iustin Pop
675 0df4d98a Guido Trotter
  @classmethod
676 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
677 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
678 c4fbefc8 Guido Trotter

679 c4fbefc8 Guido Trotter
    """
680 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
681 c4fbefc8 Guido Trotter
682 0df4d98a Guido Trotter
  @classmethod
683 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
684 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
685 c4fbefc8 Guido Trotter

686 c4fbefc8 Guido Trotter
    """
687 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
688 c4fbefc8 Guido Trotter
689 91c10532 Andrea Spadaccini
  @classmethod
690 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
691 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
692 91c10532 Andrea Spadaccini

693 91c10532 Andrea Spadaccini
    """
694 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
695 91c10532 Andrea Spadaccini
696 86d6bc2a Guido Trotter
  @staticmethod
697 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
698 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
699 86d6bc2a Guido Trotter

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

702 86d6bc2a Guido Trotter
    """
703 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
704 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
705 86d6bc2a Guido Trotter
    else:
706 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
707 86d6bc2a Guido Trotter
708 0df4d98a Guido Trotter
  @classmethod
709 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
710 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
711 38e250ba Guido Trotter

712 38e250ba Guido Trotter
    """
713 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
714 38e250ba Guido Trotter
715 7e66c35b Guido Trotter
  @classmethod
716 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
717 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
718 547a63b7 Balazs Lecz

719 547a63b7 Balazs Lecz
    """
720 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
721 547a63b7 Balazs Lecz
722 547a63b7 Balazs Lecz
  @classmethod
723 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
724 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
725 5d9bfd87 Apollon Oikonomopoulos
    given instance.
726 5d9bfd87 Apollon Oikonomopoulos

727 5d9bfd87 Apollon Oikonomopoulos
    """
728 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
729 5d9bfd87 Apollon Oikonomopoulos
730 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
731 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
732 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
733 5d9bfd87 Apollon Oikonomopoulos

734 5d9bfd87 Apollon Oikonomopoulos
    """
735 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
736 5d9bfd87 Apollon Oikonomopoulos
737 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
738 4f580fef Sรฉbastien Bocahu
  def _InstanceKeymapFile(cls, instance_name):
739 4f580fef Sรฉbastien Bocahu
    """Returns the name of the file containing the keymap for a given instance
740 4f580fef Sรฉbastien Bocahu

741 4f580fef Sรฉbastien Bocahu
    """
742 4f580fef Sรฉbastien Bocahu
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
743 4f580fef Sรฉbastien Bocahu
744 4f580fef Sรฉbastien Bocahu
  @classmethod
745 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
746 7548396c Guido Trotter
    """Try to read a uid file
747 7548396c Guido Trotter

748 7548396c Guido Trotter
    """
749 7548396c Guido Trotter
    if os.path.exists(uid_file):
750 7548396c Guido Trotter
      try:
751 682f7601 Guido Trotter
        uid = int(utils.ReadOneLineFile(uid_file))
752 aa0b600b Guido Trotter
        return uid
753 7548396c Guido Trotter
      except EnvironmentError:
754 7548396c Guido Trotter
        logging.warning("Can't read uid file", exc_info=True)
755 7548396c Guido Trotter
      except (TypeError, ValueError):
756 7548396c Guido Trotter
        logging.warning("Can't parse uid file contents", exc_info=True)
757 aa0b600b Guido Trotter
    return None
758 7548396c Guido Trotter
759 7548396c Guido Trotter
  @classmethod
760 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
761 547a63b7 Balazs Lecz
    """Removes an instance's rutime sockets/files/dirs.
762 7e66c35b Guido Trotter

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

803 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
804 eb58f9b1 Guido Trotter
    @type instance: instance object
805 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
806 eb58f9b1 Guido Trotter
    @type seq: int
807 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
808 eb58f9b1 Guido Trotter
    @type nic: nic object
809 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
810 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
811 eb58f9b1 Guido Trotter

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

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

861 b693125f Tsachy Shacham
    @type cpu_list: list of int
862 b693125f Tsachy Shacham
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
863 b693125f Tsachy Shacham
    @rtype: int
864 b693125f Tsachy Shacham
    @return: a bit mask of CPU affinities
865 b693125f Tsachy Shacham

866 b693125f Tsachy Shacham
    """
867 b693125f Tsachy Shacham
    if cpu_list == constants.CPU_PINNING_OFF:
868 b693125f Tsachy Shacham
      return constants.CPU_PINNING_ALL_KVM
869 b693125f Tsachy Shacham
    else:
870 b693125f Tsachy Shacham
      return sum(2 ** cpu for cpu in cpu_list)
871 b693125f Tsachy Shacham
872 b693125f Tsachy Shacham
  @classmethod
873 b693125f Tsachy Shacham
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
874 b693125f Tsachy Shacham
    """Change CPU affinity for running VM according to given CPU mask.
875 b693125f Tsachy Shacham

876 b693125f Tsachy Shacham
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
877 b693125f Tsachy Shacham
    @type cpu_mask: string
878 b693125f Tsachy Shacham
    @param process_id: process ID of KVM process. Used to pin entire VM
879 b693125f Tsachy Shacham
                       to physical CPUs.
880 b693125f Tsachy Shacham
    @type process_id: int
881 b693125f Tsachy Shacham
    @param thread_dict: map of virtual CPUs to KVM thread IDs
882 b693125f Tsachy Shacham
    @type thread_dict: dict int:int
883 b693125f Tsachy Shacham

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

914 b693125f Tsachy Shacham
    @type instance_name: string
915 b693125f Tsachy Shacham
    @param instance_name: instance in question
916 b693125f Tsachy Shacham
    @rtype: dictionary of int:int
917 b693125f Tsachy Shacham
    @return: a dictionary mapping vCPU numbers to thread IDs
918 b693125f Tsachy Shacham

919 b693125f Tsachy Shacham
    """
920 b693125f Tsachy Shacham
    result = {}
921 b693125f Tsachy Shacham
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
922 b693125f Tsachy Shacham
    for line in output.stdout.splitlines():
923 b693125f Tsachy Shacham
      match = self._CPU_INFO_RE.search(line)
924 b693125f Tsachy Shacham
      if not match:
925 b693125f Tsachy Shacham
        continue
926 b693125f Tsachy Shacham
      grp = map(int, match.groups())
927 b693125f Tsachy Shacham
      result[grp[0]] = grp[1]
928 b693125f Tsachy Shacham
929 b693125f Tsachy Shacham
    return result
930 b693125f Tsachy Shacham
931 1d8a7812 Andrea Spadaccini
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
932 1d8a7812 Andrea Spadaccini
    """Complete CPU pinning.
933 b693125f Tsachy Shacham

934 b693125f Tsachy Shacham
    @type instance_name: string
935 b693125f Tsachy Shacham
    @param instance_name: name of instance
936 b693125f Tsachy Shacham
    @type cpu_mask: string
937 b693125f Tsachy Shacham
    @param cpu_mask: CPU pinning mask as entered by user
938 b693125f Tsachy Shacham

939 b693125f Tsachy Shacham
    """
940 1d8a7812 Andrea Spadaccini
    # Get KVM process ID, to be used if need to pin entire VM
941 1d8a7812 Andrea Spadaccini
    _, pid, _ = self._InstancePidAlive(instance_name)
942 1d8a7812 Andrea Spadaccini
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
943 1d8a7812 Andrea Spadaccini
    thread_dict = self._GetVcpuThreadIds(instance_name)
944 1d8a7812 Andrea Spadaccini
    # Run CPU pinning, based on configured mask
945 1d8a7812 Andrea Spadaccini
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
946 b693125f Tsachy Shacham
947 eb58f9b1 Guido Trotter
  def ListInstances(self):
948 eb58f9b1 Guido Trotter
    """Get the list of running instances.
949 eb58f9b1 Guido Trotter

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

953 eb58f9b1 Guido Trotter
    """
954 eb58f9b1 Guido Trotter
    result = []
955 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
956 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
957 eb58f9b1 Guido Trotter
        result.append(name)
958 eb58f9b1 Guido Trotter
    return result
959 eb58f9b1 Guido Trotter
960 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
961 eb58f9b1 Guido Trotter
    """Get instance properties.
962 eb58f9b1 Guido Trotter

963 4fbb3c60 Guido Trotter
    @type instance_name: string
964 c41eea6e Iustin Pop
    @param instance_name: the instance name
965 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
966 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
967 eb58f9b1 Guido Trotter

968 eb58f9b1 Guido Trotter
    """
969 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
970 1f8b3a27 Guido Trotter
    if not alive:
971 eb58f9b1 Guido Trotter
      return None
972 eb58f9b1 Guido Trotter
973 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
974 fc84cd5d Guido Trotter
    istat = "---b-"
975 eb58f9b1 Guido Trotter
    times = "0"
976 eb58f9b1 Guido Trotter
977 89da2ff3 Guido Trotter
    try:
978 89da2ff3 Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
979 89da2ff3 Guido Trotter
      qmp.connect()
980 89da2ff3 Guido Trotter
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
981 89da2ff3 Guido Trotter
      # Will fail if ballooning is not enabled, but we can then just resort to
982 89da2ff3 Guido Trotter
      # the value above.
983 89da2ff3 Guido Trotter
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
984 89da2ff3 Guido Trotter
      memory = mem_bytes / 1048576
985 89da2ff3 Guido Trotter
    except errors.HypervisorError:
986 89da2ff3 Guido Trotter
      pass
987 89da2ff3 Guido Trotter
988 fc84cd5d Guido Trotter
    return (instance_name, pid, memory, vcpus, istat, times)
989 eb58f9b1 Guido Trotter
990 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
991 eb58f9b1 Guido Trotter
    """Get properties of all instances.
992 eb58f9b1 Guido Trotter

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

995 eb58f9b1 Guido Trotter
    """
996 eb58f9b1 Guido Trotter
    data = []
997 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
998 263b8de6 Guido Trotter
      try:
999 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
1000 263b8de6 Guido Trotter
      except errors.HypervisorError:
1001 3bc145d8 Bernardo Dal Seno
        # Ignore exceptions due to instances being shut down
1002 263b8de6 Guido Trotter
        continue
1003 263b8de6 Guido Trotter
      if info:
1004 263b8de6 Guido Trotter
        data.append(info)
1005 eb58f9b1 Guido Trotter
    return data
1006 eb58f9b1 Guido Trotter
1007 b73f1c59 Guido Trotter
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused,
1008 b73f1c59 Guido Trotter
                          kvmhelp):
1009 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
1010 eb58f9b1 Guido Trotter

1011 b73f1c59 Guido Trotter
    @type kvmhelp: string
1012 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1013 839642c2 Iustin Pop
    @attention: this function must not have any side-effects; for
1014 839642c2 Iustin Pop
        example, it must not write to the filesystem, or read values
1015 839642c2 Iustin Pop
        from the current system the are expected to differ between
1016 839642c2 Iustin Pop
        nodes, since it is only run once at instance startup;
1017 839642c2 Iustin Pop
        actions/kvm arguments that can vary between systems should be
1018 839642c2 Iustin Pop
        done in L{_ExecuteKVMRuntime}
1019 839642c2 Iustin Pop

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

1384 38e250ba Guido Trotter
    """
1385 38e250ba Guido Trotter
    try:
1386 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1387 38e250ba Guido Trotter
                      data=data)
1388 90c024f6 Guido Trotter
    except EnvironmentError, err:
1389 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1390 38e250ba Guido Trotter
1391 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
1392 38e250ba Guido Trotter
    """Read an instance's KVM runtime
1393 38e250ba Guido Trotter

1394 38e250ba Guido Trotter
    """
1395 38e250ba Guido Trotter
    try:
1396 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1397 90c024f6 Guido Trotter
    except EnvironmentError, err:
1398 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1399 38e250ba Guido Trotter
    return file_content
1400 38e250ba Guido Trotter
1401 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1402 38e250ba Guido Trotter
    """Save an instance's KVM runtime
1403 38e250ba Guido Trotter

1404 38e250ba Guido Trotter
    """
1405 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
1406 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1407 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
1408 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
1409 38e250ba Guido Trotter
1410 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1411 38e250ba Guido Trotter
    """Load an instance's KVM runtime
1412 38e250ba Guido Trotter

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

1424 76431533 Guido Trotter
    @type name: string
1425 76431533 Guido Trotter
    @param name: instance name
1426 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1427 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1428 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1429 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1430 76431533 Guido Trotter

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

1447 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1448 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1449 b73f1c59 Guido Trotter
    @type kvmhelp: string
1450 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1451 30e42c4e Guido Trotter

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

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

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

1686 585c8187 Guido Trotter
    @type text: string
1687 585c8187 Guido Trotter
    @param text: output of kvm --help
1688 585c8187 Guido Trotter
    @return: (version, v_maj, v_min, v_rev)
1689 5c3d5dfd Iustin Pop
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1690 585c8187 Guido Trotter

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

1709 bc0fed4b Guido Trotter
    @type kvm_path: string
1710 bc0fed4b Guido Trotter
    @param kvm_path: path to the kvm executable
1711 bc0fed4b Guido Trotter
    @type option: a key of _KVMOPTS_CMDS
1712 bc0fed4b Guido Trotter
    @param option: kvm option to fetch the output from
1713 6e043e60 Guido Trotter
    @return: output a supported kvm invocation
1714 e3b89628 Guido Trotter
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
1715 e3b89628 Guido Trotter

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2021 cd04dfd2 Michael Hanselmann
    Check that the required binaries exist.
2022 cd04dfd2 Michael Hanselmann

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

2025 eb58f9b1 Guido Trotter
    """
2026 1f4b9d39 Iustin Pop
    msgs = []
2027 1f4b9d39 Iustin Pop
    # FIXME: this is the global kvm binary, but the actual path can be
2028 1f4b9d39 Iustin Pop
    # customized as an hv parameter; we should use the nodegroup's
2029 1f4b9d39 Iustin Pop
    # default kvm path parameter here.
2030 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
2031 1f4b9d39 Iustin Pop
      msgs.append("The KVM binary ('%s') does not exist" % constants.KVM_PATH)
2032 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2033 1f4b9d39 Iustin Pop
      msgs.append("The socat binary ('%s') does not exist" %
2034 1f4b9d39 Iustin Pop
                  constants.SOCAT_PATH)
2035 1f4b9d39 Iustin Pop
2036 1f4b9d39 Iustin Pop
    return self._FormatVerifyResults(msgs)
2037 14aa53cb Guido Trotter
2038 6b5605e8 Iustin Pop
  @classmethod
2039 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2040 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2041 6b5605e8 Iustin Pop

2042 6b5605e8 Iustin Pop
    @type hvparams:  dict
2043 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2044 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2045 6b5605e8 Iustin Pop

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

2115 d19d94db Guido Trotter
    @type hvparams:  dict
2116 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2117 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2118 d19d94db Guido Trotter

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

2166 f5118ade Iustin Pop
    """
2167 f5118ade Iustin Pop
    cls.LinuxPowercycle()