Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 1f4b9d39

History | View | Annotate | Download (79 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 8df21834 Dimitris Aragiorgis
def _BuildNetworkEnv(name, network, gateway, network6, gateway6,
152 8df21834 Dimitris Aragiorgis
                     network_type, mac_prefix, tags, env):
153 8df21834 Dimitris Aragiorgis
  """Build environment variables concerning a Network.
154 8df21834 Dimitris Aragiorgis

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

988 4fbb3c60 Guido Trotter
    @type instance_name: string
989 c41eea6e Iustin Pop
    @param instance_name: the instance name
990 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
991 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
992 eb58f9b1 Guido Trotter

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

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

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

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

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

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

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

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

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

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

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

1458 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1459 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1460 b73f1c59 Guido Trotter
    @type kvmhelp: string
1461 b73f1c59 Guido Trotter
    @param kvmhelp: output of kvm --help
1462 30e42c4e Guido Trotter

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

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

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

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

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

1720 bc0fed4b Guido Trotter
    @type kvm_path: string
1721 bc0fed4b Guido Trotter
    @param kvm_path: path to the kvm executable
1722 bc0fed4b Guido Trotter
    @type option: a key of _KVMOPTS_CMDS
1723 bc0fed4b Guido Trotter
    @param option: kvm option to fetch the output from
1724 6e043e60 Guido Trotter
    @return: output a supported kvm invocation
1725 e3b89628 Guido Trotter
    @raise errors.HypervisorError: when the KVM help output cannot be retrieved
1726 e3b89628 Guido Trotter

1727 e3b89628 Guido Trotter
    """
1728 6e043e60 Guido Trotter
    assert option in cls._KVMOPTS_CMDS, "Invalid output option"
1729 6e043e60 Guido Trotter
1730 bc0fed4b Guido Trotter
    optlist, can_fail = cls._KVMOPTS_CMDS[option]
1731 bc0fed4b Guido Trotter
1732 bc0fed4b Guido Trotter
    result = utils.RunCmd([kvm_path] + optlist)
1733 bc0fed4b Guido Trotter
    if result.failed and not can_fail:
1734 af89fa76 Helga Velroyen
      raise errors.HypervisorError("Unable to get KVM %s output" %
1735 af89fa76 Helga Velroyen
                                    " ".join(cls._KVMOPTS_CMDS[option]))
1736 e3b89628 Guido Trotter
    return result.output
1737 e3b89628 Guido Trotter
1738 e3b89628 Guido Trotter
  @classmethod
1739 3b59ec02 Guido Trotter
  def _GetKVMVersion(cls, kvm_path):
1740 d7e4a2b1 Andrea Spadaccini
    """Return the installed KVM version.
1741 b52d85c1 Guido Trotter

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

1745 b52d85c1 Guido Trotter
    """
1746 6e043e60 Guido Trotter
    return cls._ParseKVMVersion(cls._GetKVMOutput(kvm_path, cls._KVMOPT_HELP))
1747 82e3bf85 Dimitris Aragiorgis
1748 82e3bf85 Dimitris Aragiorgis
  @classmethod
1749 82e3bf85 Dimitris Aragiorgis
  def _GetDefaultMachineVersion(cls, kvm_path):
1750 82e3bf85 Dimitris Aragiorgis
    """Return the default hardware revision (e.g. pc-1.1)
1751 82e3bf85 Dimitris Aragiorgis

1752 82e3bf85 Dimitris Aragiorgis
    """
1753 6e043e60 Guido Trotter
    output = cls._GetKVMOutput(kvm_path, cls._KVMOPT_MLIST)
1754 82e3bf85 Dimitris Aragiorgis
    match = cls._DEFAULT_MACHINE_VERSION_RE.search(output)
1755 82e3bf85 Dimitris Aragiorgis
    if match:
1756 82e3bf85 Dimitris Aragiorgis
      return match.group(1)
1757 82e3bf85 Dimitris Aragiorgis
    else:
1758 82e3bf85 Dimitris Aragiorgis
      return "pc"
1759 82e3bf85 Dimitris Aragiorgis
1760 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
1761 eb58f9b1 Guido Trotter
    """Stop an instance.
1762 eb58f9b1 Guido Trotter

1763 eb58f9b1 Guido Trotter
    """
1764 bbcf7ad0 Iustin Pop
    if name is not None and not force:
1765 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
1766 bbcf7ad0 Iustin Pop
    if name is None:
1767 bbcf7ad0 Iustin Pop
      name = instance.name
1768 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
1769 bbcf7ad0 Iustin Pop
    else:
1770 bbcf7ad0 Iustin Pop
      acpi = False
1771 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
1772 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
1773 bbcf7ad0 Iustin Pop
      if force or not acpi:
1774 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
1775 eb58f9b1 Guido Trotter
      else:
1776 d0c8c01d Iustin Pop
        self._CallMonitorCommand(name, "system_powerdown")
1777 eb58f9b1 Guido Trotter
1778 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
1779 8904b35c Guido Trotter
    """Cleanup after a stopped instance
1780 8904b35c Guido Trotter

1781 8904b35c Guido Trotter
    """
1782 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1783 8904b35c Guido Trotter
    if pid > 0 and alive:
1784 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
1785 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1786 eb58f9b1 Guido Trotter
1787 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
1788 eb58f9b1 Guido Trotter
    """Reboot an instance.
1789 eb58f9b1 Guido Trotter

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

1813 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1814 30e42c4e Guido Trotter
    @param instance: instance to be migrated
1815 30e42c4e Guido Trotter
    @rtype: string
1816 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
1817 30e42c4e Guido Trotter

1818 30e42c4e Guido Trotter
    """
1819 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
1820 30e42c4e Guido Trotter
1821 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
1822 30e42c4e Guido Trotter
    """Prepare to accept an instance.
1823 30e42c4e Guido Trotter

1824 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1825 30e42c4e Guido Trotter
    @param instance: instance to be accepted
1826 30e42c4e Guido Trotter
    @type info: string
1827 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
1828 30e42c4e Guido Trotter
    @type target: string
1829 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
1830 30e42c4e Guido Trotter

1831 30e42c4e Guido Trotter
    """
1832 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1833 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1834 4b9638dc Guido Trotter
    kvmpath = instance.hvparams[constants.HV_KVM_PATH]
1835 6e043e60 Guido Trotter
    kvmhelp = self._GetKVMOutput(kvmpath, self._KVMOPT_HELP)
1836 b73f1c59 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, kvmhelp,
1837 b73f1c59 Guido Trotter
                            incoming=incoming_address)
1838 30e42c4e Guido Trotter
1839 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
1840 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
1841 30e42c4e Guido Trotter

1842 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
1843 30e42c4e Guido Trotter

1844 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1845 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
1846 30e42c4e Guido Trotter

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

1874 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
1875 30e42c4e Guido Trotter
    currently running.
1876 30e42c4e Guido Trotter

1877 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
1878 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
1879 30e42c4e Guido Trotter
    @type target: string
1880 30e42c4e Guido Trotter
    @param target: ip address of the target node
1881 30e42c4e Guido Trotter
    @type live: boolean
1882 30e42c4e Guido Trotter
    @param live: perform a live migration
1883 30e42c4e Guido Trotter

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

1908 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
1909 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
1910 6a1434d7 Andrea Spadaccini
    @type success: bool
1911 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
1912 6a1434d7 Andrea Spadaccini
    @type live: bool
1913 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
1914 6a1434d7 Andrea Spadaccini

1915 6a1434d7 Andrea Spadaccini
    """
1916 6a1434d7 Andrea Spadaccini
    if success:
1917 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
1918 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
1919 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
1920 6a1434d7 Andrea Spadaccini
    elif live:
1921 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1922 6a1434d7 Andrea Spadaccini
1923 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
1924 6a1434d7 Andrea Spadaccini
    """Get the migration status
1925 6a1434d7 Andrea Spadaccini

1926 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
1927 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
1928 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
1929 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
1930 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
1931 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
1932 6a1434d7 Andrea Spadaccini

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

1964 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
1965 3d836750 Guido Trotter
    @param instance: instance to be accepted
1966 3d836750 Guido Trotter
    @type mem: int
1967 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
1968 3d836750 Guido Trotter

1969 3d836750 Guido Trotter
    """
1970 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
1971 3d836750 Guido Trotter
1972 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
1973 eb58f9b1 Guido Trotter
    """Return information about the node.
1974 eb58f9b1 Guido Trotter

1975 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
1976 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
1977 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
1978 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
1979 34fbc862 Andrea Spadaccini
          - hv_version: the hypervisor version in the form (major, minor,
1980 34fbc862 Andrea Spadaccini
                        revision)
1981 eb58f9b1 Guido Trotter

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

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

2032 cd04dfd2 Michael Hanselmann
    Check that the required binaries exist.
2033 cd04dfd2 Michael Hanselmann

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

2036 eb58f9b1 Guido Trotter
    """
2037 1f4b9d39 Iustin Pop
    msgs = []
2038 1f4b9d39 Iustin Pop
    # FIXME: this is the global kvm binary, but the actual path can be
2039 1f4b9d39 Iustin Pop
    # customized as an hv parameter; we should use the nodegroup's
2040 1f4b9d39 Iustin Pop
    # default kvm path parameter here.
2041 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
2042 1f4b9d39 Iustin Pop
      msgs.append("The KVM binary ('%s') does not exist" % constants.KVM_PATH)
2043 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2044 1f4b9d39 Iustin Pop
      msgs.append("The socat binary ('%s') does not exist" %
2045 1f4b9d39 Iustin Pop
                  constants.SOCAT_PATH)
2046 1f4b9d39 Iustin Pop
2047 1f4b9d39 Iustin Pop
    return self._FormatVerifyResults(msgs)
2048 14aa53cb Guido Trotter
2049 6b5605e8 Iustin Pop
  @classmethod
2050 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2051 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2052 6b5605e8 Iustin Pop

2053 6b5605e8 Iustin Pop
    @type hvparams:  dict
2054 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2055 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2056 6b5605e8 Iustin Pop

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

2126 d19d94db Guido Trotter
    @type hvparams:  dict
2127 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2128 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2129 d19d94db Guido Trotter

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

2177 f5118ade Iustin Pop
    """
2178 f5118ade Iustin Pop
    cls.LinuxPowercycle()