Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 61eb1a46

History | View | Annotate | Download (70.5 kB)

1 eb58f9b1 Guido Trotter
#
2 eb58f9b1 Guido Trotter
#
3 eb58f9b1 Guido Trotter
4 41e794f6 Apollon Oikonomopoulos
# Copyright (C) 2008, 2009, 2010, 2011 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 eb58f9b1 Guido Trotter
from ganeti.hypervisor import hv_base
53 a744b676 Manuel Franceschini
from ganeti import netutils
54 5d9bfd87 Apollon Oikonomopoulos
from ganeti.utils import wrapper as utils_wrapper
55 eb58f9b1 Guido Trotter
56 eb58f9b1 Guido Trotter
57 748e4b5a Michael Hanselmann
_KVM_NETWORK_SCRIPT = constants.SYSCONFDIR + "/ganeti/kvm-vif-bridge"
58 b693125f Tsachy Shacham
_KVM_START_PAUSED_FLAG = "-S"
59 748e4b5a Michael Hanselmann
60 199b2053 Apollon Oikonomopoulos
# TUN/TAP driver constants, taken from <linux/if_tun.h>
61 199b2053 Apollon Oikonomopoulos
# They are architecture-independent and already hardcoded in qemu-kvm source,
62 199b2053 Apollon Oikonomopoulos
# so we can safely include them here.
63 199b2053 Apollon Oikonomopoulos
TUNSETIFF = 0x400454ca
64 199b2053 Apollon Oikonomopoulos
TUNGETIFF = 0x800454d2
65 199b2053 Apollon Oikonomopoulos
TUNGETFEATURES = 0x800454cf
66 199b2053 Apollon Oikonomopoulos
IFF_TAP = 0x0002
67 199b2053 Apollon Oikonomopoulos
IFF_NO_PI = 0x1000
68 199b2053 Apollon Oikonomopoulos
IFF_VNET_HDR = 0x4000
69 199b2053 Apollon Oikonomopoulos
70 199b2053 Apollon Oikonomopoulos
71 199b2053 Apollon Oikonomopoulos
def _ProbeTapVnetHdr(fd):
72 199b2053 Apollon Oikonomopoulos
  """Check whether to enable the IFF_VNET_HDR flag.
73 199b2053 Apollon Oikonomopoulos

74 199b2053 Apollon Oikonomopoulos
  To do this, _all_ of the following conditions must be met:
75 199b2053 Apollon Oikonomopoulos
   1. TUNGETFEATURES ioctl() *must* be implemented
76 199b2053 Apollon Oikonomopoulos
   2. TUNGETFEATURES ioctl() result *must* contain the IFF_VNET_HDR flag
77 199b2053 Apollon Oikonomopoulos
   3. TUNGETIFF ioctl() *must* be implemented; reading the kernel code in
78 199b2053 Apollon Oikonomopoulos
      drivers/net/tun.c there is no way to test this until after the tap device
79 199b2053 Apollon Oikonomopoulos
      has been created using TUNSETIFF, and there is no way to change the
80 199b2053 Apollon Oikonomopoulos
      IFF_VNET_HDR flag after creating the interface, catch-22! However both
81 199b2053 Apollon Oikonomopoulos
      TUNGETIFF and TUNGETFEATURES were introduced in kernel version 2.6.27,
82 199b2053 Apollon Oikonomopoulos
      thus we can expect TUNGETIFF to be present if TUNGETFEATURES is.
83 199b2053 Apollon Oikonomopoulos

84 199b2053 Apollon Oikonomopoulos
   @type fd: int
85 199b2053 Apollon Oikonomopoulos
   @param fd: the file descriptor of /dev/net/tun
86 199b2053 Apollon Oikonomopoulos

87 199b2053 Apollon Oikonomopoulos
  """
88 199b2053 Apollon Oikonomopoulos
  req = struct.pack("I", 0)
89 199b2053 Apollon Oikonomopoulos
  try:
90 199b2053 Apollon Oikonomopoulos
    res = fcntl.ioctl(fd, TUNGETFEATURES, req)
91 199b2053 Apollon Oikonomopoulos
  except EnvironmentError:
92 199b2053 Apollon Oikonomopoulos
    logging.warning("TUNGETFEATURES ioctl() not implemented")
93 199b2053 Apollon Oikonomopoulos
    return False
94 199b2053 Apollon Oikonomopoulos
95 199b2053 Apollon Oikonomopoulos
  tunflags = struct.unpack("I", res)[0]
96 199b2053 Apollon Oikonomopoulos
  if tunflags & IFF_VNET_HDR:
97 199b2053 Apollon Oikonomopoulos
    return True
98 199b2053 Apollon Oikonomopoulos
  else:
99 199b2053 Apollon Oikonomopoulos
    logging.warning("Host does not support IFF_VNET_HDR, not enabling")
100 199b2053 Apollon Oikonomopoulos
    return False
101 199b2053 Apollon Oikonomopoulos
102 199b2053 Apollon Oikonomopoulos
103 199b2053 Apollon Oikonomopoulos
def _OpenTap(vnet_hdr=True):
104 199b2053 Apollon Oikonomopoulos
  """Open a new tap device and return its file descriptor.
105 199b2053 Apollon Oikonomopoulos

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

109 199b2053 Apollon Oikonomopoulos
  @type vnet_hdr: boolean
110 199b2053 Apollon Oikonomopoulos
  @param vnet_hdr: Enable the VNET Header
111 199b2053 Apollon Oikonomopoulos
  @return: (ifname, tapfd)
112 199b2053 Apollon Oikonomopoulos
  @rtype: tuple
113 199b2053 Apollon Oikonomopoulos

114 199b2053 Apollon Oikonomopoulos
  """
115 199b2053 Apollon Oikonomopoulos
  try:
116 199b2053 Apollon Oikonomopoulos
    tapfd = os.open("/dev/net/tun", os.O_RDWR)
117 199b2053 Apollon Oikonomopoulos
  except EnvironmentError:
118 199b2053 Apollon Oikonomopoulos
    raise errors.HypervisorError("Failed to open /dev/net/tun")
119 199b2053 Apollon Oikonomopoulos
120 199b2053 Apollon Oikonomopoulos
  flags = IFF_TAP | IFF_NO_PI
121 199b2053 Apollon Oikonomopoulos
122 199b2053 Apollon Oikonomopoulos
  if vnet_hdr and _ProbeTapVnetHdr(tapfd):
123 199b2053 Apollon Oikonomopoulos
    flags |= IFF_VNET_HDR
124 199b2053 Apollon Oikonomopoulos
125 199b2053 Apollon Oikonomopoulos
  # The struct ifreq ioctl request (see netdevice(7))
126 199b2053 Apollon Oikonomopoulos
  ifr = struct.pack("16sh", "", flags)
127 199b2053 Apollon Oikonomopoulos
128 199b2053 Apollon Oikonomopoulos
  try:
129 199b2053 Apollon Oikonomopoulos
    res = fcntl.ioctl(tapfd, TUNSETIFF, ifr)
130 199b2053 Apollon Oikonomopoulos
  except EnvironmentError:
131 199b2053 Apollon Oikonomopoulos
    raise errors.HypervisorError("Failed to allocate a new TAP device")
132 199b2053 Apollon Oikonomopoulos
133 199b2053 Apollon Oikonomopoulos
  # Get the interface name from the ioctl
134 199b2053 Apollon Oikonomopoulos
  ifname = struct.unpack("16sh", res)[0].strip("\x00")
135 199b2053 Apollon Oikonomopoulos
  return (ifname, tapfd)
136 199b2053 Apollon Oikonomopoulos
137 748e4b5a Michael Hanselmann
138 91c10532 Andrea Spadaccini
class QmpMessage:
139 91c10532 Andrea Spadaccini
  """QEMU Messaging Protocol (QMP) message.
140 91c10532 Andrea Spadaccini

141 91c10532 Andrea Spadaccini
  """
142 91c10532 Andrea Spadaccini
  def __init__(self, data):
143 91c10532 Andrea Spadaccini
    """Creates a new QMP message based on the passed data.
144 91c10532 Andrea Spadaccini

145 91c10532 Andrea Spadaccini
    """
146 91c10532 Andrea Spadaccini
    if not isinstance(data, dict):
147 91c10532 Andrea Spadaccini
      raise TypeError("QmpMessage must be initialized with a dict")
148 91c10532 Andrea Spadaccini
149 91c10532 Andrea Spadaccini
    self.data = data
150 91c10532 Andrea Spadaccini
151 91c10532 Andrea Spadaccini
  def __getitem__(self, field_name):
152 91c10532 Andrea Spadaccini
    """Get the value of the required field if present, or None.
153 91c10532 Andrea Spadaccini

154 91c10532 Andrea Spadaccini
    Overrides the [] operator to provide access to the message data,
155 91c10532 Andrea Spadaccini
    returning None if the required item is not in the message
156 91c10532 Andrea Spadaccini
    @return: the value of the field_name field, or None if field_name
157 91c10532 Andrea Spadaccini
             is not contained in the message
158 91c10532 Andrea Spadaccini

159 91c10532 Andrea Spadaccini
    """
160 9b87c2cf Michael Hanselmann
    return self.data.get(field_name, None)
161 91c10532 Andrea Spadaccini
162 91c10532 Andrea Spadaccini
  def __setitem__(self, field_name, field_value):
163 91c10532 Andrea Spadaccini
    """Set the value of the required field_name to field_value.
164 91c10532 Andrea Spadaccini

165 91c10532 Andrea Spadaccini
    """
166 91c10532 Andrea Spadaccini
    self.data[field_name] = field_value
167 91c10532 Andrea Spadaccini
168 91c10532 Andrea Spadaccini
  @staticmethod
169 91c10532 Andrea Spadaccini
  def BuildFromJsonString(json_string):
170 91c10532 Andrea Spadaccini
    """Build a QmpMessage from a JSON encoded string.
171 91c10532 Andrea Spadaccini

172 91c10532 Andrea Spadaccini
    @type json_string: str
173 91c10532 Andrea Spadaccini
    @param json_string: JSON string representing the message
174 91c10532 Andrea Spadaccini
    @rtype: L{QmpMessage}
175 91c10532 Andrea Spadaccini
    @return: a L{QmpMessage} built from json_string
176 91c10532 Andrea Spadaccini

177 91c10532 Andrea Spadaccini
    """
178 91c10532 Andrea Spadaccini
    # Parse the string
179 91c10532 Andrea Spadaccini
    data = serializer.LoadJson(json_string)
180 91c10532 Andrea Spadaccini
    return QmpMessage(data)
181 91c10532 Andrea Spadaccini
182 91c10532 Andrea Spadaccini
  def __str__(self):
183 a182a3ed Michael Hanselmann
    # The protocol expects the JSON object to be sent as a single line.
184 a182a3ed Michael Hanselmann
    return serializer.DumpJson(self.data)
185 91c10532 Andrea Spadaccini
186 91c10532 Andrea Spadaccini
  def __eq__(self, other):
187 91c10532 Andrea Spadaccini
    # When comparing two QmpMessages, we are interested in comparing
188 91c10532 Andrea Spadaccini
    # their internal representation of the message data
189 91c10532 Andrea Spadaccini
    return self.data == other.data
190 91c10532 Andrea Spadaccini
191 91c10532 Andrea Spadaccini
192 91c10532 Andrea Spadaccini
class QmpConnection:
193 91c10532 Andrea Spadaccini
  """Connection to the QEMU Monitor using the QEMU Monitor Protocol (QMP).
194 91c10532 Andrea Spadaccini

195 91c10532 Andrea Spadaccini
  """
196 91c10532 Andrea Spadaccini
  _FIRST_MESSAGE_KEY = "QMP"
197 91c10532 Andrea Spadaccini
  _EVENT_KEY = "event"
198 91c10532 Andrea Spadaccini
  _ERROR_KEY = "error"
199 89da2ff3 Guido Trotter
  _RETURN_KEY = RETURN_KEY = "return"
200 89da2ff3 Guido Trotter
  _ACTUAL_KEY = ACTUAL_KEY = "actual"
201 91c10532 Andrea Spadaccini
  _ERROR_CLASS_KEY = "class"
202 91c10532 Andrea Spadaccini
  _ERROR_DATA_KEY = "data"
203 91c10532 Andrea Spadaccini
  _ERROR_DESC_KEY = "desc"
204 91c10532 Andrea Spadaccini
  _EXECUTE_KEY = "execute"
205 91c10532 Andrea Spadaccini
  _ARGUMENTS_KEY = "arguments"
206 91c10532 Andrea Spadaccini
  _CAPABILITIES_COMMAND = "qmp_capabilities"
207 91c10532 Andrea Spadaccini
  _MESSAGE_END_TOKEN = "\r\n"
208 91c10532 Andrea Spadaccini
  _SOCKET_TIMEOUT = 5
209 91c10532 Andrea Spadaccini
210 91c10532 Andrea Spadaccini
  def __init__(self, monitor_filename):
211 91c10532 Andrea Spadaccini
    """Instantiates the QmpConnection object.
212 91c10532 Andrea Spadaccini

213 91c10532 Andrea Spadaccini
    @type monitor_filename: string
214 91c10532 Andrea Spadaccini
    @param monitor_filename: the filename of the UNIX raw socket on which the
215 91c10532 Andrea Spadaccini
                             QMP monitor is listening
216 91c10532 Andrea Spadaccini

217 91c10532 Andrea Spadaccini
    """
218 91c10532 Andrea Spadaccini
    self.monitor_filename = monitor_filename
219 91c10532 Andrea Spadaccini
    self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
220 91c10532 Andrea Spadaccini
    # We want to fail if the server doesn't send a complete message
221 91c10532 Andrea Spadaccini
    # in a reasonable amount of time
222 91c10532 Andrea Spadaccini
    self.sock.settimeout(self._SOCKET_TIMEOUT)
223 91c10532 Andrea Spadaccini
    self._connected = False
224 91c10532 Andrea Spadaccini
    self._buf = ""
225 91c10532 Andrea Spadaccini
226 fc84cd5d Guido Trotter
  def _check_socket(self):
227 fc84cd5d Guido Trotter
    sock_stat = None
228 fc84cd5d Guido Trotter
    try:
229 fc84cd5d Guido Trotter
      sock_stat = os.stat(self.monitor_filename)
230 fc84cd5d Guido Trotter
    except EnvironmentError, err:
231 fc84cd5d Guido Trotter
      if err.errno == errno.ENOENT:
232 fc84cd5d Guido Trotter
        raise errors.HypervisorError("No qmp socket found")
233 fc84cd5d Guido Trotter
      else:
234 fc84cd5d Guido Trotter
        raise errors.HypervisorError("Error checking qmp socket: %s",
235 fc84cd5d Guido Trotter
                                     utils.ErrnoOrStr(err))
236 fc84cd5d Guido Trotter
    if not stat.S_ISSOCK(sock_stat.st_mode):
237 fc84cd5d Guido Trotter
      raise errors.HypervisorError("Qmp socket is not a socket")
238 fc84cd5d Guido Trotter
239 91c10532 Andrea Spadaccini
  def _check_connection(self):
240 91c10532 Andrea Spadaccini
    """Make sure that the connection is established.
241 91c10532 Andrea Spadaccini

242 91c10532 Andrea Spadaccini
    """
243 91c10532 Andrea Spadaccini
    if not self._connected:
244 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("To use a QmpConnection you need to first"
245 91c10532 Andrea Spadaccini
                                   " invoke connect() on it")
246 91c10532 Andrea Spadaccini
247 91c10532 Andrea Spadaccini
  def connect(self):
248 91c10532 Andrea Spadaccini
    """Connects to the QMP monitor.
249 91c10532 Andrea Spadaccini

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

253 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
254 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
255 91c10532 Andrea Spadaccini

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

285 91c10532 Andrea Spadaccini
    Seeks for a QMP message in the given buf. If found, it parses it and
286 91c10532 Andrea Spadaccini
    returns it together with the rest of the characters in the buf.
287 91c10532 Andrea Spadaccini
    If no message is found, returns None and the whole buffer.
288 91c10532 Andrea Spadaccini

289 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
290 91c10532 Andrea Spadaccini

291 91c10532 Andrea Spadaccini
    """
292 91c10532 Andrea Spadaccini
    message = None
293 91c10532 Andrea Spadaccini
    # Check if we got the message end token (CRLF, as per the QEMU Protocol
294 91c10532 Andrea Spadaccini
    # Specification 0.1 - Section 2.1.1)
295 91c10532 Andrea Spadaccini
    pos = buf.find(self._MESSAGE_END_TOKEN)
296 91c10532 Andrea Spadaccini
    if pos >= 0:
297 91c10532 Andrea Spadaccini
      try:
298 91c10532 Andrea Spadaccini
        message = QmpMessage.BuildFromJsonString(buf[:pos + 1])
299 91c10532 Andrea Spadaccini
      except Exception, err:
300 91c10532 Andrea Spadaccini
        raise errors.ProgrammerError("QMP data serialization error: %s" % err)
301 91c10532 Andrea Spadaccini
      buf = buf[pos + 1:]
302 91c10532 Andrea Spadaccini
303 91c10532 Andrea Spadaccini
    return (message, buf)
304 91c10532 Andrea Spadaccini
305 91c10532 Andrea Spadaccini
  def _Recv(self):
306 91c10532 Andrea Spadaccini
    """Receives a message from QMP and decodes the received JSON object.
307 91c10532 Andrea Spadaccini

308 91c10532 Andrea Spadaccini
    @rtype: QmpMessage
309 91c10532 Andrea Spadaccini
    @return: the received message
310 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
311 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
312 91c10532 Andrea Spadaccini

313 91c10532 Andrea Spadaccini
    """
314 91c10532 Andrea Spadaccini
    self._check_connection()
315 91c10532 Andrea Spadaccini
316 91c10532 Andrea Spadaccini
    # Check if there is already a message in the buffer
317 91c10532 Andrea Spadaccini
    (message, self._buf) = self._ParseMessage(self._buf)
318 91c10532 Andrea Spadaccini
    if message:
319 91c10532 Andrea Spadaccini
      return message
320 91c10532 Andrea Spadaccini
321 91c10532 Andrea Spadaccini
    recv_buffer = StringIO.StringIO(self._buf)
322 91c10532 Andrea Spadaccini
    recv_buffer.seek(len(self._buf))
323 91c10532 Andrea Spadaccini
    try:
324 91c10532 Andrea Spadaccini
      while True:
325 91c10532 Andrea Spadaccini
        data = self.sock.recv(4096)
326 91c10532 Andrea Spadaccini
        if not data:
327 91c10532 Andrea Spadaccini
          break
328 91c10532 Andrea Spadaccini
        recv_buffer.write(data)
329 91c10532 Andrea Spadaccini
330 91c10532 Andrea Spadaccini
        (message, self._buf) = self._ParseMessage(recv_buffer.getvalue())
331 91c10532 Andrea Spadaccini
        if message:
332 91c10532 Andrea Spadaccini
          return message
333 91c10532 Andrea Spadaccini
334 91c10532 Andrea Spadaccini
    except socket.timeout, err:
335 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while receiving a QMP message: "
336 91c10532 Andrea Spadaccini
                                   "%s" % (err))
337 91c10532 Andrea Spadaccini
    except socket.error, err:
338 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to receive data from KVM using the"
339 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
340 91c10532 Andrea Spadaccini
341 91c10532 Andrea Spadaccini
  def _Send(self, message):
342 91c10532 Andrea Spadaccini
    """Encodes and sends a message to KVM using QMP.
343 91c10532 Andrea Spadaccini

344 91c10532 Andrea Spadaccini
    @type message: QmpMessage
345 91c10532 Andrea Spadaccini
    @param message: message to send to KVM
346 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
347 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
348 91c10532 Andrea Spadaccini

349 91c10532 Andrea Spadaccini
    """
350 91c10532 Andrea Spadaccini
    self._check_connection()
351 91c10532 Andrea Spadaccini
    try:
352 91c10532 Andrea Spadaccini
      message_str = str(message)
353 91c10532 Andrea Spadaccini
    except Exception, err:
354 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("QMP data deserialization error: %s" % err)
355 91c10532 Andrea Spadaccini
356 91c10532 Andrea Spadaccini
    try:
357 91c10532 Andrea Spadaccini
      self.sock.sendall(message_str)
358 91c10532 Andrea Spadaccini
    except socket.timeout, err:
359 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while sending a QMP message: "
360 91c10532 Andrea Spadaccini
                                   "%s (%s)" % (err.string, err.errno))
361 91c10532 Andrea Spadaccini
    except socket.error, err:
362 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to send data from KVM using the"
363 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
364 91c10532 Andrea Spadaccini
365 91c10532 Andrea Spadaccini
  def Execute(self, command, arguments=None):
366 91c10532 Andrea Spadaccini
    """Executes a QMP command and returns the response of the server.
367 91c10532 Andrea Spadaccini

368 91c10532 Andrea Spadaccini
    @type command: str
369 91c10532 Andrea Spadaccini
    @param command: the command to execute
370 91c10532 Andrea Spadaccini
    @type arguments: dict
371 91c10532 Andrea Spadaccini
    @param arguments: dictionary of arguments to be passed to the command
372 91c10532 Andrea Spadaccini
    @rtype: dict
373 91c10532 Andrea Spadaccini
    @return: dictionary representing the received JSON object
374 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
375 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
376 91c10532 Andrea Spadaccini

377 91c10532 Andrea Spadaccini
    """
378 91c10532 Andrea Spadaccini
    self._check_connection()
379 91c10532 Andrea Spadaccini
    message = QmpMessage({self._EXECUTE_KEY: command})
380 91c10532 Andrea Spadaccini
    if arguments:
381 91c10532 Andrea Spadaccini
      message[self._ARGUMENTS_KEY] = arguments
382 91c10532 Andrea Spadaccini
    self._Send(message)
383 91c10532 Andrea Spadaccini
384 91c10532 Andrea Spadaccini
    # Events can occur between the sending of the command and the reception
385 91c10532 Andrea Spadaccini
    # of the response, so we need to filter out messages with the event key.
386 91c10532 Andrea Spadaccini
    while True:
387 91c10532 Andrea Spadaccini
      response = self._Recv()
388 91c10532 Andrea Spadaccini
      err = response[self._ERROR_KEY]
389 91c10532 Andrea Spadaccini
      if err:
390 91c10532 Andrea Spadaccini
        raise errors.HypervisorError("kvm: error executing the %s"
391 91c10532 Andrea Spadaccini
                                     " command: %s (%s, %s):" %
392 91c10532 Andrea Spadaccini
                                     (command,
393 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DESC_KEY],
394 91c10532 Andrea Spadaccini
                                      err[self._ERROR_CLASS_KEY],
395 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DATA_KEY]))
396 91c10532 Andrea Spadaccini
397 91c10532 Andrea Spadaccini
      elif not response[self._EVENT_KEY]:
398 91c10532 Andrea Spadaccini
        return response
399 91c10532 Andrea Spadaccini
400 91c10532 Andrea Spadaccini
401 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
402 65107a2f Michael Hanselmann
  """KVM hypervisor interface
403 65107a2f Michael Hanselmann

404 65107a2f Michael Hanselmann
  """
405 d271c6fd Iustin Pop
  CAN_MIGRATE = True
406 eb58f9b1 Guido Trotter
407 eb58f9b1 Guido Trotter
  _ROOT_DIR = constants.RUN_GANETI_DIR + "/kvm-hypervisor"
408 a1d79fc6 Guido Trotter
  _PIDS_DIR = _ROOT_DIR + "/pid" # contains live instances pids
409 7548396c Guido Trotter
  _UIDS_DIR = _ROOT_DIR + "/uid" # contains instances reserved uids
410 a1d79fc6 Guido Trotter
  _CTRL_DIR = _ROOT_DIR + "/ctrl" # contains instances control sockets
411 a1d79fc6 Guido Trotter
  _CONF_DIR = _ROOT_DIR + "/conf" # contains instances startup data
412 5d9bfd87 Apollon Oikonomopoulos
  _NICS_DIR = _ROOT_DIR + "/nic" # contains instances nic <-> tap associations
413 4f580fef Sรฉbastien Bocahu
  _KEYMAP_DIR = _ROOT_DIR + "/keymap" # contains instances keymaps
414 547a63b7 Balazs Lecz
  # KVM instances with chroot enabled are started in empty chroot directories.
415 547a63b7 Balazs Lecz
  _CHROOT_DIR = _ROOT_DIR + "/chroot" # for empty chroot directories
416 547a63b7 Balazs Lecz
  # After an instance is stopped, its chroot directory is removed.
417 547a63b7 Balazs Lecz
  # If the chroot directory is not empty, it can't be removed.
418 547a63b7 Balazs Lecz
  # A non-empty chroot directory indicates a possible security incident.
419 547a63b7 Balazs Lecz
  # To support forensics, the non-empty chroot directory is quarantined in
420 547a63b7 Balazs Lecz
  # a separate directory, called 'chroot-quarantine'.
421 547a63b7 Balazs Lecz
  _CHROOT_QUARANTINE_DIR = _ROOT_DIR + "/chroot-quarantine"
422 5d9bfd87 Apollon Oikonomopoulos
  _DIRS = [_ROOT_DIR, _PIDS_DIR, _UIDS_DIR, _CTRL_DIR, _CONF_DIR, _NICS_DIR,
423 547a63b7 Balazs Lecz
           _CHROOT_DIR, _CHROOT_QUARANTINE_DIR]
424 eb58f9b1 Guido Trotter
425 205ab586 Iustin Pop
  PARAMETERS = {
426 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK,
427 205ab586 Iustin Pop
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
428 205ab586 Iustin Pop
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
429 205ab586 Iustin Pop
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
430 205ab586 Iustin Pop
    constants.HV_ACPI: hv_base.NO_CHECK,
431 205ab586 Iustin Pop
    constants.HV_SERIAL_CONSOLE: hv_base.NO_CHECK,
432 d73ef63f Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS:
433 8b312c1d Manuel Franceschini
      (False, lambda x: (netutils.IP4Address.IsValid(x) or
434 8b312c1d Manuel Franceschini
                         utils.IsNormAbsPath(x)),
435 d73ef63f Michael Hanselmann
       "the VNC bind address must be either a valid IP address or an absolute"
436 d73ef63f Michael Hanselmann
       " pathname", None, None),
437 205ab586 Iustin Pop
    constants.HV_VNC_TLS: hv_base.NO_CHECK,
438 205ab586 Iustin Pop
    constants.HV_VNC_X509: hv_base.OPT_DIR_CHECK,
439 205ab586 Iustin Pop
    constants.HV_VNC_X509_VERIFY: hv_base.NO_CHECK,
440 6e6bb8d5 Guido Trotter
    constants.HV_VNC_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
441 b1cb62bd Andrea Spadaccini
    constants.HV_KVM_SPICE_BIND: hv_base.NO_CHECK, # will be checked later
442 b1cb62bd Andrea Spadaccini
    constants.HV_KVM_SPICE_IP_VERSION:
443 b1cb62bd Andrea Spadaccini
      (False, lambda x: (x == constants.IFACE_NO_IP_VERSION_SPECIFIED or
444 b1cb62bd Andrea Spadaccini
                         x in constants.VALID_IP_VERSIONS),
445 b1cb62bd Andrea Spadaccini
       "the SPICE IP version should be 4 or 6",
446 b1cb62bd Andrea Spadaccini
       None, None),
447 b451c4c7 Andrea Spadaccini
    constants.HV_KVM_SPICE_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
448 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR:
449 ea064d24 Andrea Spadaccini
      hv_base.ParamInSet(False,
450 ea064d24 Andrea Spadaccini
        constants.HT_KVM_SPICE_VALID_LOSSLESS_IMG_COMPR_OPTIONS),
451 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_JPEG_IMG_COMPR:
452 ea064d24 Andrea Spadaccini
      hv_base.ParamInSet(False,
453 ea064d24 Andrea Spadaccini
        constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
454 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR:
455 ea064d24 Andrea Spadaccini
      hv_base.ParamInSet(False,
456 ea064d24 Andrea Spadaccini
        constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
457 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION:
458 ea064d24 Andrea Spadaccini
      hv_base.ParamInSet(False,
459 ea064d24 Andrea Spadaccini
        constants.HT_KVM_SPICE_VALID_VIDEO_STREAM_DETECTION_OPTIONS),
460 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_AUDIO_COMPR: hv_base.NO_CHECK,
461 bfe86c76 Andrea Spadaccini
    constants.HV_KVM_SPICE_USE_TLS: hv_base.NO_CHECK,
462 3e40b587 Andrea Spadaccini
    constants.HV_KVM_SPICE_TLS_CIPHERS: hv_base.NO_CHECK,
463 3e40b587 Andrea Spadaccini
    constants.HV_KVM_SPICE_USE_VDAGENT: hv_base.NO_CHECK,
464 cc130cc7 Marco Casavecchia
    constants.HV_KVM_FLOPPY_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
465 205ab586 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
466 cc130cc7 Marco Casavecchia
    constants.HV_KVM_CDROM2_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
467 d73ef63f Michael Hanselmann
    constants.HV_BOOT_ORDER:
468 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
469 d73ef63f Michael Hanselmann
    constants.HV_NIC_TYPE:
470 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
471 d73ef63f Michael Hanselmann
    constants.HV_DISK_TYPE:
472 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
473 cc130cc7 Marco Casavecchia
    constants.HV_KVM_CDROM_DISK_TYPE:
474 cc130cc7 Marco Casavecchia
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_DISK_TYPES),
475 d73ef63f Michael Hanselmann
    constants.HV_USB_MOUSE:
476 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
477 4f580fef Sรฉbastien Bocahu
    constants.HV_KEYMAP: hv_base.NO_CHECK,
478 e2d14329 Andrea Spadaccini
    constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
479 e43d4f9f Apollon Oikonomopoulos
    constants.HV_MIGRATION_BANDWIDTH: hv_base.NO_CHECK,
480 e43d4f9f Apollon Oikonomopoulos
    constants.HV_MIGRATION_DOWNTIME: hv_base.NO_CHECK,
481 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
482 6b970cef Jun Futagawa
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
483 19572932 Iustin Pop
    constants.HV_DISK_CACHE:
484 19572932 Iustin Pop
      hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
485 d19d94db Guido Trotter
    constants.HV_SECURITY_MODEL:
486 d19d94db Guido Trotter
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_SM_TYPES),
487 d19d94db Guido Trotter
    constants.HV_SECURITY_DOMAIN: hv_base.NO_CHECK,
488 7ba594c0 Guido Trotter
    constants.HV_KVM_FLAG:
489 7ba594c0 Guido Trotter
      hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES),
490 fbe27e2b Guido Trotter
    constants.HV_VHOST_NET: hv_base.NO_CHECK,
491 547a63b7 Balazs Lecz
    constants.HV_KVM_USE_CHROOT: hv_base.NO_CHECK,
492 4f958b0b Miguel Di Ciurcio Filho
    constants.HV_MEM_PATH: hv_base.OPT_DIR_CHECK,
493 990ade2d Stephen Shirley
    constants.HV_REBOOT_BEHAVIOR:
494 a7f884d3 Tsachy Shacham
      hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
495 a7f884d3 Tsachy Shacham
    constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
496 205ab586 Iustin Pop
    }
497 6b5605e8 Iustin Pop
498 d0c8c01d Iustin Pop
  _MIGRATION_STATUS_RE = re.compile("Migration\s+status:\s+(\w+)",
499 30e42c4e Guido Trotter
                                    re.M | re.I)
500 65107a2f Michael Hanselmann
  _MIGRATION_PROGRESS_RE = \
501 527c0cf7 Michael Hanselmann
    re.compile(r"\s*transferred\s+ram:\s+(?P<transferred>\d+)\s+kbytes\s*\n"
502 527c0cf7 Michael Hanselmann
               r"\s*remaining\s+ram:\s+(?P<remaining>\d+)\s+kbytes\s*\n"
503 527c0cf7 Michael Hanselmann
               r"\s*total\s+ram:\s+(?P<total>\d+)\s+kbytes\s*\n", re.I)
504 61643226 Andrea Spadaccini
505 c4e388a5 Guido Trotter
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
506 c4e388a5 Guido Trotter
  _MIGRATION_INFO_RETRY_DELAY = 2
507 30e42c4e Guido Trotter
508 585c8187 Guido Trotter
  _VERSION_RE = re.compile(r"\b(\d+)\.(\d+)(\.(\d+))?\b")
509 b52d85c1 Guido Trotter
510 b693125f Tsachy Shacham
  _CPU_INFO_RE = re.compile(r"cpu\s+\#(\d+).*thread_id\s*=\s*(\d+)", re.I)
511 b693125f Tsachy Shacham
  _CPU_INFO_CMD = "info cpus"
512 b693125f Tsachy Shacham
  _CONT_CMD = "cont"
513 b693125f Tsachy Shacham
514 64bfbc08 Guido Trotter
  ANCILLARY_FILES = [
515 64bfbc08 Guido Trotter
    _KVM_NETWORK_SCRIPT,
516 64bfbc08 Guido Trotter
    ]
517 69ab2e12 Guido Trotter
  ANCILLARY_FILES_OPT = [
518 69ab2e12 Guido Trotter
    _KVM_NETWORK_SCRIPT,
519 69ab2e12 Guido Trotter
    ]
520 64bfbc08 Guido Trotter
521 eb58f9b1 Guido Trotter
  def __init__(self):
522 eb58f9b1 Guido Trotter
    hv_base.BaseHypervisor.__init__(self)
523 eb58f9b1 Guido Trotter
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
524 eb58f9b1 Guido Trotter
    # in a tmpfs filesystem or has been otherwise wiped out.
525 29921401 Iustin Pop
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
526 9afb67fe Guido Trotter
    utils.EnsureDirs(dirs)
527 eb58f9b1 Guido Trotter
528 30786fc9 Iustin Pop
  @classmethod
529 30786fc9 Iustin Pop
  def _InstancePidFile(cls, instance_name):
530 98ec75d6 Iustin Pop
    """Returns the instance pidfile.
531 98ec75d6 Iustin Pop

532 98ec75d6 Iustin Pop
    """
533 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
534 98ec75d6 Iustin Pop
535 263b8de6 Guido Trotter
  @classmethod
536 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
537 7548396c Guido Trotter
    """Returns the instance uidfile.
538 7548396c Guido Trotter

539 7548396c Guido Trotter
    """
540 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
541 7548396c Guido Trotter
542 7548396c Guido Trotter
  @classmethod
543 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
544 263b8de6 Guido Trotter
    """Check pid file for instance information.
545 263b8de6 Guido Trotter

546 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
547 263b8de6 Guido Trotter
    information from its command line.
548 263b8de6 Guido Trotter

549 263b8de6 Guido Trotter
    @type pid: string or int
550 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
551 263b8de6 Guido Trotter
    @rtype: tuple
552 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
553 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
554 263b8de6 Guido Trotter

555 263b8de6 Guido Trotter
    """
556 263b8de6 Guido Trotter
    alive = utils.IsProcessAlive(pid)
557 263b8de6 Guido Trotter
    if not alive:
558 263b8de6 Guido Trotter
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
559 263b8de6 Guido Trotter
560 263b8de6 Guido Trotter
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
561 263b8de6 Guido Trotter
    try:
562 263b8de6 Guido Trotter
      cmdline = utils.ReadFile(cmdline_file)
563 263b8de6 Guido Trotter
    except EnvironmentError, err:
564 263b8de6 Guido Trotter
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
565 263b8de6 Guido Trotter
                                   (pid, err))
566 263b8de6 Guido Trotter
567 263b8de6 Guido Trotter
    instance = None
568 263b8de6 Guido Trotter
    memory = 0
569 263b8de6 Guido Trotter
    vcpus = 0
570 263b8de6 Guido Trotter
571 d0c8c01d Iustin Pop
    arg_list = cmdline.split("\x00")
572 263b8de6 Guido Trotter
    while arg_list:
573 e687ec01 Michael Hanselmann
      arg = arg_list.pop(0)
574 263b8de6 Guido Trotter
      if arg == "-name":
575 263b8de6 Guido Trotter
        instance = arg_list.pop(0)
576 263b8de6 Guido Trotter
      elif arg == "-m":
577 263b8de6 Guido Trotter
        memory = int(arg_list.pop(0))
578 263b8de6 Guido Trotter
      elif arg == "-smp":
579 263b8de6 Guido Trotter
        vcpus = int(arg_list.pop(0))
580 263b8de6 Guido Trotter
581 263b8de6 Guido Trotter
    if instance is None:
582 263b8de6 Guido Trotter
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
583 263b8de6 Guido Trotter
                                   " instance" % pid)
584 263b8de6 Guido Trotter
585 263b8de6 Guido Trotter
    return (instance, memory, vcpus)
586 263b8de6 Guido Trotter
587 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
588 263b8de6 Guido Trotter
    """Returns the instance pidfile, pid, and liveness.
589 263b8de6 Guido Trotter

590 263b8de6 Guido Trotter
    @type instance_name: string
591 263b8de6 Guido Trotter
    @param instance_name: instance name
592 263b8de6 Guido Trotter
    @rtype: tuple
593 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
594 1f8b3a27 Guido Trotter

595 1f8b3a27 Guido Trotter
    """
596 98ec75d6 Iustin Pop
    pidfile = self._InstancePidFile(instance_name)
597 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
598 263b8de6 Guido Trotter
599 263b8de6 Guido Trotter
    alive = False
600 263b8de6 Guido Trotter
    try:
601 263b8de6 Guido Trotter
      cmd_instance = self._InstancePidInfo(pid)[0]
602 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
603 263b8de6 Guido Trotter
    except errors.HypervisorError:
604 263b8de6 Guido Trotter
      pass
605 1f8b3a27 Guido Trotter
606 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
607 1f8b3a27 Guido Trotter
608 5905901c Iustin Pop
  def _CheckDown(self, instance_name):
609 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
610 5905901c Iustin Pop

611 5905901c Iustin Pop
    """
612 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
613 5905901c Iustin Pop
    if alive:
614 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
615 5905901c Iustin Pop
                                   (instance_name, "already running"))
616 5905901c Iustin Pop
617 0df4d98a Guido Trotter
  @classmethod
618 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
619 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
620 c4fbefc8 Guido Trotter

621 c4fbefc8 Guido Trotter
    """
622 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
623 c4fbefc8 Guido Trotter
624 0df4d98a Guido Trotter
  @classmethod
625 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
626 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
627 c4fbefc8 Guido Trotter

628 c4fbefc8 Guido Trotter
    """
629 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
630 c4fbefc8 Guido Trotter
631 91c10532 Andrea Spadaccini
  @classmethod
632 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
633 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
634 91c10532 Andrea Spadaccini

635 91c10532 Andrea Spadaccini
    """
636 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
637 91c10532 Andrea Spadaccini
638 86d6bc2a Guido Trotter
  @staticmethod
639 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
640 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
641 86d6bc2a Guido Trotter

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

644 86d6bc2a Guido Trotter
    """
645 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
646 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
647 86d6bc2a Guido Trotter
    else:
648 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
649 86d6bc2a Guido Trotter
650 0df4d98a Guido Trotter
  @classmethod
651 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
652 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
653 38e250ba Guido Trotter

654 38e250ba Guido Trotter
    """
655 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
656 38e250ba Guido Trotter
657 7e66c35b Guido Trotter
  @classmethod
658 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
659 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
660 547a63b7 Balazs Lecz

661 547a63b7 Balazs Lecz
    """
662 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
663 547a63b7 Balazs Lecz
664 547a63b7 Balazs Lecz
  @classmethod
665 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
666 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
667 5d9bfd87 Apollon Oikonomopoulos
    given instance.
668 5d9bfd87 Apollon Oikonomopoulos

669 5d9bfd87 Apollon Oikonomopoulos
    """
670 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
671 5d9bfd87 Apollon Oikonomopoulos
672 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
673 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
674 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
675 5d9bfd87 Apollon Oikonomopoulos

676 5d9bfd87 Apollon Oikonomopoulos
    """
677 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
678 5d9bfd87 Apollon Oikonomopoulos
679 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
680 4f580fef Sรฉbastien Bocahu
  def _InstanceKeymapFile(cls, instance_name):
681 4f580fef Sรฉbastien Bocahu
    """Returns the name of the file containing the keymap for a given instance
682 4f580fef Sรฉbastien Bocahu

683 4f580fef Sรฉbastien Bocahu
    """
684 4f580fef Sรฉbastien Bocahu
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
685 4f580fef Sรฉbastien Bocahu
686 4f580fef Sรฉbastien Bocahu
  @classmethod
687 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
688 7548396c Guido Trotter
    """Try to read a uid file
689 7548396c Guido Trotter

690 7548396c Guido Trotter
    """
691 7548396c Guido Trotter
    if os.path.exists(uid_file):
692 7548396c Guido Trotter
      try:
693 682f7601 Guido Trotter
        uid = int(utils.ReadOneLineFile(uid_file))
694 aa0b600b Guido Trotter
        return uid
695 7548396c Guido Trotter
      except EnvironmentError:
696 7548396c Guido Trotter
        logging.warning("Can't read uid file", exc_info=True)
697 7548396c Guido Trotter
      except (TypeError, ValueError):
698 7548396c Guido Trotter
        logging.warning("Can't parse uid file contents", exc_info=True)
699 aa0b600b Guido Trotter
    return None
700 7548396c Guido Trotter
701 7548396c Guido Trotter
  @classmethod
702 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
703 547a63b7 Balazs Lecz
    """Removes an instance's rutime sockets/files/dirs.
704 7e66c35b Guido Trotter

705 7e66c35b Guido Trotter
    """
706 7e66c35b Guido Trotter
    utils.RemoveFile(pidfile)
707 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
708 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceSerial(instance_name))
709 91c10532 Andrea Spadaccini
    utils.RemoveFile(cls._InstanceQmpMonitor(instance_name))
710 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
711 4f580fef Sรฉbastien Bocahu
    utils.RemoveFile(cls._InstanceKeymapFile(instance_name))
712 7548396c Guido Trotter
    uid_file = cls._InstanceUidFile(instance_name)
713 7548396c Guido Trotter
    uid = cls._TryReadUidFile(uid_file)
714 7548396c Guido Trotter
    utils.RemoveFile(uid_file)
715 7548396c Guido Trotter
    if uid is not None:
716 7548396c Guido Trotter
      uidpool.ReleaseUid(uid)
717 7be85163 Guido Trotter
    try:
718 7be85163 Guido Trotter
      shutil.rmtree(cls._InstanceNICDir(instance_name))
719 7be85163 Guido Trotter
    except OSError, err:
720 7be85163 Guido Trotter
      if err.errno != errno.ENOENT:
721 7be85163 Guido Trotter
        raise
722 547a63b7 Balazs Lecz
    try:
723 547a63b7 Balazs Lecz
      chroot_dir = cls._InstanceChrootDir(instance_name)
724 547a63b7 Balazs Lecz
      utils.RemoveDir(chroot_dir)
725 547a63b7 Balazs Lecz
    except OSError, err:
726 547a63b7 Balazs Lecz
      if err.errno == errno.ENOTEMPTY:
727 547a63b7 Balazs Lecz
        # The chroot directory is expected to be empty, but it isn't.
728 547a63b7 Balazs Lecz
        new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
729 547a63b7 Balazs Lecz
                                          prefix="%s-%s-" %
730 547a63b7 Balazs Lecz
                                          (instance_name,
731 547a63b7 Balazs Lecz
                                           utils.TimestampForFilename()))
732 547a63b7 Balazs Lecz
        logging.warning("The chroot directory of instance %s can not be"
733 547a63b7 Balazs Lecz
                        " removed as it is not empty. Moving it to the"
734 547a63b7 Balazs Lecz
                        " quarantine instead. Please investigate the"
735 547a63b7 Balazs Lecz
                        " contents (%s) and clean up manually",
736 547a63b7 Balazs Lecz
                        instance_name, new_chroot_dir)
737 547a63b7 Balazs Lecz
        utils.RenameFile(chroot_dir, new_chroot_dir)
738 547a63b7 Balazs Lecz
      else:
739 547a63b7 Balazs Lecz
        raise
740 7e66c35b Guido Trotter
741 748e4b5a Michael Hanselmann
  @staticmethod
742 5d9bfd87 Apollon Oikonomopoulos
  def _ConfigureNIC(instance, seq, nic, tap):
743 5d9bfd87 Apollon Oikonomopoulos
    """Run the network configuration script for a specified NIC
744 eb58f9b1 Guido Trotter

745 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
746 eb58f9b1 Guido Trotter
    @type instance: instance object
747 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
748 eb58f9b1 Guido Trotter
    @type seq: int
749 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
750 eb58f9b1 Guido Trotter
    @type nic: nic object
751 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
752 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
753 eb58f9b1 Guido Trotter

754 eb58f9b1 Guido Trotter
    """
755 5d9bfd87 Apollon Oikonomopoulos
    if instance.tags:
756 5d9bfd87 Apollon Oikonomopoulos
      tags = " ".join(instance.tags)
757 5d9bfd87 Apollon Oikonomopoulos
    else:
758 5d9bfd87 Apollon Oikonomopoulos
      tags = ""
759 5d9bfd87 Apollon Oikonomopoulos
760 5d9bfd87 Apollon Oikonomopoulos
    env = {
761 5d9bfd87 Apollon Oikonomopoulos
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
762 5d9bfd87 Apollon Oikonomopoulos
      "INSTANCE": instance.name,
763 5d9bfd87 Apollon Oikonomopoulos
      "MAC": nic.mac,
764 5d9bfd87 Apollon Oikonomopoulos
      "MODE": nic.nicparams[constants.NIC_MODE],
765 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE": tap,
766 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE_INDEX": str(seq),
767 5d9bfd87 Apollon Oikonomopoulos
      "TAGS": tags,
768 5d9bfd87 Apollon Oikonomopoulos
    }
769 5d9bfd87 Apollon Oikonomopoulos
770 5d9bfd87 Apollon Oikonomopoulos
    if nic.ip:
771 5d9bfd87 Apollon Oikonomopoulos
      env["IP"] = nic.ip
772 5d9bfd87 Apollon Oikonomopoulos
773 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_LINK]:
774 5d9bfd87 Apollon Oikonomopoulos
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
775 5d9bfd87 Apollon Oikonomopoulos
776 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
777 5d9bfd87 Apollon Oikonomopoulos
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
778 5d9bfd87 Apollon Oikonomopoulos
779 5d9bfd87 Apollon Oikonomopoulos
    result = utils.RunCmd([constants.KVM_IFUP, tap], env=env)
780 5d9bfd87 Apollon Oikonomopoulos
    if result.failed:
781 5d9bfd87 Apollon Oikonomopoulos
      raise errors.HypervisorError("Failed to configure interface %s: %s."
782 5d9bfd87 Apollon Oikonomopoulos
                                   " Network configuration script output: %s" %
783 5d9bfd87 Apollon Oikonomopoulos
                                   (tap, result.fail_reason, result.output))
784 eb58f9b1 Guido Trotter
785 b693125f Tsachy Shacham
  @staticmethod
786 b693125f Tsachy Shacham
  def _VerifyAffinityPackage():
787 b693125f Tsachy Shacham
    if affinity is None:
788 b693125f Tsachy Shacham
      raise errors.HypervisorError("affinity Python package not"
789 b693125f Tsachy Shacham
        " found; cannot use CPU pinning under KVM")
790 b693125f Tsachy Shacham
791 b693125f Tsachy Shacham
  @staticmethod
792 b693125f Tsachy Shacham
  def _BuildAffinityCpuMask(cpu_list):
793 b693125f Tsachy Shacham
    """Create a CPU mask suitable for sched_setaffinity from a list of
794 b693125f Tsachy Shacham
    CPUs.
795 b693125f Tsachy Shacham

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

799 b693125f Tsachy Shacham
    @type cpu_list: list of int
800 b693125f Tsachy Shacham
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
801 b693125f Tsachy Shacham
    @rtype: int
802 b693125f Tsachy Shacham
    @return: a bit mask of CPU affinities
803 b693125f Tsachy Shacham

804 b693125f Tsachy Shacham
    """
805 b693125f Tsachy Shacham
    if cpu_list == constants.CPU_PINNING_OFF:
806 b693125f Tsachy Shacham
      return constants.CPU_PINNING_ALL_KVM
807 b693125f Tsachy Shacham
    else:
808 b693125f Tsachy Shacham
      return sum(2 ** cpu for cpu in cpu_list)
809 b693125f Tsachy Shacham
810 b693125f Tsachy Shacham
  @classmethod
811 b693125f Tsachy Shacham
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
812 b693125f Tsachy Shacham
    """Change CPU affinity for running VM according to given CPU mask.
813 b693125f Tsachy Shacham

814 b693125f Tsachy Shacham
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
815 b693125f Tsachy Shacham
    @type cpu_mask: string
816 b693125f Tsachy Shacham
    @param process_id: process ID of KVM process. Used to pin entire VM
817 b693125f Tsachy Shacham
                       to physical CPUs.
818 b693125f Tsachy Shacham
    @type process_id: int
819 b693125f Tsachy Shacham
    @param thread_dict: map of virtual CPUs to KVM thread IDs
820 b693125f Tsachy Shacham
    @type thread_dict: dict int:int
821 b693125f Tsachy Shacham

822 b693125f Tsachy Shacham
    """
823 b693125f Tsachy Shacham
    # Convert the string CPU mask to a list of list of int's
824 b693125f Tsachy Shacham
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
825 b693125f Tsachy Shacham
826 b693125f Tsachy Shacham
    if len(cpu_list) == 1:
827 b693125f Tsachy Shacham
      all_cpu_mapping = cpu_list[0]
828 b693125f Tsachy Shacham
      if all_cpu_mapping == constants.CPU_PINNING_OFF:
829 b693125f Tsachy Shacham
        # If CPU pinning has 1 entry that's "all", then do nothing
830 b693125f Tsachy Shacham
        pass
831 b693125f Tsachy Shacham
      else:
832 b693125f Tsachy Shacham
        # If CPU pinning has one non-all entry, map the entire VM to
833 b693125f Tsachy Shacham
        # one set of physical CPUs
834 b693125f Tsachy Shacham
        cls._VerifyAffinityPackage()
835 b693125f Tsachy Shacham
        affinity.set_process_affinity_mask(process_id,
836 b693125f Tsachy Shacham
          cls._BuildAffinityCpuMask(all_cpu_mapping))
837 b693125f Tsachy Shacham
    else:
838 b693125f Tsachy Shacham
      # The number of vCPUs mapped should match the number of vCPUs
839 b693125f Tsachy Shacham
      # reported by KVM. This was already verified earlier, so
840 b693125f Tsachy Shacham
      # here only as a sanity check.
841 b693125f Tsachy Shacham
      assert len(thread_dict) == len(cpu_list)
842 b693125f Tsachy Shacham
      cls._VerifyAffinityPackage()
843 b693125f Tsachy Shacham
844 b693125f Tsachy Shacham
      # For each vCPU, map it to the proper list of physical CPUs
845 b693125f Tsachy Shacham
      for vcpu, i in zip(cpu_list, range(len(cpu_list))):
846 b693125f Tsachy Shacham
        affinity.set_process_affinity_mask(thread_dict[i],
847 b693125f Tsachy Shacham
          cls._BuildAffinityCpuMask(vcpu))
848 b693125f Tsachy Shacham
849 b693125f Tsachy Shacham
  def _GetVcpuThreadIds(self, instance_name):
850 b693125f Tsachy Shacham
    """Get a mapping of vCPU no. to thread IDs for the instance
851 b693125f Tsachy Shacham

852 b693125f Tsachy Shacham
    @type instance_name: string
853 b693125f Tsachy Shacham
    @param instance_name: instance in question
854 b693125f Tsachy Shacham
    @rtype: dictionary of int:int
855 b693125f Tsachy Shacham
    @return: a dictionary mapping vCPU numbers to thread IDs
856 b693125f Tsachy Shacham

857 b693125f Tsachy Shacham
    """
858 b693125f Tsachy Shacham
    result = {}
859 b693125f Tsachy Shacham
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
860 b693125f Tsachy Shacham
    for line in output.stdout.splitlines():
861 b693125f Tsachy Shacham
      match = self._CPU_INFO_RE.search(line)
862 b693125f Tsachy Shacham
      if not match:
863 b693125f Tsachy Shacham
        continue
864 b693125f Tsachy Shacham
      grp = map(int, match.groups())
865 b693125f Tsachy Shacham
      result[grp[0]] = grp[1]
866 b693125f Tsachy Shacham
867 b693125f Tsachy Shacham
    return result
868 b693125f Tsachy Shacham
869 1d8a7812 Andrea Spadaccini
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
870 1d8a7812 Andrea Spadaccini
    """Complete CPU pinning.
871 b693125f Tsachy Shacham

872 b693125f Tsachy Shacham
    @type instance_name: string
873 b693125f Tsachy Shacham
    @param instance_name: name of instance
874 b693125f Tsachy Shacham
    @type cpu_mask: string
875 b693125f Tsachy Shacham
    @param cpu_mask: CPU pinning mask as entered by user
876 b693125f Tsachy Shacham

877 b693125f Tsachy Shacham
    """
878 1d8a7812 Andrea Spadaccini
    # Get KVM process ID, to be used if need to pin entire VM
879 1d8a7812 Andrea Spadaccini
    _, pid, _ = self._InstancePidAlive(instance_name)
880 1d8a7812 Andrea Spadaccini
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
881 1d8a7812 Andrea Spadaccini
    thread_dict = self._GetVcpuThreadIds(instance_name)
882 1d8a7812 Andrea Spadaccini
    # Run CPU pinning, based on configured mask
883 1d8a7812 Andrea Spadaccini
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
884 b693125f Tsachy Shacham
885 eb58f9b1 Guido Trotter
  def ListInstances(self):
886 eb58f9b1 Guido Trotter
    """Get the list of running instances.
887 eb58f9b1 Guido Trotter

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

891 eb58f9b1 Guido Trotter
    """
892 eb58f9b1 Guido Trotter
    result = []
893 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
894 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
895 eb58f9b1 Guido Trotter
        result.append(name)
896 eb58f9b1 Guido Trotter
    return result
897 eb58f9b1 Guido Trotter
898 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
899 eb58f9b1 Guido Trotter
    """Get instance properties.
900 eb58f9b1 Guido Trotter

901 4fbb3c60 Guido Trotter
    @type instance_name: string
902 c41eea6e Iustin Pop
    @param instance_name: the instance name
903 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
904 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
905 eb58f9b1 Guido Trotter

906 eb58f9b1 Guido Trotter
    """
907 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
908 1f8b3a27 Guido Trotter
    if not alive:
909 eb58f9b1 Guido Trotter
      return None
910 eb58f9b1 Guido Trotter
911 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
912 fc84cd5d Guido Trotter
    istat = "---b-"
913 eb58f9b1 Guido Trotter
    times = "0"
914 eb58f9b1 Guido Trotter
915 89da2ff3 Guido Trotter
    try:
916 89da2ff3 Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
917 89da2ff3 Guido Trotter
      qmp.connect()
918 89da2ff3 Guido Trotter
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
919 89da2ff3 Guido Trotter
      # Will fail if ballooning is not enabled, but we can then just resort to
920 89da2ff3 Guido Trotter
      # the value above.
921 89da2ff3 Guido Trotter
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
922 89da2ff3 Guido Trotter
      memory = mem_bytes / 1048576
923 89da2ff3 Guido Trotter
    except errors.HypervisorError:
924 89da2ff3 Guido Trotter
      pass
925 89da2ff3 Guido Trotter
926 fc84cd5d Guido Trotter
    return (instance_name, pid, memory, vcpus, istat, times)
927 eb58f9b1 Guido Trotter
928 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
929 eb58f9b1 Guido Trotter
    """Get properties of all instances.
930 eb58f9b1 Guido Trotter

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

933 eb58f9b1 Guido Trotter
    """
934 eb58f9b1 Guido Trotter
    data = []
935 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
936 263b8de6 Guido Trotter
      try:
937 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
938 263b8de6 Guido Trotter
      except errors.HypervisorError:
939 263b8de6 Guido Trotter
        continue
940 263b8de6 Guido Trotter
      if info:
941 263b8de6 Guido Trotter
        data.append(info)
942 eb58f9b1 Guido Trotter
    return data
943 eb58f9b1 Guido Trotter
944 323f9095 Stephen Shirley
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused):
945 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
946 eb58f9b1 Guido Trotter

947 eb58f9b1 Guido Trotter
    """
948 b6267745 Andrea Spadaccini
    # pylint: disable=R0914,R0915
949 440351f8 Andrea Spadaccini
    _, v_major, v_min, _ = self._GetKVMVersion()
950 4304964a Guido Trotter
951 e687ec01 Michael Hanselmann
    pidfile = self._InstancePidFile(instance.name)
952 eb58f9b1 Guido Trotter
    kvm = constants.KVM_PATH
953 eb58f9b1 Guido Trotter
    kvm_cmd = [kvm]
954 c6a39fc2 Guido Trotter
    # used just by the vnc server, if enabled
955 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-name", instance.name])
956 f5a4b9ce Guido Trotter
    kvm_cmd.extend(["-m", instance.beparams[constants.BE_MAXMEM]])
957 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-smp", instance.beparams[constants.BE_VCPUS]])
958 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-pidfile", pidfile])
959 fcf5b670 Guido Trotter
    kvm_cmd.extend(["-balloon", "virtio"])
960 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-daemonize"])
961 6b5605e8 Iustin Pop
    if not instance.hvparams[constants.HV_ACPI]:
962 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-no-acpi"])
963 990ade2d Stephen Shirley
    if instance.hvparams[constants.HV_REBOOT_BEHAVIOR] == \
964 990ade2d Stephen Shirley
        constants.INSTANCE_REBOOT_EXIT:
965 990ade2d Stephen Shirley
      kvm_cmd.extend(["-no-reboot"])
966 eb58f9b1 Guido Trotter
967 a985b417 Iustin Pop
    hvp = instance.hvparams
968 835528af Iustin Pop
    boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
969 835528af Iustin Pop
    boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
970 cc130cc7 Marco Casavecchia
    boot_floppy = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_FLOPPY
971 835528af Iustin Pop
    boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
972 8745c3d7 Guido Trotter
973 b1cb62bd Andrea Spadaccini
    self.ValidateParameters(hvp)
974 b1cb62bd Andrea Spadaccini
975 b693125f Tsachy Shacham
    if startup_paused:
976 b693125f Tsachy Shacham
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
977 b693125f Tsachy Shacham
978 7ba594c0 Guido Trotter
    if hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED:
979 7ba594c0 Guido Trotter
      kvm_cmd.extend(["-enable-kvm"])
980 7ba594c0 Guido Trotter
    elif hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED:
981 7ba594c0 Guido Trotter
      kvm_cmd.extend(["-disable-kvm"])
982 7ba594c0 Guido Trotter
983 8745c3d7 Guido Trotter
    if boot_network:
984 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-boot", "n"])
985 1213604d Guido Trotter
986 a985b417 Iustin Pop
    disk_type = hvp[constants.HV_DISK_TYPE]
987 1213604d Guido Trotter
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
988 d0c8c01d Iustin Pop
      if_val = ",if=virtio"
989 1213604d Guido Trotter
    else:
990 d0c8c01d Iustin Pop
      if_val = ",if=%s" % disk_type
991 19572932 Iustin Pop
    # Cache mode
992 19572932 Iustin Pop
    disk_cache = hvp[constants.HV_DISK_CACHE]
993 41e794f6 Apollon Oikonomopoulos
    if instance.disk_template in constants.DTS_EXT_MIRROR:
994 41e794f6 Apollon Oikonomopoulos
      if disk_cache != "none":
995 41e794f6 Apollon Oikonomopoulos
        # TODO: make this a hard error, instead of a silent overwrite
996 41e794f6 Apollon Oikonomopoulos
        logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
997 41e794f6 Apollon Oikonomopoulos
                        " to prevent shared storage corruption on migration",
998 41e794f6 Apollon Oikonomopoulos
                        disk_cache)
999 41e794f6 Apollon Oikonomopoulos
      cache_val = ",cache=none"
1000 41e794f6 Apollon Oikonomopoulos
    elif disk_cache != constants.HT_CACHE_DEFAULT:
1001 19572932 Iustin Pop
      cache_val = ",cache=%s" % disk_cache
1002 19572932 Iustin Pop
    else:
1003 19572932 Iustin Pop
      cache_val = ""
1004 069cfbf1 Iustin Pop
    for cfdev, dev_path in block_devices:
1005 d34b16d7 Iustin Pop
      if cfdev.mode != constants.DISK_RDWR:
1006 d34b16d7 Iustin Pop
        raise errors.HypervisorError("Instance has read-only disks which"
1007 d34b16d7 Iustin Pop
                                     " are not supported by KVM")
1008 eb58f9b1 Guido Trotter
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
1009 4304964a Guido Trotter
      boot_val = ""
1010 66d5dbef Guido Trotter
      if boot_disk:
1011 d0c8c01d Iustin Pop
        kvm_cmd.extend(["-boot", "c"])
1012 66d5dbef Guido Trotter
        boot_disk = False
1013 4304964a Guido Trotter
        if (v_major, v_min) < (0, 14) and disk_type != constants.HT_DISK_IDE:
1014 4304964a Guido Trotter
          boot_val = ",boot=on"
1015 eb58f9b1 Guido Trotter
1016 d0c8c01d Iustin Pop
      drive_val = "file=%s,format=raw%s%s%s" % (dev_path, if_val, boot_val,
1017 19572932 Iustin Pop
                                                cache_val)
1018 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1019 eb58f9b1 Guido Trotter
1020 cc130cc7 Marco Casavecchia
    #Now we can specify a different device type for CDROM devices.
1021 cc130cc7 Marco Casavecchia
    cdrom_disk_type = hvp[constants.HV_KVM_CDROM_DISK_TYPE]
1022 cc130cc7 Marco Casavecchia
    if not cdrom_disk_type:
1023 cc130cc7 Marco Casavecchia
      cdrom_disk_type = disk_type
1024 cc130cc7 Marco Casavecchia
1025 a985b417 Iustin Pop
    iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
1026 66d5dbef Guido Trotter
    if iso_image:
1027 d0c8c01d Iustin Pop
      options = ",format=raw,media=cdrom"
1028 66d5dbef Guido Trotter
      if boot_cdrom:
1029 d0c8c01d Iustin Pop
        kvm_cmd.extend(["-boot", "d"])
1030 cc130cc7 Marco Casavecchia
        if cdrom_disk_type != constants.HT_DISK_IDE:
1031 d0c8c01d Iustin Pop
          options = "%s,boot=on,if=%s" % (options, constants.HT_DISK_IDE)
1032 cc130cc7 Marco Casavecchia
        else:
1033 d0c8c01d Iustin Pop
          options = "%s,boot=on" % options
1034 9dd363eb Guido Trotter
      else:
1035 cc130cc7 Marco Casavecchia
        if cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1036 d0c8c01d Iustin Pop
          if_val = ",if=virtio"
1037 9cf4321f Apollon Oikonomopoulos
        else:
1038 d0c8c01d Iustin Pop
          if_val = ",if=%s" % cdrom_disk_type
1039 d0c8c01d Iustin Pop
        options = "%s%s" % (options, if_val)
1040 d0c8c01d Iustin Pop
      drive_val = "file=%s%s" % (iso_image, options)
1041 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1042 66d5dbef Guido Trotter
1043 cc130cc7 Marco Casavecchia
    iso_image2 = hvp[constants.HV_KVM_CDROM2_IMAGE_PATH]
1044 cc130cc7 Marco Casavecchia
    if iso_image2:
1045 d0c8c01d Iustin Pop
      options = ",format=raw,media=cdrom"
1046 cc130cc7 Marco Casavecchia
      if cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1047 d0c8c01d Iustin Pop
        if_val = ",if=virtio"
1048 cc130cc7 Marco Casavecchia
      else:
1049 d0c8c01d Iustin Pop
        if_val = ",if=%s" % cdrom_disk_type
1050 d0c8c01d Iustin Pop
      options = "%s%s" % (options, if_val)
1051 d0c8c01d Iustin Pop
      drive_val = "file=%s%s" % (iso_image2, options)
1052 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1053 cc130cc7 Marco Casavecchia
1054 cc130cc7 Marco Casavecchia
    floppy_image = hvp[constants.HV_KVM_FLOPPY_IMAGE_PATH]
1055 cc130cc7 Marco Casavecchia
    if floppy_image:
1056 d0c8c01d Iustin Pop
      options = ",format=raw,media=disk"
1057 cc130cc7 Marco Casavecchia
      if boot_floppy:
1058 d0c8c01d Iustin Pop
        kvm_cmd.extend(["-boot", "a"])
1059 d0c8c01d Iustin Pop
        options = "%s,boot=on" % options
1060 d0c8c01d Iustin Pop
      if_val = ",if=floppy"
1061 d0c8c01d Iustin Pop
      options = "%s%s" % (options, if_val)
1062 d0c8c01d Iustin Pop
      drive_val = "file=%s%s" % (floppy_image, options)
1063 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1064 cc130cc7 Marco Casavecchia
1065 a985b417 Iustin Pop
    kernel_path = hvp[constants.HV_KERNEL_PATH]
1066 df5ab9f0 Guido Trotter
    if kernel_path:
1067 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-kernel", kernel_path])
1068 a985b417 Iustin Pop
      initrd_path = hvp[constants.HV_INITRD_PATH]
1069 df5ab9f0 Guido Trotter
      if initrd_path:
1070 d0c8c01d Iustin Pop
        kvm_cmd.extend(["-initrd", initrd_path])
1071 d0c8c01d Iustin Pop
      root_append = ["root=%s" % hvp[constants.HV_ROOT_PATH],
1072 07813a9e Iustin Pop
                     hvp[constants.HV_KERNEL_ARGS]]
1073 07813a9e Iustin Pop
      if hvp[constants.HV_SERIAL_CONSOLE]:
1074 d0c8c01d Iustin Pop
        root_append.append("console=ttyS0,38400")
1075 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-append", " ".join(root_append)])
1076 eb58f9b1 Guido Trotter
1077 4f958b0b Miguel Di Ciurcio Filho
    mem_path = hvp[constants.HV_MEM_PATH]
1078 4f958b0b Miguel Di Ciurcio Filho
    if mem_path:
1079 9d3015f9 Guido Trotter
      kvm_cmd.extend(["-mem-path", mem_path, "-mem-prealloc"])
1080 4f958b0b Miguel Di Ciurcio Filho
1081 a985b417 Iustin Pop
    mouse_type = hvp[constants.HV_USB_MOUSE]
1082 31f6f67a Guido Trotter
    vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
1083 31f6f67a Guido Trotter
1084 11344a50 Guido Trotter
    if mouse_type:
1085 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-usb"])
1086 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-usbdevice", mouse_type])
1087 31f6f67a Guido Trotter
    elif vnc_bind_address:
1088 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-usbdevice", constants.HT_MOUSE_TABLET])
1089 11344a50 Guido Trotter
1090 4f580fef Sรฉbastien Bocahu
    keymap = hvp[constants.HV_KEYMAP]
1091 4f580fef Sรฉbastien Bocahu
    if keymap:
1092 4f580fef Sรฉbastien Bocahu
      keymap_path = self._InstanceKeymapFile(instance.name)
1093 4f580fef Sรฉbastien Bocahu
      # If a keymap file is specified, KVM won't use its internal defaults. By
1094 4f580fef Sรฉbastien Bocahu
      # first including the "en-us" layout, an error on loading the actual
1095 4f580fef Sรฉbastien Bocahu
      # layout (e.g. because it can't be found) won't lead to a non-functional
1096 4f580fef Sรฉbastien Bocahu
      # keyboard. A keyboard with incorrect keys is still better than none.
1097 4f580fef Sรฉbastien Bocahu
      utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
1098 4f580fef Sรฉbastien Bocahu
      kvm_cmd.extend(["-k", keymap_path])
1099 4f580fef Sรฉbastien Bocahu
1100 8470c8db Guido Trotter
    if vnc_bind_address:
1101 8b312c1d Manuel Franceschini
      if netutils.IP4Address.IsValid(vnc_bind_address):
1102 377d74c9 Guido Trotter
        if instance.network_port > constants.VNC_BASE_PORT:
1103 377d74c9 Guido Trotter
          display = instance.network_port - constants.VNC_BASE_PORT
1104 14f5f1b6 Manuel Franceschini
          if vnc_bind_address == constants.IP4_ADDRESS_ANY:
1105 d0c8c01d Iustin Pop
            vnc_arg = ":%d" % (display)
1106 8447f52b Guido Trotter
          else:
1107 d0c8c01d Iustin Pop
            vnc_arg = "%s:%d" % (vnc_bind_address, display)
1108 8470c8db Guido Trotter
        else:
1109 8447f52b Guido Trotter
          logging.error("Network port is not a valid VNC display (%d < %d)."
1110 07b8a2b5 Iustin Pop
                        " Not starting VNC", instance.network_port,
1111 07b8a2b5 Iustin Pop
                        constants.VNC_BASE_PORT)
1112 d0c8c01d Iustin Pop
          vnc_arg = "none"
1113 8b2d1013 Guido Trotter
1114 8b2d1013 Guido Trotter
        # Only allow tls and other option when not binding to a file, for now.
1115 8b2d1013 Guido Trotter
        # kvm/qemu gets confused otherwise about the filename to use.
1116 d0c8c01d Iustin Pop
        vnc_append = ""
1117 a985b417 Iustin Pop
        if hvp[constants.HV_VNC_TLS]:
1118 d0c8c01d Iustin Pop
          vnc_append = "%s,tls" % vnc_append
1119 a985b417 Iustin Pop
          if hvp[constants.HV_VNC_X509_VERIFY]:
1120 d0c8c01d Iustin Pop
            vnc_append = "%s,x509verify=%s" % (vnc_append,
1121 a985b417 Iustin Pop
                                               hvp[constants.HV_VNC_X509])
1122 a985b417 Iustin Pop
          elif hvp[constants.HV_VNC_X509]:
1123 d0c8c01d Iustin Pop
            vnc_append = "%s,x509=%s" % (vnc_append,
1124 a985b417 Iustin Pop
                                         hvp[constants.HV_VNC_X509])
1125 6e6bb8d5 Guido Trotter
        if hvp[constants.HV_VNC_PASSWORD_FILE]:
1126 d0c8c01d Iustin Pop
          vnc_append = "%s,password" % vnc_append
1127 6e6bb8d5 Guido Trotter
1128 d0c8c01d Iustin Pop
        vnc_arg = "%s%s" % (vnc_arg, vnc_append)
1129 8b2d1013 Guido Trotter
1130 8470c8db Guido Trotter
      else:
1131 d0c8c01d Iustin Pop
        vnc_arg = "unix:%s/%s.vnc" % (vnc_bind_address, instance.name)
1132 8b2d1013 Guido Trotter
1133 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-vnc", vnc_arg])
1134 8470c8db Guido Trotter
    else:
1135 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-nographic"])
1136 8470c8db Guido Trotter
1137 69b99987 Michael Hanselmann
    monitor_dev = ("unix:%s,server,nowait" %
1138 69b99987 Michael Hanselmann
                   self._InstanceMonitor(instance.name))
1139 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-monitor", monitor_dev])
1140 a985b417 Iustin Pop
    if hvp[constants.HV_SERIAL_CONSOLE]:
1141 d0c8c01d Iustin Pop
      serial_dev = ("unix:%s,server,nowait" %
1142 a985b417 Iustin Pop
                    self._InstanceSerial(instance.name))
1143 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-serial", serial_dev])
1144 a2faf9ee Guido Trotter
    else:
1145 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-serial", "none"])
1146 eb58f9b1 Guido Trotter
1147 b1cb62bd Andrea Spadaccini
    spice_bind = hvp[constants.HV_KVM_SPICE_BIND]
1148 11ae7a0a Andrea Spadaccini
    spice_ip_version = None
1149 b1cb62bd Andrea Spadaccini
    if spice_bind:
1150 b1cb62bd Andrea Spadaccini
      if netutils.IsValidInterface(spice_bind):
1151 b1cb62bd Andrea Spadaccini
        # The user specified a network interface, we have to figure out the IP
1152 b1cb62bd Andrea Spadaccini
        # address.
1153 b1cb62bd Andrea Spadaccini
        addresses = netutils.GetInterfaceIpAddresses(spice_bind)
1154 b1cb62bd Andrea Spadaccini
        spice_ip_version = hvp[constants.HV_KVM_SPICE_IP_VERSION]
1155 b1cb62bd Andrea Spadaccini
1156 b1cb62bd Andrea Spadaccini
        # if the user specified an IP version and the interface does not
1157 b1cb62bd Andrea Spadaccini
        # have that kind of IP addresses, throw an exception
1158 b1cb62bd Andrea Spadaccini
        if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1159 b1cb62bd Andrea Spadaccini
          if not addresses[spice_ip_version]:
1160 b1cb62bd Andrea Spadaccini
            raise errors.HypervisorError("spice: unable to get an IPv%s address"
1161 b1cb62bd Andrea Spadaccini
                                         " for %s" % (spice_ip_version,
1162 b1cb62bd Andrea Spadaccini
                                                      spice_bind))
1163 b1cb62bd Andrea Spadaccini
1164 b1cb62bd Andrea Spadaccini
        # the user did not specify an IP version, we have to figure it out
1165 b1cb62bd Andrea Spadaccini
        elif (addresses[constants.IP4_VERSION] and
1166 b1cb62bd Andrea Spadaccini
              addresses[constants.IP6_VERSION]):
1167 b1cb62bd Andrea Spadaccini
          # we have both ipv4 and ipv6, let's use the cluster default IP
1168 b1cb62bd Andrea Spadaccini
          # version
1169 b1cb62bd Andrea Spadaccini
          cluster_family = ssconf.SimpleStore().GetPrimaryIPFamily()
1170 65107a2f Michael Hanselmann
          spice_ip_version = \
1171 65107a2f Michael Hanselmann
            netutils.IPAddress.GetVersionFromAddressFamily(cluster_family)
1172 b1cb62bd Andrea Spadaccini
        elif addresses[constants.IP4_VERSION]:
1173 b1cb62bd Andrea Spadaccini
          spice_ip_version = constants.IP4_VERSION
1174 b845c8a1 Andrea Spadaccini
        elif addresses[constants.IP6_VERSION]:
1175 b1cb62bd Andrea Spadaccini
          spice_ip_version = constants.IP6_VERSION
1176 b845c8a1 Andrea Spadaccini
        else:
1177 b845c8a1 Andrea Spadaccini
          raise errors.HypervisorError("spice: unable to get an IP address"
1178 b845c8a1 Andrea Spadaccini
                                       " for %s" % (spice_bind))
1179 b1cb62bd Andrea Spadaccini
1180 b1cb62bd Andrea Spadaccini
        spice_address = addresses[spice_ip_version][0]
1181 b1cb62bd Andrea Spadaccini
1182 b1cb62bd Andrea Spadaccini
      else:
1183 b1cb62bd Andrea Spadaccini
        # spice_bind is known to be a valid IP address, because
1184 b1cb62bd Andrea Spadaccini
        # ValidateParameters checked it.
1185 b1cb62bd Andrea Spadaccini
        spice_address = spice_bind
1186 b1cb62bd Andrea Spadaccini
1187 bfe86c76 Andrea Spadaccini
      spice_arg = "addr=%s" % spice_address
1188 bfe86c76 Andrea Spadaccini
      if hvp[constants.HV_KVM_SPICE_USE_TLS]:
1189 bfe86c76 Andrea Spadaccini
        spice_arg = "%s,tls-port=%s,x509-cacert-file=%s" % (spice_arg,
1190 bfe86c76 Andrea Spadaccini
            instance.network_port, constants.SPICE_CACERT_FILE)
1191 bfe86c76 Andrea Spadaccini
        spice_arg = "%s,x509-key-file=%s,x509-cert-file=%s" % (spice_arg,
1192 bfe86c76 Andrea Spadaccini
            constants.SPICE_CERT_FILE, constants.SPICE_CERT_FILE)
1193 3e40b587 Andrea Spadaccini
        tls_ciphers = hvp[constants.HV_KVM_SPICE_TLS_CIPHERS]
1194 3e40b587 Andrea Spadaccini
        if tls_ciphers:
1195 3e40b587 Andrea Spadaccini
          spice_arg = "%s,tls-ciphers=%s" % (spice_arg, tls_ciphers)
1196 bfe86c76 Andrea Spadaccini
      else:
1197 bfe86c76 Andrea Spadaccini
        spice_arg = "%s,port=%s" % (spice_arg, instance.network_port)
1198 bfe86c76 Andrea Spadaccini
1199 b451c4c7 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]:
1200 b451c4c7 Andrea Spadaccini
        spice_arg = "%s,disable-ticketing" % spice_arg
1201 b451c4c7 Andrea Spadaccini
1202 11ae7a0a Andrea Spadaccini
      if spice_ip_version:
1203 11ae7a0a Andrea Spadaccini
        spice_arg = "%s,ipv%s" % (spice_arg, spice_ip_version)
1204 b1cb62bd Andrea Spadaccini
1205 ea064d24 Andrea Spadaccini
      # Image compression options
1206 ea064d24 Andrea Spadaccini
      img_lossless = hvp[constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR]
1207 ea064d24 Andrea Spadaccini
      img_jpeg = hvp[constants.HV_KVM_SPICE_JPEG_IMG_COMPR]
1208 ea064d24 Andrea Spadaccini
      img_zlib_glz = hvp[constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR]
1209 ea064d24 Andrea Spadaccini
      if img_lossless:
1210 ea064d24 Andrea Spadaccini
        spice_arg = "%s,image-compression=%s" % (spice_arg, img_lossless)
1211 ea064d24 Andrea Spadaccini
      if img_jpeg:
1212 ea064d24 Andrea Spadaccini
        spice_arg = "%s,jpeg-wan-compression=%s" % (spice_arg, img_jpeg)
1213 ea064d24 Andrea Spadaccini
      if img_zlib_glz:
1214 ea064d24 Andrea Spadaccini
        spice_arg = "%s,zlib-glz-wan-compression=%s" % (spice_arg, img_zlib_glz)
1215 ea064d24 Andrea Spadaccini
1216 ea064d24 Andrea Spadaccini
      # Video stream detection
1217 ea064d24 Andrea Spadaccini
      video_streaming = hvp[constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION]
1218 ea064d24 Andrea Spadaccini
      if video_streaming:
1219 ea064d24 Andrea Spadaccini
        spice_arg = "%s,streaming-video=%s" % (spice_arg, video_streaming)
1220 ea064d24 Andrea Spadaccini
1221 ea064d24 Andrea Spadaccini
      # Audio compression, by default in qemu-kvm it is on
1222 ea064d24 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_AUDIO_COMPR]:
1223 ea064d24 Andrea Spadaccini
        spice_arg = "%s,playback-compression=off" % spice_arg
1224 3e40b587 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_USE_VDAGENT]:
1225 3e40b587 Andrea Spadaccini
        spice_arg = "%s,agent-mouse=off" % spice_arg
1226 ea064d24 Andrea Spadaccini
1227 b1cb62bd Andrea Spadaccini
      logging.info("KVM: SPICE will listen on port %s", instance.network_port)
1228 b1cb62bd Andrea Spadaccini
      kvm_cmd.extend(["-spice", spice_arg])
1229 b1cb62bd Andrea Spadaccini
1230 2ebdfbb5 Andrea Spadaccini
      # Tell kvm to use the paravirtualized graphic card, optimized for SPICE
1231 2ebdfbb5 Andrea Spadaccini
      kvm_cmd.extend(["-vga", "qxl"])
1232 2ebdfbb5 Andrea Spadaccini
1233 6b970cef Jun Futagawa
    if hvp[constants.HV_USE_LOCALTIME]:
1234 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-localtime"])
1235 6b970cef Jun Futagawa
1236 547a63b7 Balazs Lecz
    if hvp[constants.HV_KVM_USE_CHROOT]:
1237 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-chroot", self._InstanceChrootDir(instance.name)])
1238 547a63b7 Balazs Lecz
1239 ee5f20b0 Guido Trotter
    # Save the current instance nics, but defer their expansion as parameters,
1240 ee5f20b0 Guido Trotter
    # as we'll need to generate executable temp files for them.
1241 ee5f20b0 Guido Trotter
    kvm_nics = instance.nics
1242 a985b417 Iustin Pop
    hvparams = hvp
1243 ee5f20b0 Guido Trotter
1244 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
1245 ee5f20b0 Guido Trotter
1246 38e250ba Guido Trotter
  def _WriteKVMRuntime(self, instance_name, data):
1247 38e250ba Guido Trotter
    """Write an instance's KVM runtime
1248 38e250ba Guido Trotter

1249 38e250ba Guido Trotter
    """
1250 38e250ba Guido Trotter
    try:
1251 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1252 38e250ba Guido Trotter
                      data=data)
1253 90c024f6 Guido Trotter
    except EnvironmentError, err:
1254 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1255 38e250ba Guido Trotter
1256 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
1257 38e250ba Guido Trotter
    """Read an instance's KVM runtime
1258 38e250ba Guido Trotter

1259 38e250ba Guido Trotter
    """
1260 38e250ba Guido Trotter
    try:
1261 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1262 90c024f6 Guido Trotter
    except EnvironmentError, err:
1263 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1264 38e250ba Guido Trotter
    return file_content
1265 38e250ba Guido Trotter
1266 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1267 38e250ba Guido Trotter
    """Save an instance's KVM runtime
1268 38e250ba Guido Trotter

1269 38e250ba Guido Trotter
    """
1270 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
1271 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1272 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
1273 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
1274 38e250ba Guido Trotter
1275 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1276 38e250ba Guido Trotter
    """Load an instance's KVM runtime
1277 38e250ba Guido Trotter

1278 38e250ba Guido Trotter
    """
1279 30e42c4e Guido Trotter
    if not serialized_runtime:
1280 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1281 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
1282 c2672466 Guido Trotter
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
1283 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
1284 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
1285 38e250ba Guido Trotter
1286 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1287 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
1288 76431533 Guido Trotter

1289 76431533 Guido Trotter
    @type name: string
1290 76431533 Guido Trotter
    @param name: instance name
1291 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1292 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1293 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1294 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1295 76431533 Guido Trotter

1296 76431533 Guido Trotter
    """
1297 5d9bfd87 Apollon Oikonomopoulos
    try:
1298 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1299 5d9bfd87 Apollon Oikonomopoulos
    finally:
1300 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
1301 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
1302 5d9bfd87 Apollon Oikonomopoulos
1303 76431533 Guido Trotter
    if result.failed:
1304 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1305 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
1306 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
1307 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
1308 76431533 Guido Trotter
1309 30e42c4e Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
1310 ee5f20b0 Guido Trotter
    """Execute a KVM cmd, after completing it with some last minute data
1311 ee5f20b0 Guido Trotter

1312 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1313 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1314 30e42c4e Guido Trotter

1315 ee5f20b0 Guido Trotter
    """
1316 297e6e53 Guido Trotter
    # Small _ExecuteKVMRuntime hv parameters programming howto:
1317 297e6e53 Guido Trotter
    #  - conf_hvp contains the parameters as configured on ganeti. they might
1318 297e6e53 Guido Trotter
    #    have changed since the instance started; only use them if the change
1319 297e6e53 Guido Trotter
    #    won't affect the inside of the instance (which hasn't been rebooted).
1320 297e6e53 Guido Trotter
    #  - up_hvp contains the parameters as they were when the instance was
1321 297e6e53 Guido Trotter
    #    started, plus any new parameter which has been added between ganeti
1322 297e6e53 Guido Trotter
    #    versions: it is paramount that those default to a value which won't
1323 297e6e53 Guido Trotter
    #    affect the inside of the instance as well.
1324 297e6e53 Guido Trotter
    conf_hvp = instance.hvparams
1325 5905901c Iustin Pop
    name = instance.name
1326 5905901c Iustin Pop
    self._CheckDown(name)
1327 ee5f20b0 Guido Trotter
1328 ee5f20b0 Guido Trotter
    temp_files = []
1329 ee5f20b0 Guido Trotter
1330 297e6e53 Guido Trotter
    kvm_cmd, kvm_nics, up_hvp = kvm_runtime
1331 297e6e53 Guido Trotter
    up_hvp = objects.FillDict(conf_hvp, up_hvp)
1332 ee5f20b0 Guido Trotter
1333 440351f8 Andrea Spadaccini
    _, v_major, v_min, _ = self._GetKVMVersion()
1334 4b784cf8 Miguel Di Ciurcio Filho
1335 297e6e53 Guido Trotter
    # We know it's safe to run as a different user upon migration, so we'll use
1336 297e6e53 Guido Trotter
    # the latest conf, from conf_hvp.
1337 297e6e53 Guido Trotter
    security_model = conf_hvp[constants.HV_SECURITY_MODEL]
1338 cef34868 Guido Trotter
    if security_model == constants.HT_SM_USER:
1339 297e6e53 Guido Trotter
      kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
1340 cef34868 Guido Trotter
1341 297e6e53 Guido Trotter
    # We have reasons to believe changing something like the nic driver/type
1342 297e6e53 Guido Trotter
    # upon migration won't exactly fly with the instance kernel, so for nic
1343 297e6e53 Guido Trotter
    # related parameters we'll use up_hvp
1344 5d9bfd87 Apollon Oikonomopoulos
    tapfds = []
1345 5d9bfd87 Apollon Oikonomopoulos
    taps = []
1346 ee5f20b0 Guido Trotter
    if not kvm_nics:
1347 fbe27e2b Guido Trotter
      kvm_cmd.extend(["-net", "none"])
1348 ee5f20b0 Guido Trotter
    else:
1349 5d9bfd87 Apollon Oikonomopoulos
      vnet_hdr = False
1350 fbe27e2b Guido Trotter
      tap_extra = ""
1351 297e6e53 Guido Trotter
      nic_type = up_hvp[constants.HV_NIC_TYPE]
1352 37f88dc6 Guido Trotter
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
1353 4b784cf8 Miguel Di Ciurcio Filho
        # From version 0.12.0, kvm uses a new sintax for network configuration.
1354 049383d9 Adeodato Simo
        if (v_major, v_min) >= (0, 12):
1355 4b784cf8 Miguel Di Ciurcio Filho
          nic_model = "virtio-net-pci"
1356 5d9bfd87 Apollon Oikonomopoulos
          vnet_hdr = True
1357 4b784cf8 Miguel Di Ciurcio Filho
        else:
1358 4b784cf8 Miguel Di Ciurcio Filho
          nic_model = "virtio"
1359 4b784cf8 Miguel Di Ciurcio Filho
1360 297e6e53 Guido Trotter
        if up_hvp[constants.HV_VHOST_NET]:
1361 4b784cf8 Miguel Di Ciurcio Filho
          # vhost_net is only available from version 0.13.0 or newer
1362 049383d9 Adeodato Simo
          if (v_major, v_min) >= (0, 13):
1363 4b784cf8 Miguel Di Ciurcio Filho
            tap_extra = ",vhost=on"
1364 4b784cf8 Miguel Di Ciurcio Filho
          else:
1365 4b784cf8 Miguel Di Ciurcio Filho
            raise errors.HypervisorError("vhost_net is configured"
1366 4b784cf8 Miguel Di Ciurcio Filho
                                        " but it is not available")
1367 37f88dc6 Guido Trotter
      else:
1368 4b784cf8 Miguel Di Ciurcio Filho
        nic_model = nic_type
1369 37f88dc6 Guido Trotter
1370 ee5f20b0 Guido Trotter
      for nic_seq, nic in enumerate(kvm_nics):
1371 5d9bfd87 Apollon Oikonomopoulos
        tapname, tapfd = _OpenTap(vnet_hdr)
1372 5d9bfd87 Apollon Oikonomopoulos
        tapfds.append(tapfd)
1373 5d9bfd87 Apollon Oikonomopoulos
        taps.append(tapname)
1374 049383d9 Adeodato Simo
        if (v_major, v_min) >= (0, 12):
1375 4b784cf8 Miguel Di Ciurcio Filho
          nic_val = "%s,mac=%s,netdev=netdev%s" % (nic_model, nic.mac, nic_seq)
1376 5d9bfd87 Apollon Oikonomopoulos
          tap_val = "type=tap,id=netdev%s,fd=%d%s" % (nic_seq, tapfd, tap_extra)
1377 4b784cf8 Miguel Di Ciurcio Filho
          kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
1378 4b784cf8 Miguel Di Ciurcio Filho
        else:
1379 049383d9 Adeodato Simo
          nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq,
1380 049383d9 Adeodato Simo
                                                         nic.mac, nic_model)
1381 5d9bfd87 Apollon Oikonomopoulos
          tap_val = "tap,vlan=%s,fd=%d" % (nic_seq, tapfd)
1382 4b784cf8 Miguel Di Ciurcio Filho
          kvm_cmd.extend(["-net", tap_val, "-net", nic_val])
1383 ee5f20b0 Guido Trotter
1384 30e42c4e Guido Trotter
    if incoming:
1385 30e42c4e Guido Trotter
      target, port = incoming
1386 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])
1387 30e42c4e Guido Trotter
1388 297e6e53 Guido Trotter
    # Changing the vnc password doesn't bother the guest that much. At most it
1389 297e6e53 Guido Trotter
    # will surprise people who connect to it. Whether positively or negatively
1390 297e6e53 Guido Trotter
    # it's debatable.
1391 297e6e53 Guido Trotter
    vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
1392 6e6bb8d5 Guido Trotter
    vnc_pwd = None
1393 6e6bb8d5 Guido Trotter
    if vnc_pwd_file:
1394 6e6bb8d5 Guido Trotter
      try:
1395 682f7601 Guido Trotter
        vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
1396 6e6bb8d5 Guido Trotter
      except EnvironmentError, err:
1397 6e6bb8d5 Guido Trotter
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
1398 6e6bb8d5 Guido Trotter
                                     % (vnc_pwd_file, err))
1399 6e6bb8d5 Guido Trotter
1400 297e6e53 Guido Trotter
    if conf_hvp[constants.HV_KVM_USE_CHROOT]:
1401 547a63b7 Balazs Lecz
      utils.EnsureDirs([(self._InstanceChrootDir(name),
1402 547a63b7 Balazs Lecz
                         constants.SECURE_DIR_MODE)])
1403 547a63b7 Balazs Lecz
1404 91c10532 Andrea Spadaccini
    # Automatically enable QMP if version is >= 0.14
1405 91c10532 Andrea Spadaccini
    if (v_major, v_min) >= (0, 14):
1406 91c10532 Andrea Spadaccini
      logging.debug("Enabling QMP")
1407 91c10532 Andrea Spadaccini
      kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
1408 91c10532 Andrea Spadaccini
                    self._InstanceQmpMonitor(instance.name)])
1409 91c10532 Andrea Spadaccini
1410 cc8a8ed7 Apollon Oikonomopoulos
    # Configure the network now for starting instances and bridged interfaces,
1411 cc8a8ed7 Apollon Oikonomopoulos
    # during FinalizeMigration for incoming instances' routed interfaces
1412 cc8a8ed7 Apollon Oikonomopoulos
    for nic_seq, nic in enumerate(kvm_nics):
1413 cc8a8ed7 Apollon Oikonomopoulos
      if (incoming and
1414 cc8a8ed7 Apollon Oikonomopoulos
          nic.nicparams[constants.NIC_MODE] != constants.NIC_MODE_BRIDGED):
1415 cc8a8ed7 Apollon Oikonomopoulos
        continue
1416 cc8a8ed7 Apollon Oikonomopoulos
      self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
1417 5d9bfd87 Apollon Oikonomopoulos
1418 1d8a7812 Andrea Spadaccini
    # CPU affinity requires kvm to start paused, so we set this flag if the
1419 1d8a7812 Andrea Spadaccini
    # instance is not already paused and if we are not going to accept a
1420 1d8a7812 Andrea Spadaccini
    # migrating instance. In the latter case, pausing is not needed.
1421 1d8a7812 Andrea Spadaccini
    start_kvm_paused = not (_KVM_START_PAUSED_FLAG in kvm_cmd) and not incoming
1422 945a7e67 Guido Trotter
    if start_kvm_paused:
1423 945a7e67 Guido Trotter
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1424 b693125f Tsachy Shacham
1425 b693125f Tsachy Shacham
    # Note: CPU pinning is using up_hvp since changes take effect
1426 b693125f Tsachy Shacham
    # during instance startup anyway, and to avoid problems when soft
1427 b693125f Tsachy Shacham
    # rebooting the instance.
1428 c607b1f7 Tsachy Shacham
    cpu_pinning = False
1429 b693125f Tsachy Shacham
    if up_hvp.get(constants.HV_CPU_MASK, None):
1430 b693125f Tsachy Shacham
      cpu_pinning = True
1431 b693125f Tsachy Shacham
1432 76431533 Guido Trotter
    if security_model == constants.HT_SM_POOL:
1433 76431533 Guido Trotter
      ss = ssconf.SimpleStore()
1434 76431533 Guido Trotter
      uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
1435 76431533 Guido Trotter
      all_uids = set(uidpool.ExpandUidPool(uid_pool))
1436 76431533 Guido Trotter
      uid = uidpool.RequestUnusedUid(all_uids)
1437 76431533 Guido Trotter
      try:
1438 76431533 Guido Trotter
        username = pwd.getpwuid(uid.GetUid()).pw_name
1439 76431533 Guido Trotter
        kvm_cmd.extend(["-runas", username])
1440 5d9bfd87 Apollon Oikonomopoulos
        self._RunKVMCmd(name, kvm_cmd, tapfds)
1441 76431533 Guido Trotter
      except:
1442 76431533 Guido Trotter
        uidpool.ReleaseUid(uid)
1443 76431533 Guido Trotter
        raise
1444 76431533 Guido Trotter
      else:
1445 76431533 Guido Trotter
        uid.Unlock()
1446 3af16328 Apollon Oikonomopoulos
        utils.WriteFile(self._InstanceUidFile(name), data=uid.AsStr())
1447 76431533 Guido Trotter
    else:
1448 5d9bfd87 Apollon Oikonomopoulos
      self._RunKVMCmd(name, kvm_cmd, tapfds)
1449 5d9bfd87 Apollon Oikonomopoulos
1450 5d9bfd87 Apollon Oikonomopoulos
    utils.EnsureDirs([(self._InstanceNICDir(instance.name),
1451 5d9bfd87 Apollon Oikonomopoulos
                     constants.RUN_DIRS_MODE)])
1452 5d9bfd87 Apollon Oikonomopoulos
    for nic_seq, tap in enumerate(taps):
1453 5d9bfd87 Apollon Oikonomopoulos
      utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
1454 5d9bfd87 Apollon Oikonomopoulos
                      data=tap)
1455 eb58f9b1 Guido Trotter
1456 6e6bb8d5 Guido Trotter
    if vnc_pwd:
1457 d0c8c01d Iustin Pop
      change_cmd = "change vnc password %s" % vnc_pwd
1458 6e6bb8d5 Guido Trotter
      self._CallMonitorCommand(instance.name, change_cmd)
1459 6e6bb8d5 Guido Trotter
1460 b451c4c7 Andrea Spadaccini
    # Setting SPICE password. We are not vulnerable to malicious passwordless
1461 b451c4c7 Andrea Spadaccini
    # connection attempts because SPICE by default does not allow connections
1462 b451c4c7 Andrea Spadaccini
    # if neither a password nor the "disable_ticketing" options are specified.
1463 b451c4c7 Andrea Spadaccini
    # As soon as we send the password via QMP, that password is a valid ticket
1464 b451c4c7 Andrea Spadaccini
    # for connection.
1465 b451c4c7 Andrea Spadaccini
    spice_password_file = conf_hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]
1466 b451c4c7 Andrea Spadaccini
    if spice_password_file:
1467 fc84cd5d Guido Trotter
      spice_pwd = ""
1468 b451c4c7 Andrea Spadaccini
      try:
1469 b451c4c7 Andrea Spadaccini
        spice_pwd = utils.ReadOneLineFile(spice_password_file, strict=True)
1470 b451c4c7 Andrea Spadaccini
      except EnvironmentError, err:
1471 b451c4c7 Andrea Spadaccini
        raise errors.HypervisorError("Failed to open SPICE password file %s: %s"
1472 b451c4c7 Andrea Spadaccini
                                     % (spice_password_file, err))
1473 b451c4c7 Andrea Spadaccini
1474 fc84cd5d Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
1475 fc84cd5d Guido Trotter
      qmp.connect()
1476 fc84cd5d Guido Trotter
      arguments = {
1477 fc84cd5d Guido Trotter
          "protocol": "spice",
1478 fc84cd5d Guido Trotter
          "password": spice_pwd,
1479 fc84cd5d Guido Trotter
      }
1480 fc84cd5d Guido Trotter
      qmp.Execute("set_password", arguments)
1481 fc84cd5d Guido Trotter
1482 08137f9e Iustin Pop
    for filename in temp_files:
1483 08137f9e Iustin Pop
      utils.RemoveFile(filename)
1484 eb58f9b1 Guido Trotter
1485 b693125f Tsachy Shacham
    # If requested, set CPU affinity and resume instance execution
1486 b693125f Tsachy Shacham
    if cpu_pinning:
1487 945a7e67 Guido Trotter
      self._ExecuteCpuAffinity(instance.name, up_hvp[constants.HV_CPU_MASK])
1488 945a7e67 Guido Trotter
1489 61eb1a46 Guido Trotter
    start_memory = self._InstanceStartupMemory(instance)
1490 61eb1a46 Guido Trotter
    if start_memory < instance.beparams[constants.BE_MAXMEM]:
1491 61eb1a46 Guido Trotter
      self.BalloonInstanceMemory(instance, start_memory)
1492 61eb1a46 Guido Trotter
1493 945a7e67 Guido Trotter
    if start_kvm_paused:
1494 945a7e67 Guido Trotter
      # To control CPU pinning, ballooning, and vnc/spice passwords the VM was
1495 945a7e67 Guido Trotter
      # started in a frozen state. If freezing was not explicitely requested
1496 945a7e67 Guido Trotter
      # resume the vm status.
1497 945a7e67 Guido Trotter
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1498 b693125f Tsachy Shacham
1499 323f9095 Stephen Shirley
  def StartInstance(self, instance, block_devices, startup_paused):
1500 ee5f20b0 Guido Trotter
    """Start an instance.
1501 ee5f20b0 Guido Trotter

1502 ee5f20b0 Guido Trotter
    """
1503 5905901c Iustin Pop
    self._CheckDown(instance.name)
1504 7238edb5 Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1505 7238edb5 Iustin Pop
                                           startup_paused)
1506 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1507 ee5f20b0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
1508 ee5f20b0 Guido Trotter
1509 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
1510 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
1511 6567aff3 Guido Trotter

1512 6567aff3 Guido Trotter
    """
1513 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1514 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
1515 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
1516 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1517 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
1518 6567aff3 Guido Trotter
    if result.failed:
1519 6567aff3 Guido Trotter
      msg = ("Failed to send command '%s' to instance %s."
1520 6567aff3 Guido Trotter
             " output: %s, error: %s, fail_reason: %s" %
1521 9798fcae Guido Trotter
             (command, instance_name,
1522 9798fcae Guido Trotter
              result.stdout, result.stderr, result.fail_reason))
1523 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
1524 6567aff3 Guido Trotter
1525 6567aff3 Guido Trotter
    return result
1526 6567aff3 Guido Trotter
1527 b52d85c1 Guido Trotter
  @classmethod
1528 585c8187 Guido Trotter
  def _ParseKVMVersion(cls, text):
1529 585c8187 Guido Trotter
    """Parse the KVM version from the --help output.
1530 585c8187 Guido Trotter

1531 585c8187 Guido Trotter
    @type text: string
1532 585c8187 Guido Trotter
    @param text: output of kvm --help
1533 585c8187 Guido Trotter
    @return: (version, v_maj, v_min, v_rev)
1534 585c8187 Guido Trotter
    @raise L{errors.HypervisorError}: when the KVM version cannot be retrieved
1535 585c8187 Guido Trotter

1536 585c8187 Guido Trotter
    """
1537 585c8187 Guido Trotter
    match = cls._VERSION_RE.search(text.splitlines()[0])
1538 585c8187 Guido Trotter
    if not match:
1539 585c8187 Guido Trotter
      raise errors.HypervisorError("Unable to get KVM version")
1540 585c8187 Guido Trotter
1541 585c8187 Guido Trotter
    v_all = match.group(0)
1542 585c8187 Guido Trotter
    v_maj = int(match.group(1))
1543 585c8187 Guido Trotter
    v_min = int(match.group(2))
1544 585c8187 Guido Trotter
    if match.group(4):
1545 585c8187 Guido Trotter
      v_rev = int(match.group(4))
1546 585c8187 Guido Trotter
    else:
1547 585c8187 Guido Trotter
      v_rev = 0
1548 585c8187 Guido Trotter
    return (v_all, v_maj, v_min, v_rev)
1549 585c8187 Guido Trotter
1550 585c8187 Guido Trotter
  @classmethod
1551 b52d85c1 Guido Trotter
  def _GetKVMVersion(cls):
1552 d7e4a2b1 Andrea Spadaccini
    """Return the installed KVM version.
1553 b52d85c1 Guido Trotter

1554 440351f8 Andrea Spadaccini
    @return: (version, v_maj, v_min, v_rev)
1555 d7e4a2b1 Andrea Spadaccini
    @raise L{errors.HypervisorError}: when the KVM version cannot be retrieved
1556 b52d85c1 Guido Trotter

1557 b52d85c1 Guido Trotter
    """
1558 b52d85c1 Guido Trotter
    result = utils.RunCmd([constants.KVM_PATH, "--help"])
1559 b52d85c1 Guido Trotter
    if result.failed:
1560 440351f8 Andrea Spadaccini
      raise errors.HypervisorError("Unable to get KVM version")
1561 585c8187 Guido Trotter
    return cls._ParseKVMVersion(result.output)
1562 b52d85c1 Guido Trotter
1563 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
1564 eb58f9b1 Guido Trotter
    """Stop an instance.
1565 eb58f9b1 Guido Trotter

1566 eb58f9b1 Guido Trotter
    """
1567 bbcf7ad0 Iustin Pop
    if name is not None and not force:
1568 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
1569 bbcf7ad0 Iustin Pop
    if name is None:
1570 bbcf7ad0 Iustin Pop
      name = instance.name
1571 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
1572 bbcf7ad0 Iustin Pop
    else:
1573 bbcf7ad0 Iustin Pop
      acpi = False
1574 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
1575 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
1576 bbcf7ad0 Iustin Pop
      if force or not acpi:
1577 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
1578 eb58f9b1 Guido Trotter
      else:
1579 d0c8c01d Iustin Pop
        self._CallMonitorCommand(name, "system_powerdown")
1580 eb58f9b1 Guido Trotter
1581 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
1582 8904b35c Guido Trotter
    """Cleanup after a stopped instance
1583 8904b35c Guido Trotter

1584 8904b35c Guido Trotter
    """
1585 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1586 8904b35c Guido Trotter
    if pid > 0 and alive:
1587 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
1588 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1589 eb58f9b1 Guido Trotter
1590 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
1591 eb58f9b1 Guido Trotter
    """Reboot an instance.
1592 eb58f9b1 Guido Trotter

1593 eb58f9b1 Guido Trotter
    """
1594 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
1595 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
1596 eb58f9b1 Guido Trotter
    # to shutdown and restart.
1597 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
1598 1f8b3a27 Guido Trotter
    if not alive:
1599 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
1600 78411c60 Iustin Pop
                                   " not running" % instance.name)
1601 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
1602 f02881e0 Guido Trotter
    # ...first load it...
1603 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
1604 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
1605 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
1606 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
1607 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
1608 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1609 f02881e0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
1610 eb58f9b1 Guido Trotter
1611 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
1612 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
1613 30e42c4e Guido Trotter

1614 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1615 30e42c4e Guido Trotter
    @param instance: instance to be migrated
1616 30e42c4e Guido Trotter
    @rtype: string
1617 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
1618 30e42c4e Guido Trotter

1619 30e42c4e Guido Trotter
    """
1620 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
1621 30e42c4e Guido Trotter
1622 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
1623 30e42c4e Guido Trotter
    """Prepare to accept an instance.
1624 30e42c4e Guido Trotter

1625 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1626 30e42c4e Guido Trotter
    @param instance: instance to be accepted
1627 30e42c4e Guido Trotter
    @type info: string
1628 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
1629 30e42c4e Guido Trotter
    @type target: string
1630 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
1631 30e42c4e Guido Trotter

1632 30e42c4e Guido Trotter
    """
1633 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1634 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1635 30e42c4e Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
1636 30e42c4e Guido Trotter
1637 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
1638 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
1639 30e42c4e Guido Trotter

1640 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
1641 30e42c4e Guido Trotter

1642 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1643 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
1644 30e42c4e Guido Trotter

1645 30e42c4e Guido Trotter
    """
1646 30e42c4e Guido Trotter
    if success:
1647 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1648 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
1649 5d9bfd87 Apollon Oikonomopoulos
1650 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
1651 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1652 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
1653 cc8a8ed7 Apollon Oikonomopoulos
          continue
1654 5d9bfd87 Apollon Oikonomopoulos
        try:
1655 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
1656 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
1657 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
1658 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
1659 5d9bfd87 Apollon Oikonomopoulos
          continue
1660 5d9bfd87 Apollon Oikonomopoulos
        try:
1661 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
1662 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
1663 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
1664 5d9bfd87 Apollon Oikonomopoulos
1665 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
1666 30e42c4e Guido Trotter
    else:
1667 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
1668 30e42c4e Guido Trotter
1669 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
1670 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
1671 30e42c4e Guido Trotter

1672 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
1673 30e42c4e Guido Trotter
    currently running.
1674 30e42c4e Guido Trotter

1675 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
1676 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
1677 30e42c4e Guido Trotter
    @type target: string
1678 30e42c4e Guido Trotter
    @param target: ip address of the target node
1679 30e42c4e Guido Trotter
    @type live: boolean
1680 30e42c4e Guido Trotter
    @param live: perform a live migration
1681 30e42c4e Guido Trotter

1682 30e42c4e Guido Trotter
    """
1683 58d38b02 Iustin Pop
    instance_name = instance.name
1684 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
1685 6a1434d7 Andrea Spadaccini
    _, _, alive = self._InstancePidAlive(instance_name)
1686 30e42c4e Guido Trotter
    if not alive:
1687 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
1688 30e42c4e Guido Trotter
1689 30e42c4e Guido Trotter
    if not live:
1690 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
1691 30e42c4e Guido Trotter
1692 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
1693 e43d4f9f Apollon Oikonomopoulos
        instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1694 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
1695 e43d4f9f Apollon Oikonomopoulos
1696 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
1697 e43d4f9f Apollon Oikonomopoulos
        instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
1698 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
1699 e43d4f9f Apollon Oikonomopoulos
1700 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
1701 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
1702 30e42c4e Guido Trotter
1703 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
1704 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
1705 6a1434d7 Andrea Spadaccini

1706 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
1707 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
1708 6a1434d7 Andrea Spadaccini
    @type success: bool
1709 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
1710 6a1434d7 Andrea Spadaccini
    @type live: bool
1711 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
1712 6a1434d7 Andrea Spadaccini

1713 6a1434d7 Andrea Spadaccini
    """
1714 6a1434d7 Andrea Spadaccini
    if success:
1715 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
1716 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
1717 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
1718 6a1434d7 Andrea Spadaccini
    elif live:
1719 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
1720 6a1434d7 Andrea Spadaccini
1721 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
1722 6a1434d7 Andrea Spadaccini
    """Get the migration status
1723 6a1434d7 Andrea Spadaccini

1724 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
1725 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
1726 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
1727 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
1728 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
1729 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
1730 6a1434d7 Andrea Spadaccini

1731 6a1434d7 Andrea Spadaccini
    """
1732 d0c8c01d Iustin Pop
    info_command = "info migrate"
1733 6a1434d7 Andrea Spadaccini
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
1734 6a1434d7 Andrea Spadaccini
      result = self._CallMonitorCommand(instance.name, info_command)
1735 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
1736 30e42c4e Guido Trotter
      if not match:
1737 c4e388a5 Guido Trotter
        if not result.stdout:
1738 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
1739 c4e388a5 Guido Trotter
        else:
1740 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
1741 c4e388a5 Guido Trotter
                          result.stdout)
1742 30e42c4e Guido Trotter
      else:
1743 30e42c4e Guido Trotter
        status = match.group(1)
1744 6a1434d7 Andrea Spadaccini
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
1745 6a1434d7 Andrea Spadaccini
          migration_status = objects.MigrationStatus(status=status)
1746 61643226 Andrea Spadaccini
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
1747 61643226 Andrea Spadaccini
          if match:
1748 61643226 Andrea Spadaccini
            migration_status.transferred_ram = match.group("transferred")
1749 61643226 Andrea Spadaccini
            migration_status.total_ram = match.group("total")
1750 61643226 Andrea Spadaccini
1751 6a1434d7 Andrea Spadaccini
          return migration_status
1752 30e42c4e Guido Trotter
1753 6a1434d7 Andrea Spadaccini
        logging.warning("KVM: unknown migration status '%s'", status)
1754 6a1434d7 Andrea Spadaccini
1755 6a1434d7 Andrea Spadaccini
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1756 6a1434d7 Andrea Spadaccini
1757 6a1434d7 Andrea Spadaccini
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED,
1758 6a1434d7 Andrea Spadaccini
                                  info="Too many 'info migrate' broken answers")
1759 30e42c4e Guido Trotter
1760 3d836750 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
1761 3d836750 Guido Trotter
    """Balloon an instance memory to a certain value.
1762 3d836750 Guido Trotter

1763 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
1764 3d836750 Guido Trotter
    @param instance: instance to be accepted
1765 3d836750 Guido Trotter
    @type mem: int
1766 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
1767 3d836750 Guido Trotter

1768 3d836750 Guido Trotter
    """
1769 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
1770 3d836750 Guido Trotter
1771 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
1772 eb58f9b1 Guido Trotter
    """Return information about the node.
1773 eb58f9b1 Guido Trotter

1774 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
1775 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
1776 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
1777 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
1778 34fbc862 Andrea Spadaccini
          - hv_version: the hypervisor version in the form (major, minor,
1779 34fbc862 Andrea Spadaccini
                        revision)
1780 eb58f9b1 Guido Trotter

1781 eb58f9b1 Guido Trotter
    """
1782 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
1783 34fbc862 Andrea Spadaccini
    _, v_major, v_min, v_rev = self._GetKVMVersion()
1784 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
1785 34fbc862 Andrea Spadaccini
    return result
1786 eb58f9b1 Guido Trotter
1787 637ce7f9 Guido Trotter
  @classmethod
1788 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
1789 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
1790 eb58f9b1 Guido Trotter

1791 eb58f9b1 Guido Trotter
    """
1792 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
1793 2f4c951e Stephen Shirley
      cmd = [constants.KVM_CONSOLE_WRAPPER,
1794 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
1795 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
1796 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
1797 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
1798 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
1799 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
1800 55cc0a44 Michael Hanselmann
                                     host=instance.primary_node,
1801 55cc0a44 Michael Hanselmann
                                     user=constants.GANETI_RUNAS,
1802 55cc0a44 Michael Hanselmann
                                     command=cmd)
1803 3be34f57 Guido Trotter
1804 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
1805 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
1806 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
1807 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
1808 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
1809 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
1810 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
1811 55cc0a44 Michael Hanselmann
                                     display=display)
1812 55cc0a44 Michael Hanselmann
1813 4d2cdb5a Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
1814 4d2cdb5a Andrea Spadaccini
    if spice_bind:
1815 4d2cdb5a Andrea Spadaccini
      return objects.InstanceConsole(instance=instance.name,
1816 4d2cdb5a Andrea Spadaccini
                                     kind=constants.CONS_SPICE,
1817 4d2cdb5a Andrea Spadaccini
                                     host=spice_bind,
1818 4d2cdb5a Andrea Spadaccini
                                     port=instance.network_port)
1819 4d2cdb5a Andrea Spadaccini
1820 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
1821 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
1822 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
1823 55cc0a44 Michael Hanselmann
                                            instance.name))
1824 eb58f9b1 Guido Trotter
1825 eb58f9b1 Guido Trotter
  def Verify(self):
1826 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
1827 eb58f9b1 Guido Trotter

1828 eb58f9b1 Guido Trotter
    Check that the binary exists.
1829 eb58f9b1 Guido Trotter

1830 eb58f9b1 Guido Trotter
    """
1831 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
1832 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
1833 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
1834 14aa53cb Guido Trotter
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
1835 14aa53cb Guido Trotter
1836 6b5605e8 Iustin Pop
  @classmethod
1837 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
1838 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
1839 6b5605e8 Iustin Pop

1840 6b5605e8 Iustin Pop
    @type hvparams:  dict
1841 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
1842 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
1843 6b5605e8 Iustin Pop

1844 6b5605e8 Iustin Pop
    """
1845 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
1846 6b5605e8 Iustin Pop
1847 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
1848 df5ab9f0 Guido Trotter
    if kernel_path:
1849 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
1850 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
1851 205ab586 Iustin Pop
                                     " if a kernel is defined")
1852 6b5605e8 Iustin Pop
1853 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
1854 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
1855 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
1856 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
1857 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
1858 66d5dbef Guido Trotter
1859 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
1860 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
1861 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
1862 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
1863 835528af Iustin Pop
                                   " ISO path")
1864 f5118ade Iustin Pop
1865 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
1866 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
1867 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
1868 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
1869 d19d94db Guido Trotter
                                     " must be specified")
1870 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
1871 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
1872 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
1873 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
1874 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
1875 d19d94db Guido Trotter
1876 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
1877 b451c4c7 Andrea Spadaccini
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
1878 b1cb62bd Andrea Spadaccini
    if spice_bind:
1879 b1cb62bd Andrea Spadaccini
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1880 b1cb62bd Andrea Spadaccini
        # if an IP version is specified, the spice_bind parameter must be an
1881 b1cb62bd Andrea Spadaccini
        # IP of that family
1882 b1cb62bd Andrea Spadaccini
        if (netutils.IP4Address.IsValid(spice_bind) and
1883 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP4_VERSION):
1884 b1cb62bd Andrea Spadaccini
          raise errors.HypervisorError("spice: got an IPv4 address (%s), but"
1885 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
1886 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
1887 b1cb62bd Andrea Spadaccini
1888 b1cb62bd Andrea Spadaccini
        if (netutils.IP6Address.IsValid(spice_bind) and
1889 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP6_VERSION):
1890 b1cb62bd Andrea Spadaccini
          raise errors.HypervisorError("spice: got an IPv6 address (%s), but"
1891 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
1892 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
1893 b451c4c7 Andrea Spadaccini
    else:
1894 0e1b03b9 Andrea Spadaccini
      # All the other SPICE parameters depend on spice_bind being set. Raise an
1895 0e1b03b9 Andrea Spadaccini
      # error if any of them is set without it.
1896 0e1b03b9 Andrea Spadaccini
      spice_additional_params = frozenset([
1897 0e1b03b9 Andrea Spadaccini
        constants.HV_KVM_SPICE_IP_VERSION,
1898 0e1b03b9 Andrea Spadaccini
        constants.HV_KVM_SPICE_PASSWORD_FILE,
1899 ea064d24 Andrea Spadaccini
        constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR,
1900 ea064d24 Andrea Spadaccini
        constants.HV_KVM_SPICE_JPEG_IMG_COMPR,
1901 ea064d24 Andrea Spadaccini
        constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR,
1902 ea064d24 Andrea Spadaccini
        constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION,
1903 bfe86c76 Andrea Spadaccini
        constants.HV_KVM_SPICE_USE_TLS,
1904 0e1b03b9 Andrea Spadaccini
        ])
1905 0e1b03b9 Andrea Spadaccini
      for param in spice_additional_params:
1906 0e1b03b9 Andrea Spadaccini
        if hvparams[param]:
1907 0e1b03b9 Andrea Spadaccini
          raise errors.HypervisorError("spice: %s requires %s to be set" %
1908 0e1b03b9 Andrea Spadaccini
                                       (param, constants.HV_KVM_SPICE_BIND))
1909 b1cb62bd Andrea Spadaccini
1910 d19d94db Guido Trotter
  @classmethod
1911 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
1912 d19d94db Guido Trotter
    """Check the given parameters for validity.
1913 d19d94db Guido Trotter

1914 d19d94db Guido Trotter
    @type hvparams:  dict
1915 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
1916 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
1917 d19d94db Guido Trotter

1918 d19d94db Guido Trotter
    """
1919 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
1920 d19d94db Guido Trotter
1921 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
1922 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
1923 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
1924 d19d94db Guido Trotter
      try:
1925 1feb39ec Guido Trotter
        pwd.getpwnam(username)
1926 d19d94db Guido Trotter
      except KeyError:
1927 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
1928 d19d94db Guido Trotter
                                     % username)
1929 d19d94db Guido Trotter
1930 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
1931 b1cb62bd Andrea Spadaccini
    if spice_bind:
1932 b1cb62bd Andrea Spadaccini
      # only one of VNC and SPICE can be used currently.
1933 b1cb62bd Andrea Spadaccini
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
1934 b1cb62bd Andrea Spadaccini
        raise errors.HypervisorError("both SPICE and VNC are configured, but"
1935 b1cb62bd Andrea Spadaccini
                                     " only one of them can be used at a"
1936 b1cb62bd Andrea Spadaccini
                                     " given time.")
1937 b1cb62bd Andrea Spadaccini
1938 b1cb62bd Andrea Spadaccini
      # KVM version should be >= 0.14.0
1939 b1cb62bd Andrea Spadaccini
      _, v_major, v_min, _ = cls._GetKVMVersion()
1940 b1cb62bd Andrea Spadaccini
      if (v_major, v_min) < (0, 14):
1941 b1cb62bd Andrea Spadaccini
        raise errors.HypervisorError("spice is configured, but it is not"
1942 b1cb62bd Andrea Spadaccini
                                     " available in versions of KVM < 0.14")
1943 b1cb62bd Andrea Spadaccini
1944 b1cb62bd Andrea Spadaccini
      # if spice_bind is not an IP address, it must be a valid interface
1945 b1cb62bd Andrea Spadaccini
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind)
1946 b1cb62bd Andrea Spadaccini
                       or netutils.IP6Address.IsValid(spice_bind))
1947 b1cb62bd Andrea Spadaccini
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
1948 b1cb62bd Andrea Spadaccini
        raise errors.HypervisorError("spice: the %s parameter must be either"
1949 b1cb62bd Andrea Spadaccini
                                     " a valid IP address or interface name" %
1950 b1cb62bd Andrea Spadaccini
                                     constants.HV_KVM_SPICE_BIND)
1951 b1cb62bd Andrea Spadaccini
1952 f5118ade Iustin Pop
  @classmethod
1953 f5118ade Iustin Pop
  def PowercycleNode(cls):
1954 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
1955 f5118ade Iustin Pop

1956 f5118ade Iustin Pop
    """
1957 f5118ade Iustin Pop
    cls.LinuxPowercycle()