Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 69ab2e12

History | View | Annotate | Download (61.7 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 91c10532 Andrea Spadaccini
import StringIO
39 eb58f9b1 Guido Trotter
40 eb58f9b1 Guido Trotter
from ganeti import utils
41 eb58f9b1 Guido Trotter
from ganeti import constants
42 eb58f9b1 Guido Trotter
from ganeti import errors
43 38e250ba Guido Trotter
from ganeti import serializer
44 38e250ba Guido Trotter
from ganeti import objects
45 76431533 Guido Trotter
from ganeti import uidpool
46 76431533 Guido Trotter
from ganeti import ssconf
47 eb58f9b1 Guido Trotter
from ganeti.hypervisor import hv_base
48 a744b676 Manuel Franceschini
from ganeti import netutils
49 5d9bfd87 Apollon Oikonomopoulos
from ganeti.utils import wrapper as utils_wrapper
50 eb58f9b1 Guido Trotter
51 eb58f9b1 Guido Trotter
52 748e4b5a Michael Hanselmann
_KVM_NETWORK_SCRIPT = constants.SYSCONFDIR + "/ganeti/kvm-vif-bridge"
53 748e4b5a Michael Hanselmann
54 199b2053 Apollon Oikonomopoulos
# TUN/TAP driver constants, taken from <linux/if_tun.h>
55 199b2053 Apollon Oikonomopoulos
# They are architecture-independent and already hardcoded in qemu-kvm source,
56 199b2053 Apollon Oikonomopoulos
# so we can safely include them here.
57 199b2053 Apollon Oikonomopoulos
TUNSETIFF = 0x400454ca
58 199b2053 Apollon Oikonomopoulos
TUNGETIFF = 0x800454d2
59 199b2053 Apollon Oikonomopoulos
TUNGETFEATURES = 0x800454cf
60 199b2053 Apollon Oikonomopoulos
IFF_TAP = 0x0002
61 199b2053 Apollon Oikonomopoulos
IFF_NO_PI = 0x1000
62 199b2053 Apollon Oikonomopoulos
IFF_VNET_HDR = 0x4000
63 199b2053 Apollon Oikonomopoulos
64 199b2053 Apollon Oikonomopoulos
65 199b2053 Apollon Oikonomopoulos
def _ProbeTapVnetHdr(fd):
66 199b2053 Apollon Oikonomopoulos
  """Check whether to enable the IFF_VNET_HDR flag.
67 199b2053 Apollon Oikonomopoulos

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

78 199b2053 Apollon Oikonomopoulos
   @type fd: int
79 199b2053 Apollon Oikonomopoulos
   @param fd: the file descriptor of /dev/net/tun
80 199b2053 Apollon Oikonomopoulos

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

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

103 199b2053 Apollon Oikonomopoulos
  @type vnet_hdr: boolean
104 199b2053 Apollon Oikonomopoulos
  @param vnet_hdr: Enable the VNET Header
105 199b2053 Apollon Oikonomopoulos
  @return: (ifname, tapfd)
106 199b2053 Apollon Oikonomopoulos
  @rtype: tuple
107 199b2053 Apollon Oikonomopoulos

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

135 91c10532 Andrea Spadaccini
  """
136 91c10532 Andrea Spadaccini
137 91c10532 Andrea Spadaccini
  def __init__(self, data):
138 91c10532 Andrea Spadaccini
    """Creates a new QMP message based on the passed data.
139 91c10532 Andrea Spadaccini

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

149 91c10532 Andrea Spadaccini
    Overrides the [] operator to provide access to the message data,
150 91c10532 Andrea Spadaccini
    returning None if the required item is not in the message
151 91c10532 Andrea Spadaccini
    @return: the value of the field_name field, or None if field_name
152 91c10532 Andrea Spadaccini
             is not contained in the message
153 91c10532 Andrea Spadaccini

154 91c10532 Andrea Spadaccini
    """
155 91c10532 Andrea Spadaccini
156 91c10532 Andrea Spadaccini
    if field_name in self.data:
157 91c10532 Andrea Spadaccini
      return self.data[field_name]
158 91c10532 Andrea Spadaccini
159 91c10532 Andrea Spadaccini
    return None
160 91c10532 Andrea Spadaccini
161 91c10532 Andrea Spadaccini
  def __setitem__(self, field_name, field_value):
162 91c10532 Andrea Spadaccini
    """Set the value of the required field_name to field_value.
163 91c10532 Andrea Spadaccini

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

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

176 91c10532 Andrea Spadaccini
    """
177 91c10532 Andrea Spadaccini
    # Parse the string
178 91c10532 Andrea Spadaccini
    data = serializer.LoadJson(json_string)
179 91c10532 Andrea Spadaccini
    return QmpMessage(data)
180 91c10532 Andrea Spadaccini
181 91c10532 Andrea Spadaccini
  def __str__(self):
182 91c10532 Andrea Spadaccini
    # The protocol expects the JSON object to be sent as a single
183 91c10532 Andrea Spadaccini
    # line, hence the need for indent=False.
184 91c10532 Andrea Spadaccini
    return serializer.DumpJson(self.data, indent=False)
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 91c10532 Andrea Spadaccini
  _ERROR_CLASS_KEY = "class"
200 91c10532 Andrea Spadaccini
  _ERROR_DATA_KEY = "data"
201 91c10532 Andrea Spadaccini
  _ERROR_DESC_KEY = "desc"
202 91c10532 Andrea Spadaccini
  _EXECUTE_KEY = "execute"
203 91c10532 Andrea Spadaccini
  _ARGUMENTS_KEY = "arguments"
204 91c10532 Andrea Spadaccini
  _CAPABILITIES_COMMAND = "qmp_capabilities"
205 91c10532 Andrea Spadaccini
  _MESSAGE_END_TOKEN = "\r\n"
206 91c10532 Andrea Spadaccini
  _SOCKET_TIMEOUT = 5
207 91c10532 Andrea Spadaccini
208 91c10532 Andrea Spadaccini
  def __init__(self, monitor_filename):
209 91c10532 Andrea Spadaccini
    """Instantiates the QmpConnection object.
210 91c10532 Andrea Spadaccini

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

215 91c10532 Andrea Spadaccini
    """
216 91c10532 Andrea Spadaccini
    self.monitor_filename = monitor_filename
217 91c10532 Andrea Spadaccini
    self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
218 91c10532 Andrea Spadaccini
    # We want to fail if the server doesn't send a complete message
219 91c10532 Andrea Spadaccini
    # in a reasonable amount of time
220 91c10532 Andrea Spadaccini
    self.sock.settimeout(self._SOCKET_TIMEOUT)
221 91c10532 Andrea Spadaccini
    self._connected = False
222 91c10532 Andrea Spadaccini
    self._buf = ""
223 91c10532 Andrea Spadaccini
224 91c10532 Andrea Spadaccini
  def _check_connection(self):
225 91c10532 Andrea Spadaccini
    """Make sure that the connection is established.
226 91c10532 Andrea Spadaccini

227 91c10532 Andrea Spadaccini
    """
228 91c10532 Andrea Spadaccini
    if not self._connected:
229 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("To use a QmpConnection you need to first"
230 91c10532 Andrea Spadaccini
                                   " invoke connect() on it")
231 91c10532 Andrea Spadaccini
232 91c10532 Andrea Spadaccini
  def connect(self):
233 91c10532 Andrea Spadaccini
    """Connects to the QMP monitor.
234 91c10532 Andrea Spadaccini

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

238 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
239 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
240 91c10532 Andrea Spadaccini

241 91c10532 Andrea Spadaccini
    """
242 91c10532 Andrea Spadaccini
    self.sock.connect(self.monitor_filename)
243 91c10532 Andrea Spadaccini
    self._connected = True
244 91c10532 Andrea Spadaccini
245 91c10532 Andrea Spadaccini
    # Check if we receive a correct greeting message from the server
246 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 2.2)
247 91c10532 Andrea Spadaccini
    greeting = self._Recv()
248 91c10532 Andrea Spadaccini
    if not greeting[self._FIRST_MESSAGE_KEY]:
249 91c10532 Andrea Spadaccini
      self._connected = False
250 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("kvm: qmp communication error (wrong"
251 91c10532 Andrea Spadaccini
                                   " server greeting")
252 91c10532 Andrea Spadaccini
253 91c10532 Andrea Spadaccini
    # Let's put the monitor in command mode using the qmp_capabilities
254 91c10532 Andrea Spadaccini
    # command, or else no command will be executable.
255 91c10532 Andrea Spadaccini
    # (As per the QEMU Protocol Specification 0.1 - section 4)
256 91c10532 Andrea Spadaccini
    self.Execute(self._CAPABILITIES_COMMAND)
257 91c10532 Andrea Spadaccini
258 91c10532 Andrea Spadaccini
  def _ParseMessage(self, buf):
259 91c10532 Andrea Spadaccini
    """Extract and parse a QMP message from the given buffer.
260 91c10532 Andrea Spadaccini

261 91c10532 Andrea Spadaccini
    Seeks for a QMP message in the given buf. If found, it parses it and
262 91c10532 Andrea Spadaccini
    returns it together with the rest of the characters in the buf.
263 91c10532 Andrea Spadaccini
    If no message is found, returns None and the whole buffer.
264 91c10532 Andrea Spadaccini

265 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
266 91c10532 Andrea Spadaccini

267 91c10532 Andrea Spadaccini
    """
268 91c10532 Andrea Spadaccini
    message = None
269 91c10532 Andrea Spadaccini
    # Check if we got the message end token (CRLF, as per the QEMU Protocol
270 91c10532 Andrea Spadaccini
    # Specification 0.1 - Section 2.1.1)
271 91c10532 Andrea Spadaccini
    pos = buf.find(self._MESSAGE_END_TOKEN)
272 91c10532 Andrea Spadaccini
    if pos >= 0:
273 91c10532 Andrea Spadaccini
      try:
274 91c10532 Andrea Spadaccini
        message = QmpMessage.BuildFromJsonString(buf[:pos + 1])
275 91c10532 Andrea Spadaccini
      except Exception, err:
276 91c10532 Andrea Spadaccini
        raise errors.ProgrammerError("QMP data serialization error: %s" % err)
277 91c10532 Andrea Spadaccini
      buf = buf[pos + 1:]
278 91c10532 Andrea Spadaccini
279 91c10532 Andrea Spadaccini
    return (message, buf)
280 91c10532 Andrea Spadaccini
281 91c10532 Andrea Spadaccini
  def _Recv(self):
282 91c10532 Andrea Spadaccini
    """Receives a message from QMP and decodes the received JSON object.
283 91c10532 Andrea Spadaccini

284 91c10532 Andrea Spadaccini
    @rtype: QmpMessage
285 91c10532 Andrea Spadaccini
    @return: the received message
286 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
287 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
288 91c10532 Andrea Spadaccini

289 91c10532 Andrea Spadaccini
    """
290 91c10532 Andrea Spadaccini
    self._check_connection()
291 91c10532 Andrea Spadaccini
292 91c10532 Andrea Spadaccini
    # Check if there is already a message in the buffer
293 91c10532 Andrea Spadaccini
    (message, self._buf) = self._ParseMessage(self._buf)
294 91c10532 Andrea Spadaccini
    if message:
295 91c10532 Andrea Spadaccini
      return message
296 91c10532 Andrea Spadaccini
297 91c10532 Andrea Spadaccini
    recv_buffer = StringIO.StringIO(self._buf)
298 91c10532 Andrea Spadaccini
    recv_buffer.seek(len(self._buf))
299 91c10532 Andrea Spadaccini
    try:
300 91c10532 Andrea Spadaccini
      while True:
301 91c10532 Andrea Spadaccini
        data = self.sock.recv(4096)
302 91c10532 Andrea Spadaccini
        if not data:
303 91c10532 Andrea Spadaccini
          break
304 91c10532 Andrea Spadaccini
        recv_buffer.write(data)
305 91c10532 Andrea Spadaccini
306 91c10532 Andrea Spadaccini
        (message, self._buf) = self._ParseMessage(recv_buffer.getvalue())
307 91c10532 Andrea Spadaccini
        if message:
308 91c10532 Andrea Spadaccini
          return message
309 91c10532 Andrea Spadaccini
310 91c10532 Andrea Spadaccini
    except socket.timeout, err:
311 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while receiving a QMP message: "
312 91c10532 Andrea Spadaccini
                                   "%s" % (err))
313 91c10532 Andrea Spadaccini
    except socket.error, err:
314 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to receive data from KVM using the"
315 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
316 91c10532 Andrea Spadaccini
317 91c10532 Andrea Spadaccini
  def _Send(self, message):
318 91c10532 Andrea Spadaccini
    """Encodes and sends a message to KVM using QMP.
319 91c10532 Andrea Spadaccini

320 91c10532 Andrea Spadaccini
    @type message: QmpMessage
321 91c10532 Andrea Spadaccini
    @param message: message to send to KVM
322 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
323 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
324 91c10532 Andrea Spadaccini

325 91c10532 Andrea Spadaccini
    """
326 91c10532 Andrea Spadaccini
    self._check_connection()
327 91c10532 Andrea Spadaccini
    try:
328 91c10532 Andrea Spadaccini
      message_str = str(message)
329 91c10532 Andrea Spadaccini
    except Exception, err:
330 91c10532 Andrea Spadaccini
      raise errors.ProgrammerError("QMP data deserialization error: %s" % err)
331 91c10532 Andrea Spadaccini
332 91c10532 Andrea Spadaccini
    try:
333 91c10532 Andrea Spadaccini
      self.sock.sendall(message_str)
334 91c10532 Andrea Spadaccini
    except socket.timeout, err:
335 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Timeout while sending a QMP message: "
336 91c10532 Andrea Spadaccini
                                   "%s (%s)" % (err.string, err.errno))
337 91c10532 Andrea Spadaccini
    except socket.error, err:
338 91c10532 Andrea Spadaccini
      raise errors.HypervisorError("Unable to send data from KVM using the"
339 91c10532 Andrea Spadaccini
                                   " QMP protocol: %s" % err)
340 91c10532 Andrea Spadaccini
341 91c10532 Andrea Spadaccini
  def Execute(self, command, arguments=None):
342 91c10532 Andrea Spadaccini
    """Executes a QMP command and returns the response of the server.
343 91c10532 Andrea Spadaccini

344 91c10532 Andrea Spadaccini
    @type command: str
345 91c10532 Andrea Spadaccini
    @param command: the command to execute
346 91c10532 Andrea Spadaccini
    @type arguments: dict
347 91c10532 Andrea Spadaccini
    @param arguments: dictionary of arguments to be passed to the command
348 91c10532 Andrea Spadaccini
    @rtype: dict
349 91c10532 Andrea Spadaccini
    @return: dictionary representing the received JSON object
350 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
351 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
352 91c10532 Andrea Spadaccini

353 91c10532 Andrea Spadaccini
    """
354 91c10532 Andrea Spadaccini
    self._check_connection()
355 91c10532 Andrea Spadaccini
    message = QmpMessage({self._EXECUTE_KEY: command})
356 91c10532 Andrea Spadaccini
    if arguments:
357 91c10532 Andrea Spadaccini
      message[self._ARGUMENTS_KEY] = arguments
358 91c10532 Andrea Spadaccini
    self._Send(message)
359 91c10532 Andrea Spadaccini
360 91c10532 Andrea Spadaccini
    # Events can occur between the sending of the command and the reception
361 91c10532 Andrea Spadaccini
    # of the response, so we need to filter out messages with the event key.
362 91c10532 Andrea Spadaccini
    while True:
363 91c10532 Andrea Spadaccini
      response = self._Recv()
364 91c10532 Andrea Spadaccini
      err = response[self._ERROR_KEY]
365 91c10532 Andrea Spadaccini
      if err:
366 91c10532 Andrea Spadaccini
        raise errors.HypervisorError("kvm: error executing the %s"
367 91c10532 Andrea Spadaccini
                                     " command: %s (%s, %s):" %
368 91c10532 Andrea Spadaccini
                                     (command,
369 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DESC_KEY],
370 91c10532 Andrea Spadaccini
                                      err[self._ERROR_CLASS_KEY],
371 91c10532 Andrea Spadaccini
                                      err[self._ERROR_DATA_KEY]))
372 91c10532 Andrea Spadaccini
373 91c10532 Andrea Spadaccini
      elif not response[self._EVENT_KEY]:
374 91c10532 Andrea Spadaccini
        return response
375 91c10532 Andrea Spadaccini
376 91c10532 Andrea Spadaccini
377 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
378 c4469f75 Guido Trotter
  """KVM hypervisor interface"""
379 d271c6fd Iustin Pop
  CAN_MIGRATE = True
380 eb58f9b1 Guido Trotter
381 eb58f9b1 Guido Trotter
  _ROOT_DIR = constants.RUN_GANETI_DIR + "/kvm-hypervisor"
382 a1d79fc6 Guido Trotter
  _PIDS_DIR = _ROOT_DIR + "/pid" # contains live instances pids
383 7548396c Guido Trotter
  _UIDS_DIR = _ROOT_DIR + "/uid" # contains instances reserved uids
384 a1d79fc6 Guido Trotter
  _CTRL_DIR = _ROOT_DIR + "/ctrl" # contains instances control sockets
385 a1d79fc6 Guido Trotter
  _CONF_DIR = _ROOT_DIR + "/conf" # contains instances startup data
386 5d9bfd87 Apollon Oikonomopoulos
  _NICS_DIR = _ROOT_DIR + "/nic" # contains instances nic <-> tap associations
387 4f580fef Sébastien Bocahu
  _KEYMAP_DIR = _ROOT_DIR + "/keymap" # contains instances keymaps
388 547a63b7 Balazs Lecz
  # KVM instances with chroot enabled are started in empty chroot directories.
389 547a63b7 Balazs Lecz
  _CHROOT_DIR = _ROOT_DIR + "/chroot" # for empty chroot directories
390 547a63b7 Balazs Lecz
  # After an instance is stopped, its chroot directory is removed.
391 547a63b7 Balazs Lecz
  # If the chroot directory is not empty, it can't be removed.
392 547a63b7 Balazs Lecz
  # A non-empty chroot directory indicates a possible security incident.
393 547a63b7 Balazs Lecz
  # To support forensics, the non-empty chroot directory is quarantined in
394 547a63b7 Balazs Lecz
  # a separate directory, called 'chroot-quarantine'.
395 547a63b7 Balazs Lecz
  _CHROOT_QUARANTINE_DIR = _ROOT_DIR + "/chroot-quarantine"
396 5d9bfd87 Apollon Oikonomopoulos
  _DIRS = [_ROOT_DIR, _PIDS_DIR, _UIDS_DIR, _CTRL_DIR, _CONF_DIR, _NICS_DIR,
397 547a63b7 Balazs Lecz
           _CHROOT_DIR, _CHROOT_QUARANTINE_DIR]
398 eb58f9b1 Guido Trotter
399 205ab586 Iustin Pop
  PARAMETERS = {
400 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK,
401 205ab586 Iustin Pop
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
402 205ab586 Iustin Pop
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
403 205ab586 Iustin Pop
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
404 205ab586 Iustin Pop
    constants.HV_ACPI: hv_base.NO_CHECK,
405 205ab586 Iustin Pop
    constants.HV_SERIAL_CONSOLE: hv_base.NO_CHECK,
406 d73ef63f Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS:
407 8b312c1d Manuel Franceschini
      (False, lambda x: (netutils.IP4Address.IsValid(x) or
408 8b312c1d Manuel Franceschini
                         utils.IsNormAbsPath(x)),
409 d73ef63f Michael Hanselmann
       "the VNC bind address must be either a valid IP address or an absolute"
410 d73ef63f Michael Hanselmann
       " pathname", None, None),
411 205ab586 Iustin Pop
    constants.HV_VNC_TLS: hv_base.NO_CHECK,
412 205ab586 Iustin Pop
    constants.HV_VNC_X509: hv_base.OPT_DIR_CHECK,
413 205ab586 Iustin Pop
    constants.HV_VNC_X509_VERIFY: hv_base.NO_CHECK,
414 6e6bb8d5 Guido Trotter
    constants.HV_VNC_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
415 b1cb62bd Andrea Spadaccini
    constants.HV_KVM_SPICE_BIND: hv_base.NO_CHECK, # will be checked later
416 b1cb62bd Andrea Spadaccini
    constants.HV_KVM_SPICE_IP_VERSION:
417 b1cb62bd Andrea Spadaccini
      (False, lambda x: (x == constants.IFACE_NO_IP_VERSION_SPECIFIED or
418 b1cb62bd Andrea Spadaccini
                         x in constants.VALID_IP_VERSIONS),
419 b1cb62bd Andrea Spadaccini
       "the SPICE IP version should be 4 or 6",
420 b1cb62bd Andrea Spadaccini
       None, None),
421 b451c4c7 Andrea Spadaccini
    constants.HV_KVM_SPICE_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
422 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR:
423 ea064d24 Andrea Spadaccini
      hv_base.ParamInSet(False,
424 ea064d24 Andrea Spadaccini
        constants.HT_KVM_SPICE_VALID_LOSSLESS_IMG_COMPR_OPTIONS),
425 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_JPEG_IMG_COMPR:
426 ea064d24 Andrea Spadaccini
      hv_base.ParamInSet(False,
427 ea064d24 Andrea Spadaccini
        constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
428 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR:
429 ea064d24 Andrea Spadaccini
      hv_base.ParamInSet(False,
430 ea064d24 Andrea Spadaccini
        constants.HT_KVM_SPICE_VALID_LOSSY_IMG_COMPR_OPTIONS),
431 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION:
432 ea064d24 Andrea Spadaccini
      hv_base.ParamInSet(False,
433 ea064d24 Andrea Spadaccini
        constants.HT_KVM_SPICE_VALID_VIDEO_STREAM_DETECTION_OPTIONS),
434 ea064d24 Andrea Spadaccini
    constants.HV_KVM_SPICE_AUDIO_COMPR: hv_base.NO_CHECK,
435 cc130cc7 Marco Casavecchia
    constants.HV_KVM_FLOPPY_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
436 205ab586 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
437 cc130cc7 Marco Casavecchia
    constants.HV_KVM_CDROM2_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
438 d73ef63f Michael Hanselmann
    constants.HV_BOOT_ORDER:
439 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
440 d73ef63f Michael Hanselmann
    constants.HV_NIC_TYPE:
441 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
442 d73ef63f Michael Hanselmann
    constants.HV_DISK_TYPE:
443 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
444 cc130cc7 Marco Casavecchia
    constants.HV_KVM_CDROM_DISK_TYPE:
445 cc130cc7 Marco Casavecchia
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_DISK_TYPES),
446 d73ef63f Michael Hanselmann
    constants.HV_USB_MOUSE:
447 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
448 4f580fef Sébastien Bocahu
    constants.HV_KEYMAP: hv_base.NO_CHECK,
449 e2d14329 Andrea Spadaccini
    constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
450 e43d4f9f Apollon Oikonomopoulos
    constants.HV_MIGRATION_BANDWIDTH: hv_base.NO_CHECK,
451 e43d4f9f Apollon Oikonomopoulos
    constants.HV_MIGRATION_DOWNTIME: hv_base.NO_CHECK,
452 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
453 6b970cef Jun Futagawa
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
454 19572932 Iustin Pop
    constants.HV_DISK_CACHE:
455 19572932 Iustin Pop
      hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
456 d19d94db Guido Trotter
    constants.HV_SECURITY_MODEL:
457 d19d94db Guido Trotter
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_SM_TYPES),
458 d19d94db Guido Trotter
    constants.HV_SECURITY_DOMAIN: hv_base.NO_CHECK,
459 7ba594c0 Guido Trotter
    constants.HV_KVM_FLAG:
460 7ba594c0 Guido Trotter
      hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES),
461 fbe27e2b Guido Trotter
    constants.HV_VHOST_NET: hv_base.NO_CHECK,
462 547a63b7 Balazs Lecz
    constants.HV_KVM_USE_CHROOT: hv_base.NO_CHECK,
463 4f958b0b Miguel Di Ciurcio Filho
    constants.HV_MEM_PATH: hv_base.OPT_DIR_CHECK,
464 990ade2d Stephen Shirley
    constants.HV_REBOOT_BEHAVIOR:
465 990ade2d Stephen Shirley
      hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS)
466 205ab586 Iustin Pop
    }
467 6b5605e8 Iustin Pop
468 d0c8c01d Iustin Pop
  _MIGRATION_STATUS_RE = re.compile("Migration\s+status:\s+(\w+)",
469 30e42c4e Guido Trotter
                                    re.M | re.I)
470 c4e388a5 Guido Trotter
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
471 c4e388a5 Guido Trotter
  _MIGRATION_INFO_RETRY_DELAY = 2
472 30e42c4e Guido Trotter
473 b52d85c1 Guido Trotter
  _VERSION_RE = re.compile(r"\b(\d+)\.(\d+)\.(\d+)\b")
474 b52d85c1 Guido Trotter
475 64bfbc08 Guido Trotter
  ANCILLARY_FILES = [
476 64bfbc08 Guido Trotter
    _KVM_NETWORK_SCRIPT,
477 64bfbc08 Guido Trotter
    ]
478 69ab2e12 Guido Trotter
  ANCILLARY_FILES_OPT = [
479 69ab2e12 Guido Trotter
    _KVM_NETWORK_SCRIPT,
480 69ab2e12 Guido Trotter
    ]
481 64bfbc08 Guido Trotter
482 eb58f9b1 Guido Trotter
  def __init__(self):
483 eb58f9b1 Guido Trotter
    hv_base.BaseHypervisor.__init__(self)
484 eb58f9b1 Guido Trotter
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
485 eb58f9b1 Guido Trotter
    # in a tmpfs filesystem or has been otherwise wiped out.
486 29921401 Iustin Pop
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
487 9afb67fe Guido Trotter
    utils.EnsureDirs(dirs)
488 eb58f9b1 Guido Trotter
489 30786fc9 Iustin Pop
  @classmethod
490 30786fc9 Iustin Pop
  def _InstancePidFile(cls, instance_name):
491 98ec75d6 Iustin Pop
    """Returns the instance pidfile.
492 98ec75d6 Iustin Pop

493 98ec75d6 Iustin Pop
    """
494 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
495 98ec75d6 Iustin Pop
496 263b8de6 Guido Trotter
  @classmethod
497 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
498 7548396c Guido Trotter
    """Returns the instance uidfile.
499 7548396c Guido Trotter

500 7548396c Guido Trotter
    """
501 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
502 7548396c Guido Trotter
503 7548396c Guido Trotter
  @classmethod
504 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
505 263b8de6 Guido Trotter
    """Check pid file for instance information.
506 263b8de6 Guido Trotter

507 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
508 263b8de6 Guido Trotter
    information from its command line.
509 263b8de6 Guido Trotter

510 263b8de6 Guido Trotter
    @type pid: string or int
511 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
512 263b8de6 Guido Trotter
    @rtype: tuple
513 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
514 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
515 263b8de6 Guido Trotter

516 263b8de6 Guido Trotter
    """
517 263b8de6 Guido Trotter
    alive = utils.IsProcessAlive(pid)
518 263b8de6 Guido Trotter
    if not alive:
519 263b8de6 Guido Trotter
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
520 263b8de6 Guido Trotter
521 263b8de6 Guido Trotter
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
522 263b8de6 Guido Trotter
    try:
523 263b8de6 Guido Trotter
      cmdline = utils.ReadFile(cmdline_file)
524 263b8de6 Guido Trotter
    except EnvironmentError, err:
525 263b8de6 Guido Trotter
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
526 263b8de6 Guido Trotter
                                   (pid, err))
527 263b8de6 Guido Trotter
528 263b8de6 Guido Trotter
    instance = None
529 263b8de6 Guido Trotter
    memory = 0
530 263b8de6 Guido Trotter
    vcpus = 0
531 263b8de6 Guido Trotter
532 d0c8c01d Iustin Pop
    arg_list = cmdline.split("\x00")
533 263b8de6 Guido Trotter
    while arg_list:
534 e687ec01 Michael Hanselmann
      arg = arg_list.pop(0)
535 263b8de6 Guido Trotter
      if arg == "-name":
536 263b8de6 Guido Trotter
        instance = arg_list.pop(0)
537 263b8de6 Guido Trotter
      elif arg == "-m":
538 263b8de6 Guido Trotter
        memory = int(arg_list.pop(0))
539 263b8de6 Guido Trotter
      elif arg == "-smp":
540 263b8de6 Guido Trotter
        vcpus = int(arg_list.pop(0))
541 263b8de6 Guido Trotter
542 263b8de6 Guido Trotter
    if instance is None:
543 263b8de6 Guido Trotter
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
544 263b8de6 Guido Trotter
                                   " instance" % pid)
545 263b8de6 Guido Trotter
546 263b8de6 Guido Trotter
    return (instance, memory, vcpus)
547 263b8de6 Guido Trotter
548 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
549 263b8de6 Guido Trotter
    """Returns the instance pidfile, pid, and liveness.
550 263b8de6 Guido Trotter

551 263b8de6 Guido Trotter
    @type instance_name: string
552 263b8de6 Guido Trotter
    @param instance_name: instance name
553 263b8de6 Guido Trotter
    @rtype: tuple
554 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
555 1f8b3a27 Guido Trotter

556 1f8b3a27 Guido Trotter
    """
557 98ec75d6 Iustin Pop
    pidfile = self._InstancePidFile(instance_name)
558 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
559 263b8de6 Guido Trotter
560 263b8de6 Guido Trotter
    alive = False
561 263b8de6 Guido Trotter
    try:
562 263b8de6 Guido Trotter
      cmd_instance = self._InstancePidInfo(pid)[0]
563 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
564 263b8de6 Guido Trotter
    except errors.HypervisorError:
565 263b8de6 Guido Trotter
      pass
566 1f8b3a27 Guido Trotter
567 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
568 1f8b3a27 Guido Trotter
569 5905901c Iustin Pop
  def _CheckDown(self, instance_name):
570 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
571 5905901c Iustin Pop

572 5905901c Iustin Pop
    """
573 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
574 5905901c Iustin Pop
    if alive:
575 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
576 5905901c Iustin Pop
                                   (instance_name, "already running"))
577 5905901c Iustin Pop
578 0df4d98a Guido Trotter
  @classmethod
579 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
580 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
581 c4fbefc8 Guido Trotter

582 c4fbefc8 Guido Trotter
    """
583 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
584 c4fbefc8 Guido Trotter
585 0df4d98a Guido Trotter
  @classmethod
586 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
587 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
588 c4fbefc8 Guido Trotter

589 c4fbefc8 Guido Trotter
    """
590 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
591 c4fbefc8 Guido Trotter
592 91c10532 Andrea Spadaccini
  @classmethod
593 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
594 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
595 91c10532 Andrea Spadaccini

596 91c10532 Andrea Spadaccini
    """
597 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
598 91c10532 Andrea Spadaccini
599 86d6bc2a Guido Trotter
  @staticmethod
600 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
601 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
602 86d6bc2a Guido Trotter

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

605 86d6bc2a Guido Trotter
    """
606 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
607 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
608 86d6bc2a Guido Trotter
    else:
609 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
610 86d6bc2a Guido Trotter
611 0df4d98a Guido Trotter
  @classmethod
612 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
613 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
614 38e250ba Guido Trotter

615 38e250ba Guido Trotter
    """
616 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
617 38e250ba Guido Trotter
618 7e66c35b Guido Trotter
  @classmethod
619 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
620 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
621 547a63b7 Balazs Lecz

622 547a63b7 Balazs Lecz
    """
623 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
624 547a63b7 Balazs Lecz
625 547a63b7 Balazs Lecz
  @classmethod
626 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
627 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
628 5d9bfd87 Apollon Oikonomopoulos
    given instance.
629 5d9bfd87 Apollon Oikonomopoulos

630 5d9bfd87 Apollon Oikonomopoulos
    """
631 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
632 5d9bfd87 Apollon Oikonomopoulos
633 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
634 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
635 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
636 5d9bfd87 Apollon Oikonomopoulos

637 5d9bfd87 Apollon Oikonomopoulos
    """
638 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
639 5d9bfd87 Apollon Oikonomopoulos
640 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
641 4f580fef Sébastien Bocahu
  def _InstanceKeymapFile(cls, instance_name):
642 4f580fef Sébastien Bocahu
    """Returns the name of the file containing the keymap for a given instance
643 4f580fef Sébastien Bocahu

644 4f580fef Sébastien Bocahu
    """
645 4f580fef Sébastien Bocahu
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
646 4f580fef Sébastien Bocahu
647 4f580fef Sébastien Bocahu
  @classmethod
648 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
649 7548396c Guido Trotter
    """Try to read a uid file
650 7548396c Guido Trotter

651 7548396c Guido Trotter
    """
652 7548396c Guido Trotter
    if os.path.exists(uid_file):
653 7548396c Guido Trotter
      try:
654 682f7601 Guido Trotter
        uid = int(utils.ReadOneLineFile(uid_file))
655 aa0b600b Guido Trotter
        return uid
656 7548396c Guido Trotter
      except EnvironmentError:
657 7548396c Guido Trotter
        logging.warning("Can't read uid file", exc_info=True)
658 7548396c Guido Trotter
      except (TypeError, ValueError):
659 7548396c Guido Trotter
        logging.warning("Can't parse uid file contents", exc_info=True)
660 aa0b600b Guido Trotter
    return None
661 7548396c Guido Trotter
662 7548396c Guido Trotter
  @classmethod
663 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
664 547a63b7 Balazs Lecz
    """Removes an instance's rutime sockets/files/dirs.
665 7e66c35b Guido Trotter

666 7e66c35b Guido Trotter
    """
667 7e66c35b Guido Trotter
    utils.RemoveFile(pidfile)
668 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
669 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceSerial(instance_name))
670 91c10532 Andrea Spadaccini
    utils.RemoveFile(cls._InstanceQmpMonitor(instance_name))
671 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
672 4f580fef Sébastien Bocahu
    utils.RemoveFile(cls._InstanceKeymapFile(instance_name))
673 7548396c Guido Trotter
    uid_file = cls._InstanceUidFile(instance_name)
674 7548396c Guido Trotter
    uid = cls._TryReadUidFile(uid_file)
675 7548396c Guido Trotter
    utils.RemoveFile(uid_file)
676 7548396c Guido Trotter
    if uid is not None:
677 7548396c Guido Trotter
      uidpool.ReleaseUid(uid)
678 7be85163 Guido Trotter
    try:
679 7be85163 Guido Trotter
      shutil.rmtree(cls._InstanceNICDir(instance_name))
680 7be85163 Guido Trotter
    except OSError, err:
681 7be85163 Guido Trotter
      if err.errno != errno.ENOENT:
682 7be85163 Guido Trotter
        raise
683 547a63b7 Balazs Lecz
    try:
684 547a63b7 Balazs Lecz
      chroot_dir = cls._InstanceChrootDir(instance_name)
685 547a63b7 Balazs Lecz
      utils.RemoveDir(chroot_dir)
686 547a63b7 Balazs Lecz
    except OSError, err:
687 547a63b7 Balazs Lecz
      if err.errno == errno.ENOTEMPTY:
688 547a63b7 Balazs Lecz
        # The chroot directory is expected to be empty, but it isn't.
689 547a63b7 Balazs Lecz
        new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
690 547a63b7 Balazs Lecz
                                          prefix="%s-%s-" %
691 547a63b7 Balazs Lecz
                                          (instance_name,
692 547a63b7 Balazs Lecz
                                           utils.TimestampForFilename()))
693 547a63b7 Balazs Lecz
        logging.warning("The chroot directory of instance %s can not be"
694 547a63b7 Balazs Lecz
                        " removed as it is not empty. Moving it to the"
695 547a63b7 Balazs Lecz
                        " quarantine instead. Please investigate the"
696 547a63b7 Balazs Lecz
                        " contents (%s) and clean up manually",
697 547a63b7 Balazs Lecz
                        instance_name, new_chroot_dir)
698 547a63b7 Balazs Lecz
        utils.RenameFile(chroot_dir, new_chroot_dir)
699 547a63b7 Balazs Lecz
      else:
700 547a63b7 Balazs Lecz
        raise
701 7e66c35b Guido Trotter
702 748e4b5a Michael Hanselmann
  @staticmethod
703 5d9bfd87 Apollon Oikonomopoulos
  def _ConfigureNIC(instance, seq, nic, tap):
704 5d9bfd87 Apollon Oikonomopoulos
    """Run the network configuration script for a specified NIC
705 eb58f9b1 Guido Trotter

706 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
707 eb58f9b1 Guido Trotter
    @type instance: instance object
708 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
709 eb58f9b1 Guido Trotter
    @type seq: int
710 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
711 eb58f9b1 Guido Trotter
    @type nic: nic object
712 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
713 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
714 eb58f9b1 Guido Trotter

715 eb58f9b1 Guido Trotter
    """
716 748e4b5a Michael Hanselmann
717 5d9bfd87 Apollon Oikonomopoulos
    if instance.tags:
718 5d9bfd87 Apollon Oikonomopoulos
      tags = " ".join(instance.tags)
719 5d9bfd87 Apollon Oikonomopoulos
    else:
720 5d9bfd87 Apollon Oikonomopoulos
      tags = ""
721 5d9bfd87 Apollon Oikonomopoulos
722 5d9bfd87 Apollon Oikonomopoulos
    env = {
723 5d9bfd87 Apollon Oikonomopoulos
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
724 5d9bfd87 Apollon Oikonomopoulos
      "INSTANCE": instance.name,
725 5d9bfd87 Apollon Oikonomopoulos
      "MAC": nic.mac,
726 5d9bfd87 Apollon Oikonomopoulos
      "MODE": nic.nicparams[constants.NIC_MODE],
727 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE": tap,
728 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE_INDEX": str(seq),
729 5d9bfd87 Apollon Oikonomopoulos
      "TAGS": tags,
730 5d9bfd87 Apollon Oikonomopoulos
    }
731 5d9bfd87 Apollon Oikonomopoulos
732 5d9bfd87 Apollon Oikonomopoulos
    if nic.ip:
733 5d9bfd87 Apollon Oikonomopoulos
      env["IP"] = nic.ip
734 5d9bfd87 Apollon Oikonomopoulos
735 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_LINK]:
736 5d9bfd87 Apollon Oikonomopoulos
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
737 5d9bfd87 Apollon Oikonomopoulos
738 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
739 5d9bfd87 Apollon Oikonomopoulos
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
740 5d9bfd87 Apollon Oikonomopoulos
741 5d9bfd87 Apollon Oikonomopoulos
    result = utils.RunCmd([constants.KVM_IFUP, tap], env=env)
742 5d9bfd87 Apollon Oikonomopoulos
    if result.failed:
743 5d9bfd87 Apollon Oikonomopoulos
      raise errors.HypervisorError("Failed to configure interface %s: %s."
744 5d9bfd87 Apollon Oikonomopoulos
                                   " Network configuration script output: %s" %
745 5d9bfd87 Apollon Oikonomopoulos
                                   (tap, result.fail_reason, result.output))
746 eb58f9b1 Guido Trotter
747 eb58f9b1 Guido Trotter
  def ListInstances(self):
748 eb58f9b1 Guido Trotter
    """Get the list of running instances.
749 eb58f9b1 Guido Trotter

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

753 eb58f9b1 Guido Trotter
    """
754 eb58f9b1 Guido Trotter
    result = []
755 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
756 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
757 eb58f9b1 Guido Trotter
        result.append(name)
758 eb58f9b1 Guido Trotter
    return result
759 eb58f9b1 Guido Trotter
760 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
761 eb58f9b1 Guido Trotter
    """Get instance properties.
762 eb58f9b1 Guido Trotter

763 4fbb3c60 Guido Trotter
    @type instance_name: string
764 c41eea6e Iustin Pop
    @param instance_name: the instance name
765 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
766 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
767 eb58f9b1 Guido Trotter

768 eb58f9b1 Guido Trotter
    """
769 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
770 1f8b3a27 Guido Trotter
    if not alive:
771 eb58f9b1 Guido Trotter
      return None
772 eb58f9b1 Guido Trotter
773 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
774 eb58f9b1 Guido Trotter
    stat = "---b-"
775 eb58f9b1 Guido Trotter
    times = "0"
776 eb58f9b1 Guido Trotter
777 eb58f9b1 Guido Trotter
    return (instance_name, pid, memory, vcpus, stat, times)
778 eb58f9b1 Guido Trotter
779 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
780 eb58f9b1 Guido Trotter
    """Get properties of all instances.
781 eb58f9b1 Guido Trotter

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

784 eb58f9b1 Guido Trotter
    """
785 eb58f9b1 Guido Trotter
    data = []
786 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
787 263b8de6 Guido Trotter
      try:
788 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
789 263b8de6 Guido Trotter
      except errors.HypervisorError:
790 263b8de6 Guido Trotter
        continue
791 263b8de6 Guido Trotter
      if info:
792 263b8de6 Guido Trotter
        data.append(info)
793 eb58f9b1 Guido Trotter
    return data
794 eb58f9b1 Guido Trotter
795 323f9095 Stephen Shirley
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused):
796 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
797 eb58f9b1 Guido Trotter

798 eb58f9b1 Guido Trotter
    """
799 0aee8ee9 Guido Trotter
    # pylint: disable=R0914
800 440351f8 Andrea Spadaccini
    _, v_major, v_min, _ = self._GetKVMVersion()
801 4304964a Guido Trotter
802 e687ec01 Michael Hanselmann
    pidfile = self._InstancePidFile(instance.name)
803 eb58f9b1 Guido Trotter
    kvm = constants.KVM_PATH
804 eb58f9b1 Guido Trotter
    kvm_cmd = [kvm]
805 c6a39fc2 Guido Trotter
    # used just by the vnc server, if enabled
806 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-name", instance.name])
807 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-m", instance.beparams[constants.BE_MEMORY]])
808 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-smp", instance.beparams[constants.BE_VCPUS]])
809 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-pidfile", pidfile])
810 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-daemonize"])
811 6b5605e8 Iustin Pop
    if not instance.hvparams[constants.HV_ACPI]:
812 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-no-acpi"])
813 323f9095 Stephen Shirley
    if startup_paused:
814 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-S"])
815 990ade2d Stephen Shirley
    if instance.hvparams[constants.HV_REBOOT_BEHAVIOR] == \
816 990ade2d Stephen Shirley
        constants.INSTANCE_REBOOT_EXIT:
817 990ade2d Stephen Shirley
      kvm_cmd.extend(["-no-reboot"])
818 eb58f9b1 Guido Trotter
819 a985b417 Iustin Pop
    hvp = instance.hvparams
820 835528af Iustin Pop
    boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
821 835528af Iustin Pop
    boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
822 cc130cc7 Marco Casavecchia
    boot_floppy = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_FLOPPY
823 835528af Iustin Pop
    boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
824 8745c3d7 Guido Trotter
825 b1cb62bd Andrea Spadaccini
    self.ValidateParameters(hvp)
826 b1cb62bd Andrea Spadaccini
827 7ba594c0 Guido Trotter
    if hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED:
828 7ba594c0 Guido Trotter
      kvm_cmd.extend(["-enable-kvm"])
829 7ba594c0 Guido Trotter
    elif hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED:
830 7ba594c0 Guido Trotter
      kvm_cmd.extend(["-disable-kvm"])
831 7ba594c0 Guido Trotter
832 8745c3d7 Guido Trotter
    if boot_network:
833 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-boot", "n"])
834 1213604d Guido Trotter
835 a985b417 Iustin Pop
    disk_type = hvp[constants.HV_DISK_TYPE]
836 1213604d Guido Trotter
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
837 d0c8c01d Iustin Pop
      if_val = ",if=virtio"
838 1213604d Guido Trotter
    else:
839 d0c8c01d Iustin Pop
      if_val = ",if=%s" % disk_type
840 19572932 Iustin Pop
    # Cache mode
841 19572932 Iustin Pop
    disk_cache = hvp[constants.HV_DISK_CACHE]
842 41e794f6 Apollon Oikonomopoulos
    if instance.disk_template in constants.DTS_EXT_MIRROR:
843 41e794f6 Apollon Oikonomopoulos
      if disk_cache != "none":
844 41e794f6 Apollon Oikonomopoulos
        # TODO: make this a hard error, instead of a silent overwrite
845 41e794f6 Apollon Oikonomopoulos
        logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
846 41e794f6 Apollon Oikonomopoulos
                        " to prevent shared storage corruption on migration",
847 41e794f6 Apollon Oikonomopoulos
                        disk_cache)
848 41e794f6 Apollon Oikonomopoulos
      cache_val = ",cache=none"
849 41e794f6 Apollon Oikonomopoulos
    elif disk_cache != constants.HT_CACHE_DEFAULT:
850 19572932 Iustin Pop
      cache_val = ",cache=%s" % disk_cache
851 19572932 Iustin Pop
    else:
852 19572932 Iustin Pop
      cache_val = ""
853 069cfbf1 Iustin Pop
    for cfdev, dev_path in block_devices:
854 d34b16d7 Iustin Pop
      if cfdev.mode != constants.DISK_RDWR:
855 d34b16d7 Iustin Pop
        raise errors.HypervisorError("Instance has read-only disks which"
856 d34b16d7 Iustin Pop
                                     " are not supported by KVM")
857 eb58f9b1 Guido Trotter
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
858 4304964a Guido Trotter
      boot_val = ""
859 66d5dbef Guido Trotter
      if boot_disk:
860 d0c8c01d Iustin Pop
        kvm_cmd.extend(["-boot", "c"])
861 66d5dbef Guido Trotter
        boot_disk = False
862 4304964a Guido Trotter
        if (v_major, v_min) < (0, 14) and disk_type != constants.HT_DISK_IDE:
863 4304964a Guido Trotter
          boot_val = ",boot=on"
864 eb58f9b1 Guido Trotter
865 d0c8c01d Iustin Pop
      drive_val = "file=%s,format=raw%s%s%s" % (dev_path, if_val, boot_val,
866 19572932 Iustin Pop
                                                cache_val)
867 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
868 eb58f9b1 Guido Trotter
869 cc130cc7 Marco Casavecchia
    #Now we can specify a different device type for CDROM devices.
870 cc130cc7 Marco Casavecchia
    cdrom_disk_type = hvp[constants.HV_KVM_CDROM_DISK_TYPE]
871 cc130cc7 Marco Casavecchia
    if not cdrom_disk_type:
872 cc130cc7 Marco Casavecchia
      cdrom_disk_type = disk_type
873 cc130cc7 Marco Casavecchia
874 a985b417 Iustin Pop
    iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
875 66d5dbef Guido Trotter
    if iso_image:
876 d0c8c01d Iustin Pop
      options = ",format=raw,media=cdrom"
877 66d5dbef Guido Trotter
      if boot_cdrom:
878 d0c8c01d Iustin Pop
        kvm_cmd.extend(["-boot", "d"])
879 cc130cc7 Marco Casavecchia
        if cdrom_disk_type != constants.HT_DISK_IDE:
880 d0c8c01d Iustin Pop
          options = "%s,boot=on,if=%s" % (options, constants.HT_DISK_IDE)
881 cc130cc7 Marco Casavecchia
        else:
882 d0c8c01d Iustin Pop
          options = "%s,boot=on" % options
883 9dd363eb Guido Trotter
      else:
884 cc130cc7 Marco Casavecchia
        if cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
885 d0c8c01d Iustin Pop
          if_val = ",if=virtio"
886 9cf4321f Apollon Oikonomopoulos
        else:
887 d0c8c01d Iustin Pop
          if_val = ",if=%s" % cdrom_disk_type
888 d0c8c01d Iustin Pop
        options = "%s%s" % (options, if_val)
889 d0c8c01d Iustin Pop
      drive_val = "file=%s%s" % (iso_image, options)
890 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
891 66d5dbef Guido Trotter
892 cc130cc7 Marco Casavecchia
    iso_image2 = hvp[constants.HV_KVM_CDROM2_IMAGE_PATH]
893 cc130cc7 Marco Casavecchia
    if iso_image2:
894 d0c8c01d Iustin Pop
      options = ",format=raw,media=cdrom"
895 cc130cc7 Marco Casavecchia
      if cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
896 d0c8c01d Iustin Pop
        if_val = ",if=virtio"
897 cc130cc7 Marco Casavecchia
      else:
898 d0c8c01d Iustin Pop
        if_val = ",if=%s" % cdrom_disk_type
899 d0c8c01d Iustin Pop
      options = "%s%s" % (options, if_val)
900 d0c8c01d Iustin Pop
      drive_val = "file=%s%s" % (iso_image2, options)
901 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
902 cc130cc7 Marco Casavecchia
903 cc130cc7 Marco Casavecchia
    floppy_image = hvp[constants.HV_KVM_FLOPPY_IMAGE_PATH]
904 cc130cc7 Marco Casavecchia
    if floppy_image:
905 d0c8c01d Iustin Pop
      options = ",format=raw,media=disk"
906 cc130cc7 Marco Casavecchia
      if boot_floppy:
907 d0c8c01d Iustin Pop
        kvm_cmd.extend(["-boot", "a"])
908 d0c8c01d Iustin Pop
        options = "%s,boot=on" % options
909 d0c8c01d Iustin Pop
      if_val = ",if=floppy"
910 d0c8c01d Iustin Pop
      options = "%s%s" % (options, if_val)
911 d0c8c01d Iustin Pop
      drive_val = "file=%s%s" % (floppy_image, options)
912 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
913 cc130cc7 Marco Casavecchia
914 a985b417 Iustin Pop
    kernel_path = hvp[constants.HV_KERNEL_PATH]
915 df5ab9f0 Guido Trotter
    if kernel_path:
916 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-kernel", kernel_path])
917 a985b417 Iustin Pop
      initrd_path = hvp[constants.HV_INITRD_PATH]
918 df5ab9f0 Guido Trotter
      if initrd_path:
919 d0c8c01d Iustin Pop
        kvm_cmd.extend(["-initrd", initrd_path])
920 d0c8c01d Iustin Pop
      root_append = ["root=%s" % hvp[constants.HV_ROOT_PATH],
921 07813a9e Iustin Pop
                     hvp[constants.HV_KERNEL_ARGS]]
922 07813a9e Iustin Pop
      if hvp[constants.HV_SERIAL_CONSOLE]:
923 d0c8c01d Iustin Pop
        root_append.append("console=ttyS0,38400")
924 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-append", " ".join(root_append)])
925 eb58f9b1 Guido Trotter
926 4f958b0b Miguel Di Ciurcio Filho
    mem_path = hvp[constants.HV_MEM_PATH]
927 4f958b0b Miguel Di Ciurcio Filho
    if mem_path:
928 9d3015f9 Guido Trotter
      kvm_cmd.extend(["-mem-path", mem_path, "-mem-prealloc"])
929 4f958b0b Miguel Di Ciurcio Filho
930 a985b417 Iustin Pop
    mouse_type = hvp[constants.HV_USB_MOUSE]
931 31f6f67a Guido Trotter
    vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
932 31f6f67a Guido Trotter
933 11344a50 Guido Trotter
    if mouse_type:
934 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-usb"])
935 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-usbdevice", mouse_type])
936 31f6f67a Guido Trotter
    elif vnc_bind_address:
937 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-usbdevice", constants.HT_MOUSE_TABLET])
938 11344a50 Guido Trotter
939 4f580fef Sébastien Bocahu
    keymap = hvp[constants.HV_KEYMAP]
940 4f580fef Sébastien Bocahu
    if keymap:
941 4f580fef Sébastien Bocahu
      keymap_path = self._InstanceKeymapFile(instance.name)
942 4f580fef Sébastien Bocahu
      # If a keymap file is specified, KVM won't use its internal defaults. By
943 4f580fef Sébastien Bocahu
      # first including the "en-us" layout, an error on loading the actual
944 4f580fef Sébastien Bocahu
      # layout (e.g. because it can't be found) won't lead to a non-functional
945 4f580fef Sébastien Bocahu
      # keyboard. A keyboard with incorrect keys is still better than none.
946 4f580fef Sébastien Bocahu
      utils.WriteFile(keymap_path, data="include en-us\ninclude %s\n" % keymap)
947 4f580fef Sébastien Bocahu
      kvm_cmd.extend(["-k", keymap_path])
948 4f580fef Sébastien Bocahu
949 8470c8db Guido Trotter
    if vnc_bind_address:
950 8b312c1d Manuel Franceschini
      if netutils.IP4Address.IsValid(vnc_bind_address):
951 377d74c9 Guido Trotter
        if instance.network_port > constants.VNC_BASE_PORT:
952 377d74c9 Guido Trotter
          display = instance.network_port - constants.VNC_BASE_PORT
953 14f5f1b6 Manuel Franceschini
          if vnc_bind_address == constants.IP4_ADDRESS_ANY:
954 d0c8c01d Iustin Pop
            vnc_arg = ":%d" % (display)
955 8447f52b Guido Trotter
          else:
956 d0c8c01d Iustin Pop
            vnc_arg = "%s:%d" % (vnc_bind_address, display)
957 8470c8db Guido Trotter
        else:
958 8447f52b Guido Trotter
          logging.error("Network port is not a valid VNC display (%d < %d)."
959 07b8a2b5 Iustin Pop
                        " Not starting VNC", instance.network_port,
960 07b8a2b5 Iustin Pop
                        constants.VNC_BASE_PORT)
961 d0c8c01d Iustin Pop
          vnc_arg = "none"
962 8b2d1013 Guido Trotter
963 8b2d1013 Guido Trotter
        # Only allow tls and other option when not binding to a file, for now.
964 8b2d1013 Guido Trotter
        # kvm/qemu gets confused otherwise about the filename to use.
965 d0c8c01d Iustin Pop
        vnc_append = ""
966 a985b417 Iustin Pop
        if hvp[constants.HV_VNC_TLS]:
967 d0c8c01d Iustin Pop
          vnc_append = "%s,tls" % vnc_append
968 a985b417 Iustin Pop
          if hvp[constants.HV_VNC_X509_VERIFY]:
969 d0c8c01d Iustin Pop
            vnc_append = "%s,x509verify=%s" % (vnc_append,
970 a985b417 Iustin Pop
                                               hvp[constants.HV_VNC_X509])
971 a985b417 Iustin Pop
          elif hvp[constants.HV_VNC_X509]:
972 d0c8c01d Iustin Pop
            vnc_append = "%s,x509=%s" % (vnc_append,
973 a985b417 Iustin Pop
                                         hvp[constants.HV_VNC_X509])
974 6e6bb8d5 Guido Trotter
        if hvp[constants.HV_VNC_PASSWORD_FILE]:
975 d0c8c01d Iustin Pop
          vnc_append = "%s,password" % vnc_append
976 6e6bb8d5 Guido Trotter
977 d0c8c01d Iustin Pop
        vnc_arg = "%s%s" % (vnc_arg, vnc_append)
978 8b2d1013 Guido Trotter
979 8470c8db Guido Trotter
      else:
980 d0c8c01d Iustin Pop
        vnc_arg = "unix:%s/%s.vnc" % (vnc_bind_address, instance.name)
981 8b2d1013 Guido Trotter
982 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-vnc", vnc_arg])
983 8470c8db Guido Trotter
    else:
984 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-nographic"])
985 8470c8db Guido Trotter
986 69b99987 Michael Hanselmann
    monitor_dev = ("unix:%s,server,nowait" %
987 69b99987 Michael Hanselmann
                   self._InstanceMonitor(instance.name))
988 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-monitor", monitor_dev])
989 a985b417 Iustin Pop
    if hvp[constants.HV_SERIAL_CONSOLE]:
990 d0c8c01d Iustin Pop
      serial_dev = ("unix:%s,server,nowait" %
991 a985b417 Iustin Pop
                    self._InstanceSerial(instance.name))
992 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-serial", serial_dev])
993 a2faf9ee Guido Trotter
    else:
994 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-serial", "none"])
995 eb58f9b1 Guido Trotter
996 b1cb62bd Andrea Spadaccini
    spice_bind = hvp[constants.HV_KVM_SPICE_BIND]
997 11ae7a0a Andrea Spadaccini
    spice_ip_version = None
998 b1cb62bd Andrea Spadaccini
    if spice_bind:
999 b1cb62bd Andrea Spadaccini
      if netutils.IsValidInterface(spice_bind):
1000 b1cb62bd Andrea Spadaccini
        # The user specified a network interface, we have to figure out the IP
1001 b1cb62bd Andrea Spadaccini
        # address.
1002 b1cb62bd Andrea Spadaccini
        addresses = netutils.GetInterfaceIpAddresses(spice_bind)
1003 b1cb62bd Andrea Spadaccini
        spice_ip_version = hvp[constants.HV_KVM_SPICE_IP_VERSION]
1004 b1cb62bd Andrea Spadaccini
1005 b1cb62bd Andrea Spadaccini
        # if the user specified an IP version and the interface does not
1006 b1cb62bd Andrea Spadaccini
        # have that kind of IP addresses, throw an exception
1007 b1cb62bd Andrea Spadaccini
        if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1008 b1cb62bd Andrea Spadaccini
          if not addresses[spice_ip_version]:
1009 b1cb62bd Andrea Spadaccini
            raise errors.HypervisorError("spice: unable to get an IPv%s address"
1010 b1cb62bd Andrea Spadaccini
                                         " for %s" % (spice_ip_version,
1011 b1cb62bd Andrea Spadaccini
                                                      spice_bind))
1012 b1cb62bd Andrea Spadaccini
1013 b1cb62bd Andrea Spadaccini
        # the user did not specify an IP version, we have to figure it out
1014 b1cb62bd Andrea Spadaccini
        elif (addresses[constants.IP4_VERSION] and
1015 b1cb62bd Andrea Spadaccini
              addresses[constants.IP6_VERSION]):
1016 b1cb62bd Andrea Spadaccini
          # we have both ipv4 and ipv6, let's use the cluster default IP
1017 b1cb62bd Andrea Spadaccini
          # version
1018 b1cb62bd Andrea Spadaccini
          cluster_family = ssconf.SimpleStore().GetPrimaryIPFamily()
1019 b1cb62bd Andrea Spadaccini
          spice_ip_version = netutils.IPAddress.GetVersionFromAddressFamily(
1020 b1cb62bd Andrea Spadaccini
              cluster_family)
1021 b1cb62bd Andrea Spadaccini
        elif addresses[constants.IP4_VERSION]:
1022 b1cb62bd Andrea Spadaccini
          spice_ip_version = constants.IP4_VERSION
1023 b845c8a1 Andrea Spadaccini
        elif addresses[constants.IP6_VERSION]:
1024 b1cb62bd Andrea Spadaccini
          spice_ip_version = constants.IP6_VERSION
1025 b845c8a1 Andrea Spadaccini
        else:
1026 b845c8a1 Andrea Spadaccini
          raise errors.HypervisorError("spice: unable to get an IP address"
1027 b845c8a1 Andrea Spadaccini
                                       " for %s" % (spice_bind))
1028 b1cb62bd Andrea Spadaccini
1029 b1cb62bd Andrea Spadaccini
        spice_address = addresses[spice_ip_version][0]
1030 b1cb62bd Andrea Spadaccini
1031 b1cb62bd Andrea Spadaccini
      else:
1032 b1cb62bd Andrea Spadaccini
        # spice_bind is known to be a valid IP address, because
1033 b1cb62bd Andrea Spadaccini
        # ValidateParameters checked it.
1034 b1cb62bd Andrea Spadaccini
        spice_address = spice_bind
1035 b1cb62bd Andrea Spadaccini
1036 9849cec7 Guido Trotter
      spice_arg = "addr=%s,port=%s" % (spice_address, instance.network_port)
1037 b451c4c7 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]:
1038 b451c4c7 Andrea Spadaccini
        spice_arg = "%s,disable-ticketing" % spice_arg
1039 b451c4c7 Andrea Spadaccini
1040 11ae7a0a Andrea Spadaccini
      if spice_ip_version:
1041 11ae7a0a Andrea Spadaccini
        spice_arg = "%s,ipv%s" % (spice_arg, spice_ip_version)
1042 b1cb62bd Andrea Spadaccini
1043 ea064d24 Andrea Spadaccini
      # Image compression options
1044 ea064d24 Andrea Spadaccini
      img_lossless = hvp[constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR]
1045 ea064d24 Andrea Spadaccini
      img_jpeg = hvp[constants.HV_KVM_SPICE_JPEG_IMG_COMPR]
1046 ea064d24 Andrea Spadaccini
      img_zlib_glz = hvp[constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR]
1047 ea064d24 Andrea Spadaccini
      if img_lossless:
1048 ea064d24 Andrea Spadaccini
        spice_arg = "%s,image-compression=%s" % (spice_arg, img_lossless)
1049 ea064d24 Andrea Spadaccini
      if img_jpeg:
1050 ea064d24 Andrea Spadaccini
        spice_arg = "%s,jpeg-wan-compression=%s" % (spice_arg, img_jpeg)
1051 ea064d24 Andrea Spadaccini
      if img_zlib_glz:
1052 ea064d24 Andrea Spadaccini
        spice_arg = "%s,zlib-glz-wan-compression=%s" % (spice_arg, img_zlib_glz)
1053 ea064d24 Andrea Spadaccini
1054 ea064d24 Andrea Spadaccini
      # Video stream detection
1055 ea064d24 Andrea Spadaccini
      video_streaming = hvp[constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION]
1056 ea064d24 Andrea Spadaccini
      if video_streaming:
1057 ea064d24 Andrea Spadaccini
        spice_arg = "%s,streaming-video=%s" % (spice_arg, video_streaming)
1058 ea064d24 Andrea Spadaccini
1059 ea064d24 Andrea Spadaccini
      # Audio compression, by default in qemu-kvm it is on
1060 ea064d24 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_AUDIO_COMPR]:
1061 ea064d24 Andrea Spadaccini
        spice_arg = "%s,playback-compression=off" % spice_arg
1062 ea064d24 Andrea Spadaccini
1063 b1cb62bd Andrea Spadaccini
      logging.info("KVM: SPICE will listen on port %s", instance.network_port)
1064 b1cb62bd Andrea Spadaccini
      kvm_cmd.extend(["-spice", spice_arg])
1065 b1cb62bd Andrea Spadaccini
1066 2ebdfbb5 Andrea Spadaccini
      # Tell kvm to use the paravirtualized graphic card, optimized for SPICE
1067 2ebdfbb5 Andrea Spadaccini
      kvm_cmd.extend(["-vga", "qxl"])
1068 2ebdfbb5 Andrea Spadaccini
1069 6b970cef Jun Futagawa
    if hvp[constants.HV_USE_LOCALTIME]:
1070 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-localtime"])
1071 6b970cef Jun Futagawa
1072 547a63b7 Balazs Lecz
    if hvp[constants.HV_KVM_USE_CHROOT]:
1073 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-chroot", self._InstanceChrootDir(instance.name)])
1074 547a63b7 Balazs Lecz
1075 ee5f20b0 Guido Trotter
    # Save the current instance nics, but defer their expansion as parameters,
1076 ee5f20b0 Guido Trotter
    # as we'll need to generate executable temp files for them.
1077 ee5f20b0 Guido Trotter
    kvm_nics = instance.nics
1078 a985b417 Iustin Pop
    hvparams = hvp
1079 ee5f20b0 Guido Trotter
1080 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
1081 ee5f20b0 Guido Trotter
1082 38e250ba Guido Trotter
  def _WriteKVMRuntime(self, instance_name, data):
1083 38e250ba Guido Trotter
    """Write an instance's KVM runtime
1084 38e250ba Guido Trotter

1085 38e250ba Guido Trotter
    """
1086 38e250ba Guido Trotter
    try:
1087 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1088 38e250ba Guido Trotter
                      data=data)
1089 90c024f6 Guido Trotter
    except EnvironmentError, err:
1090 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1091 38e250ba Guido Trotter
1092 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
1093 38e250ba Guido Trotter
    """Read an instance's KVM runtime
1094 38e250ba Guido Trotter

1095 38e250ba Guido Trotter
    """
1096 38e250ba Guido Trotter
    try:
1097 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1098 90c024f6 Guido Trotter
    except EnvironmentError, err:
1099 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1100 38e250ba Guido Trotter
    return file_content
1101 38e250ba Guido Trotter
1102 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1103 38e250ba Guido Trotter
    """Save an instance's KVM runtime
1104 38e250ba Guido Trotter

1105 38e250ba Guido Trotter
    """
1106 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
1107 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1108 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
1109 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
1110 38e250ba Guido Trotter
1111 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1112 38e250ba Guido Trotter
    """Load an instance's KVM runtime
1113 38e250ba Guido Trotter

1114 38e250ba Guido Trotter
    """
1115 30e42c4e Guido Trotter
    if not serialized_runtime:
1116 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1117 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
1118 c2672466 Guido Trotter
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
1119 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
1120 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
1121 38e250ba Guido Trotter
1122 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1123 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
1124 76431533 Guido Trotter

1125 76431533 Guido Trotter
    @type name: string
1126 76431533 Guido Trotter
    @param name: instance name
1127 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1128 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1129 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1130 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1131 76431533 Guido Trotter

1132 76431533 Guido Trotter
    """
1133 5d9bfd87 Apollon Oikonomopoulos
    try:
1134 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1135 5d9bfd87 Apollon Oikonomopoulos
    finally:
1136 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
1137 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
1138 5d9bfd87 Apollon Oikonomopoulos
1139 76431533 Guido Trotter
    if result.failed:
1140 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1141 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
1142 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
1143 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
1144 76431533 Guido Trotter
1145 30e42c4e Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
1146 ee5f20b0 Guido Trotter
    """Execute a KVM cmd, after completing it with some last minute data
1147 ee5f20b0 Guido Trotter

1148 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1149 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1150 30e42c4e Guido Trotter

1151 ee5f20b0 Guido Trotter
    """
1152 297e6e53 Guido Trotter
    # Small _ExecuteKVMRuntime hv parameters programming howto:
1153 297e6e53 Guido Trotter
    #  - conf_hvp contains the parameters as configured on ganeti. they might
1154 297e6e53 Guido Trotter
    #    have changed since the instance started; only use them if the change
1155 297e6e53 Guido Trotter
    #    won't affect the inside of the instance (which hasn't been rebooted).
1156 297e6e53 Guido Trotter
    #  - up_hvp contains the parameters as they were when the instance was
1157 297e6e53 Guido Trotter
    #    started, plus any new parameter which has been added between ganeti
1158 297e6e53 Guido Trotter
    #    versions: it is paramount that those default to a value which won't
1159 297e6e53 Guido Trotter
    #    affect the inside of the instance as well.
1160 297e6e53 Guido Trotter
    conf_hvp = instance.hvparams
1161 5905901c Iustin Pop
    name = instance.name
1162 5905901c Iustin Pop
    self._CheckDown(name)
1163 ee5f20b0 Guido Trotter
1164 ee5f20b0 Guido Trotter
    temp_files = []
1165 ee5f20b0 Guido Trotter
1166 297e6e53 Guido Trotter
    kvm_cmd, kvm_nics, up_hvp = kvm_runtime
1167 297e6e53 Guido Trotter
    up_hvp = objects.FillDict(conf_hvp, up_hvp)
1168 ee5f20b0 Guido Trotter
1169 440351f8 Andrea Spadaccini
    _, v_major, v_min, _ = self._GetKVMVersion()
1170 4b784cf8 Miguel Di Ciurcio Filho
1171 297e6e53 Guido Trotter
    # We know it's safe to run as a different user upon migration, so we'll use
1172 297e6e53 Guido Trotter
    # the latest conf, from conf_hvp.
1173 297e6e53 Guido Trotter
    security_model = conf_hvp[constants.HV_SECURITY_MODEL]
1174 cef34868 Guido Trotter
    if security_model == constants.HT_SM_USER:
1175 297e6e53 Guido Trotter
      kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
1176 cef34868 Guido Trotter
1177 297e6e53 Guido Trotter
    # We have reasons to believe changing something like the nic driver/type
1178 297e6e53 Guido Trotter
    # upon migration won't exactly fly with the instance kernel, so for nic
1179 297e6e53 Guido Trotter
    # related parameters we'll use up_hvp
1180 5d9bfd87 Apollon Oikonomopoulos
    tapfds = []
1181 5d9bfd87 Apollon Oikonomopoulos
    taps = []
1182 ee5f20b0 Guido Trotter
    if not kvm_nics:
1183 fbe27e2b Guido Trotter
      kvm_cmd.extend(["-net", "none"])
1184 ee5f20b0 Guido Trotter
    else:
1185 5d9bfd87 Apollon Oikonomopoulos
      vnet_hdr = False
1186 fbe27e2b Guido Trotter
      tap_extra = ""
1187 297e6e53 Guido Trotter
      nic_type = up_hvp[constants.HV_NIC_TYPE]
1188 37f88dc6 Guido Trotter
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
1189 4b784cf8 Miguel Di Ciurcio Filho
        # From version 0.12.0, kvm uses a new sintax for network configuration.
1190 049383d9 Adeodato Simo
        if (v_major, v_min) >= (0, 12):
1191 4b784cf8 Miguel Di Ciurcio Filho
          nic_model = "virtio-net-pci"
1192 5d9bfd87 Apollon Oikonomopoulos
          vnet_hdr = True
1193 4b784cf8 Miguel Di Ciurcio Filho
        else:
1194 4b784cf8 Miguel Di Ciurcio Filho
          nic_model = "virtio"
1195 4b784cf8 Miguel Di Ciurcio Filho
1196 297e6e53 Guido Trotter
        if up_hvp[constants.HV_VHOST_NET]:
1197 4b784cf8 Miguel Di Ciurcio Filho
          # vhost_net is only available from version 0.13.0 or newer
1198 049383d9 Adeodato Simo
          if (v_major, v_min) >= (0, 13):
1199 4b784cf8 Miguel Di Ciurcio Filho
            tap_extra = ",vhost=on"
1200 4b784cf8 Miguel Di Ciurcio Filho
          else:
1201 4b784cf8 Miguel Di Ciurcio Filho
            raise errors.HypervisorError("vhost_net is configured"
1202 4b784cf8 Miguel Di Ciurcio Filho
                                        " but it is not available")
1203 37f88dc6 Guido Trotter
      else:
1204 4b784cf8 Miguel Di Ciurcio Filho
        nic_model = nic_type
1205 37f88dc6 Guido Trotter
1206 ee5f20b0 Guido Trotter
      for nic_seq, nic in enumerate(kvm_nics):
1207 5d9bfd87 Apollon Oikonomopoulos
        tapname, tapfd = _OpenTap(vnet_hdr)
1208 5d9bfd87 Apollon Oikonomopoulos
        tapfds.append(tapfd)
1209 5d9bfd87 Apollon Oikonomopoulos
        taps.append(tapname)
1210 049383d9 Adeodato Simo
        if (v_major, v_min) >= (0, 12):
1211 4b784cf8 Miguel Di Ciurcio Filho
          nic_val = "%s,mac=%s,netdev=netdev%s" % (nic_model, nic.mac, nic_seq)
1212 5d9bfd87 Apollon Oikonomopoulos
          tap_val = "type=tap,id=netdev%s,fd=%d%s" % (nic_seq, tapfd, tap_extra)
1213 4b784cf8 Miguel Di Ciurcio Filho
          kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
1214 4b784cf8 Miguel Di Ciurcio Filho
        else:
1215 049383d9 Adeodato Simo
          nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq,
1216 049383d9 Adeodato Simo
                                                         nic.mac, nic_model)
1217 5d9bfd87 Apollon Oikonomopoulos
          tap_val = "tap,vlan=%s,fd=%d" % (nic_seq, tapfd)
1218 4b784cf8 Miguel Di Ciurcio Filho
          kvm_cmd.extend(["-net", tap_val, "-net", nic_val])
1219 ee5f20b0 Guido Trotter
1220 30e42c4e Guido Trotter
    if incoming:
1221 30e42c4e Guido Trotter
      target, port = incoming
1222 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-incoming", "tcp:%s:%s" % (target, port)])
1223 30e42c4e Guido Trotter
1224 297e6e53 Guido Trotter
    # Changing the vnc password doesn't bother the guest that much. At most it
1225 297e6e53 Guido Trotter
    # will surprise people who connect to it. Whether positively or negatively
1226 297e6e53 Guido Trotter
    # it's debatable.
1227 297e6e53 Guido Trotter
    vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
1228 6e6bb8d5 Guido Trotter
    vnc_pwd = None
1229 6e6bb8d5 Guido Trotter
    if vnc_pwd_file:
1230 6e6bb8d5 Guido Trotter
      try:
1231 682f7601 Guido Trotter
        vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
1232 6e6bb8d5 Guido Trotter
      except EnvironmentError, err:
1233 6e6bb8d5 Guido Trotter
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
1234 6e6bb8d5 Guido Trotter
                                     % (vnc_pwd_file, err))
1235 6e6bb8d5 Guido Trotter
1236 297e6e53 Guido Trotter
    if conf_hvp[constants.HV_KVM_USE_CHROOT]:
1237 547a63b7 Balazs Lecz
      utils.EnsureDirs([(self._InstanceChrootDir(name),
1238 547a63b7 Balazs Lecz
                         constants.SECURE_DIR_MODE)])
1239 547a63b7 Balazs Lecz
1240 91c10532 Andrea Spadaccini
    # Automatically enable QMP if version is >= 0.14
1241 91c10532 Andrea Spadaccini
    if (v_major, v_min) >= (0, 14):
1242 91c10532 Andrea Spadaccini
      logging.debug("Enabling QMP")
1243 91c10532 Andrea Spadaccini
      kvm_cmd.extend(["-qmp", "unix:%s,server,nowait" %
1244 91c10532 Andrea Spadaccini
                    self._InstanceQmpMonitor(instance.name)])
1245 91c10532 Andrea Spadaccini
1246 cc8a8ed7 Apollon Oikonomopoulos
    # Configure the network now for starting instances and bridged interfaces,
1247 cc8a8ed7 Apollon Oikonomopoulos
    # during FinalizeMigration for incoming instances' routed interfaces
1248 cc8a8ed7 Apollon Oikonomopoulos
    for nic_seq, nic in enumerate(kvm_nics):
1249 cc8a8ed7 Apollon Oikonomopoulos
      if (incoming and
1250 cc8a8ed7 Apollon Oikonomopoulos
          nic.nicparams[constants.NIC_MODE] != constants.NIC_MODE_BRIDGED):
1251 cc8a8ed7 Apollon Oikonomopoulos
        continue
1252 cc8a8ed7 Apollon Oikonomopoulos
      self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
1253 5d9bfd87 Apollon Oikonomopoulos
1254 76431533 Guido Trotter
    if security_model == constants.HT_SM_POOL:
1255 76431533 Guido Trotter
      ss = ssconf.SimpleStore()
1256 76431533 Guido Trotter
      uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
1257 76431533 Guido Trotter
      all_uids = set(uidpool.ExpandUidPool(uid_pool))
1258 76431533 Guido Trotter
      uid = uidpool.RequestUnusedUid(all_uids)
1259 76431533 Guido Trotter
      try:
1260 76431533 Guido Trotter
        username = pwd.getpwuid(uid.GetUid()).pw_name
1261 76431533 Guido Trotter
        kvm_cmd.extend(["-runas", username])
1262 5d9bfd87 Apollon Oikonomopoulos
        self._RunKVMCmd(name, kvm_cmd, tapfds)
1263 76431533 Guido Trotter
      except:
1264 76431533 Guido Trotter
        uidpool.ReleaseUid(uid)
1265 76431533 Guido Trotter
        raise
1266 76431533 Guido Trotter
      else:
1267 76431533 Guido Trotter
        uid.Unlock()
1268 3af16328 Apollon Oikonomopoulos
        utils.WriteFile(self._InstanceUidFile(name), data=uid.AsStr())
1269 76431533 Guido Trotter
    else:
1270 5d9bfd87 Apollon Oikonomopoulos
      self._RunKVMCmd(name, kvm_cmd, tapfds)
1271 5d9bfd87 Apollon Oikonomopoulos
1272 5d9bfd87 Apollon Oikonomopoulos
    utils.EnsureDirs([(self._InstanceNICDir(instance.name),
1273 5d9bfd87 Apollon Oikonomopoulos
                     constants.RUN_DIRS_MODE)])
1274 5d9bfd87 Apollon Oikonomopoulos
    for nic_seq, tap in enumerate(taps):
1275 5d9bfd87 Apollon Oikonomopoulos
      utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
1276 5d9bfd87 Apollon Oikonomopoulos
                      data=tap)
1277 eb58f9b1 Guido Trotter
1278 6e6bb8d5 Guido Trotter
    if vnc_pwd:
1279 d0c8c01d Iustin Pop
      change_cmd = "change vnc password %s" % vnc_pwd
1280 6e6bb8d5 Guido Trotter
      self._CallMonitorCommand(instance.name, change_cmd)
1281 6e6bb8d5 Guido Trotter
1282 b451c4c7 Andrea Spadaccini
    # Setting SPICE password. We are not vulnerable to malicious passwordless
1283 b451c4c7 Andrea Spadaccini
    # connection attempts because SPICE by default does not allow connections
1284 b451c4c7 Andrea Spadaccini
    # if neither a password nor the "disable_ticketing" options are specified.
1285 b451c4c7 Andrea Spadaccini
    # As soon as we send the password via QMP, that password is a valid ticket
1286 b451c4c7 Andrea Spadaccini
    # for connection.
1287 b451c4c7 Andrea Spadaccini
    spice_password_file = conf_hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]
1288 b451c4c7 Andrea Spadaccini
    if spice_password_file:
1289 b451c4c7 Andrea Spadaccini
      try:
1290 b451c4c7 Andrea Spadaccini
        spice_pwd = utils.ReadOneLineFile(spice_password_file, strict=True)
1291 b451c4c7 Andrea Spadaccini
        qmp = QmpConnection(self._InstanceQmpMonitor(instance.name))
1292 b451c4c7 Andrea Spadaccini
        qmp.connect()
1293 b451c4c7 Andrea Spadaccini
        arguments = {
1294 b451c4c7 Andrea Spadaccini
            "protocol": "spice",
1295 b451c4c7 Andrea Spadaccini
            "password": spice_pwd,
1296 b451c4c7 Andrea Spadaccini
        }
1297 b451c4c7 Andrea Spadaccini
        qmp.Execute("set_password", arguments)
1298 b451c4c7 Andrea Spadaccini
      except EnvironmentError, err:
1299 b451c4c7 Andrea Spadaccini
        raise errors.HypervisorError("Failed to open SPICE password file %s: %s"
1300 b451c4c7 Andrea Spadaccini
                                     % (spice_password_file, err))
1301 b451c4c7 Andrea Spadaccini
1302 08137f9e Iustin Pop
    for filename in temp_files:
1303 08137f9e Iustin Pop
      utils.RemoveFile(filename)
1304 eb58f9b1 Guido Trotter
1305 323f9095 Stephen Shirley
  def StartInstance(self, instance, block_devices, startup_paused):
1306 ee5f20b0 Guido Trotter
    """Start an instance.
1307 ee5f20b0 Guido Trotter

1308 ee5f20b0 Guido Trotter
    """
1309 5905901c Iustin Pop
    self._CheckDown(instance.name)
1310 7238edb5 Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1311 7238edb5 Iustin Pop
                                           startup_paused)
1312 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1313 ee5f20b0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
1314 ee5f20b0 Guido Trotter
1315 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
1316 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
1317 6567aff3 Guido Trotter

1318 6567aff3 Guido Trotter
    """
1319 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1320 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
1321 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
1322 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1323 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
1324 6567aff3 Guido Trotter
    if result.failed:
1325 6567aff3 Guido Trotter
      msg = ("Failed to send command '%s' to instance %s."
1326 6567aff3 Guido Trotter
             " output: %s, error: %s, fail_reason: %s" %
1327 9798fcae Guido Trotter
             (command, instance_name,
1328 9798fcae Guido Trotter
              result.stdout, result.stderr, result.fail_reason))
1329 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
1330 6567aff3 Guido Trotter
1331 6567aff3 Guido Trotter
    return result
1332 6567aff3 Guido Trotter
1333 b52d85c1 Guido Trotter
  @classmethod
1334 b52d85c1 Guido Trotter
  def _GetKVMVersion(cls):
1335 d7e4a2b1 Andrea Spadaccini
    """Return the installed KVM version.
1336 b52d85c1 Guido Trotter

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

1340 b52d85c1 Guido Trotter
    """
1341 b52d85c1 Guido Trotter
    result = utils.RunCmd([constants.KVM_PATH, "--help"])
1342 b52d85c1 Guido Trotter
    if result.failed:
1343 440351f8 Andrea Spadaccini
      raise errors.HypervisorError("Unable to get KVM version")
1344 b52d85c1 Guido Trotter
    match = cls._VERSION_RE.search(result.output.splitlines()[0])
1345 b52d85c1 Guido Trotter
    if not match:
1346 440351f8 Andrea Spadaccini
      raise errors.HypervisorError("Unable to get KVM version")
1347 3f2eba25 Miguel Di Ciurcio Filho
1348 3f2eba25 Miguel Di Ciurcio Filho
    return (match.group(0), int(match.group(1)), int(match.group(2)),
1349 3f2eba25 Miguel Di Ciurcio Filho
            int(match.group(3)))
1350 b52d85c1 Guido Trotter
1351 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
1352 eb58f9b1 Guido Trotter
    """Stop an instance.
1353 eb58f9b1 Guido Trotter

1354 eb58f9b1 Guido Trotter
    """
1355 bbcf7ad0 Iustin Pop
    if name is not None and not force:
1356 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
1357 bbcf7ad0 Iustin Pop
    if name is None:
1358 bbcf7ad0 Iustin Pop
      name = instance.name
1359 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
1360 bbcf7ad0 Iustin Pop
    else:
1361 bbcf7ad0 Iustin Pop
      acpi = False
1362 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
1363 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
1364 bbcf7ad0 Iustin Pop
      if force or not acpi:
1365 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
1366 eb58f9b1 Guido Trotter
      else:
1367 d0c8c01d Iustin Pop
        self._CallMonitorCommand(name, "system_powerdown")
1368 eb58f9b1 Guido Trotter
1369 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
1370 8904b35c Guido Trotter
    """Cleanup after a stopped instance
1371 8904b35c Guido Trotter

1372 8904b35c Guido Trotter
    """
1373 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1374 8904b35c Guido Trotter
    if pid > 0 and alive:
1375 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
1376 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1377 eb58f9b1 Guido Trotter
1378 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
1379 eb58f9b1 Guido Trotter
    """Reboot an instance.
1380 eb58f9b1 Guido Trotter

1381 eb58f9b1 Guido Trotter
    """
1382 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
1383 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
1384 eb58f9b1 Guido Trotter
    # to shutdown and restart.
1385 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
1386 1f8b3a27 Guido Trotter
    if not alive:
1387 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
1388 78411c60 Iustin Pop
                                   " not running" % instance.name)
1389 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
1390 f02881e0 Guido Trotter
    # ...first load it...
1391 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
1392 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
1393 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
1394 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
1395 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
1396 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1397 f02881e0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
1398 eb58f9b1 Guido Trotter
1399 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
1400 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
1401 30e42c4e Guido Trotter

1402 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1403 30e42c4e Guido Trotter
    @param instance: instance to be migrated
1404 30e42c4e Guido Trotter
    @rtype: string
1405 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
1406 30e42c4e Guido Trotter

1407 30e42c4e Guido Trotter
    """
1408 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
1409 30e42c4e Guido Trotter
1410 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
1411 30e42c4e Guido Trotter
    """Prepare to accept an instance.
1412 30e42c4e Guido Trotter

1413 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1414 30e42c4e Guido Trotter
    @param instance: instance to be accepted
1415 30e42c4e Guido Trotter
    @type info: string
1416 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
1417 30e42c4e Guido Trotter
    @type target: string
1418 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
1419 30e42c4e Guido Trotter

1420 30e42c4e Guido Trotter
    """
1421 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1422 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1423 30e42c4e Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
1424 30e42c4e Guido Trotter
1425 30e42c4e Guido Trotter
  def FinalizeMigration(self, instance, info, success):
1426 30e42c4e Guido Trotter
    """Finalize an instance migration.
1427 30e42c4e Guido Trotter

1428 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
1429 30e42c4e Guido Trotter

1430 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1431 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
1432 30e42c4e Guido Trotter

1433 30e42c4e Guido Trotter
    """
1434 30e42c4e Guido Trotter
    if success:
1435 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1436 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
1437 5d9bfd87 Apollon Oikonomopoulos
1438 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
1439 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1440 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
1441 cc8a8ed7 Apollon Oikonomopoulos
          continue
1442 5d9bfd87 Apollon Oikonomopoulos
        try:
1443 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
1444 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
1445 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
1446 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
1447 5d9bfd87 Apollon Oikonomopoulos
          continue
1448 5d9bfd87 Apollon Oikonomopoulos
        try:
1449 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
1450 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
1451 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
1452 5d9bfd87 Apollon Oikonomopoulos
1453 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
1454 30e42c4e Guido Trotter
    else:
1455 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
1456 30e42c4e Guido Trotter
1457 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
1458 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
1459 30e42c4e Guido Trotter

1460 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
1461 30e42c4e Guido Trotter
    currently running.
1462 30e42c4e Guido Trotter

1463 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
1464 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
1465 30e42c4e Guido Trotter
    @type target: string
1466 30e42c4e Guido Trotter
    @param target: ip address of the target node
1467 30e42c4e Guido Trotter
    @type live: boolean
1468 30e42c4e Guido Trotter
    @param live: perform a live migration
1469 30e42c4e Guido Trotter

1470 30e42c4e Guido Trotter
    """
1471 58d38b02 Iustin Pop
    instance_name = instance.name
1472 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
1473 30e42c4e Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1474 30e42c4e Guido Trotter
    if not alive:
1475 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
1476 30e42c4e Guido Trotter
1477 30e42c4e Guido Trotter
    if not live:
1478 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
1479 30e42c4e Guido Trotter
1480 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
1481 e43d4f9f Apollon Oikonomopoulos
        instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1482 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
1483 e43d4f9f Apollon Oikonomopoulos
1484 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
1485 e43d4f9f Apollon Oikonomopoulos
        instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
1486 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
1487 e43d4f9f Apollon Oikonomopoulos
1488 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
1489 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
1490 30e42c4e Guido Trotter
1491 d0c8c01d Iustin Pop
    info_command = "info migrate"
1492 30e42c4e Guido Trotter
    done = False
1493 c4e388a5 Guido Trotter
    broken_answers = 0
1494 30e42c4e Guido Trotter
    while not done:
1495 30e42c4e Guido Trotter
      result = self._CallMonitorCommand(instance_name, info_command)
1496 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
1497 30e42c4e Guido Trotter
      if not match:
1498 c4e388a5 Guido Trotter
        broken_answers += 1
1499 c4e388a5 Guido Trotter
        if not result.stdout:
1500 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
1501 c4e388a5 Guido Trotter
        else:
1502 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
1503 c4e388a5 Guido Trotter
                          result.stdout)
1504 c4e388a5 Guido Trotter
        time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1505 30e42c4e Guido Trotter
      else:
1506 30e42c4e Guido Trotter
        status = match.group(1)
1507 d0c8c01d Iustin Pop
        if status == "completed":
1508 30e42c4e Guido Trotter
          done = True
1509 d0c8c01d Iustin Pop
        elif status == "active":
1510 c4e388a5 Guido Trotter
          # reset the broken answers count
1511 c4e388a5 Guido Trotter
          broken_answers = 0
1512 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1513 d0c8c01d Iustin Pop
        elif status == "failed" or status == "cancelled":
1514 c087266c Guido Trotter
          if not live:
1515 c087266c Guido Trotter
            self._CallMonitorCommand(instance_name, 'cont')
1516 c087266c Guido Trotter
          raise errors.HypervisorError("Migration %s at the kvm level" %
1517 c087266c Guido Trotter
                                       status)
1518 30e42c4e Guido Trotter
        else:
1519 c4e388a5 Guido Trotter
          logging.warning("KVM: unknown migration status '%s'", status)
1520 c4e388a5 Guido Trotter
          broken_answers += 1
1521 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1522 c4e388a5 Guido Trotter
      if broken_answers >= self._MIGRATION_INFO_MAX_BAD_ANSWERS:
1523 c4e388a5 Guido Trotter
        raise errors.HypervisorError("Too many 'info migrate' broken answers")
1524 30e42c4e Guido Trotter
1525 30e42c4e Guido Trotter
    utils.KillProcess(pid)
1526 7b381438 Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1527 30e42c4e Guido Trotter
1528 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
1529 eb58f9b1 Guido Trotter
    """Return information about the node.
1530 eb58f9b1 Guido Trotter

1531 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
1532 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
1533 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
1534 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
1535 34fbc862 Andrea Spadaccini
          - hv_version: the hypervisor version in the form (major, minor,
1536 34fbc862 Andrea Spadaccini
                        revision)
1537 eb58f9b1 Guido Trotter

1538 eb58f9b1 Guido Trotter
    """
1539 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
1540 34fbc862 Andrea Spadaccini
    _, v_major, v_min, v_rev = self._GetKVMVersion()
1541 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
1542 34fbc862 Andrea Spadaccini
    return result
1543 eb58f9b1 Guido Trotter
1544 637ce7f9 Guido Trotter
  @classmethod
1545 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
1546 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
1547 eb58f9b1 Guido Trotter

1548 eb58f9b1 Guido Trotter
    """
1549 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
1550 2f4c951e Stephen Shirley
      cmd = [constants.KVM_CONSOLE_WRAPPER,
1551 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
1552 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
1553 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
1554 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
1555 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
1556 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
1557 55cc0a44 Michael Hanselmann
                                     host=instance.primary_node,
1558 55cc0a44 Michael Hanselmann
                                     user=constants.GANETI_RUNAS,
1559 55cc0a44 Michael Hanselmann
                                     command=cmd)
1560 3be34f57 Guido Trotter
1561 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
1562 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
1563 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
1564 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
1565 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
1566 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
1567 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
1568 55cc0a44 Michael Hanselmann
                                     display=display)
1569 55cc0a44 Michael Hanselmann
1570 4d2cdb5a Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
1571 4d2cdb5a Andrea Spadaccini
    if spice_bind:
1572 4d2cdb5a Andrea Spadaccini
      return objects.InstanceConsole(instance=instance.name,
1573 4d2cdb5a Andrea Spadaccini
                                     kind=constants.CONS_SPICE,
1574 4d2cdb5a Andrea Spadaccini
                                     host=spice_bind,
1575 4d2cdb5a Andrea Spadaccini
                                     port=instance.network_port)
1576 4d2cdb5a Andrea Spadaccini
1577 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
1578 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
1579 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
1580 55cc0a44 Michael Hanselmann
                                            instance.name))
1581 eb58f9b1 Guido Trotter
1582 eb58f9b1 Guido Trotter
  def Verify(self):
1583 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
1584 eb58f9b1 Guido Trotter

1585 eb58f9b1 Guido Trotter
    Check that the binary exists.
1586 eb58f9b1 Guido Trotter

1587 eb58f9b1 Guido Trotter
    """
1588 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
1589 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
1590 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
1591 14aa53cb Guido Trotter
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
1592 14aa53cb Guido Trotter
1593 6b5605e8 Iustin Pop
  @classmethod
1594 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
1595 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
1596 6b5605e8 Iustin Pop

1597 6b5605e8 Iustin Pop
    @type hvparams:  dict
1598 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
1599 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
1600 6b5605e8 Iustin Pop

1601 6b5605e8 Iustin Pop
    """
1602 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
1603 6b5605e8 Iustin Pop
1604 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
1605 df5ab9f0 Guido Trotter
    if kernel_path:
1606 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
1607 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
1608 205ab586 Iustin Pop
                                     " if a kernel is defined")
1609 6b5605e8 Iustin Pop
1610 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
1611 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
1612 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
1613 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
1614 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
1615 66d5dbef Guido Trotter
1616 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
1617 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
1618 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
1619 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
1620 835528af Iustin Pop
                                   " ISO path")
1621 f5118ade Iustin Pop
1622 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
1623 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
1624 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
1625 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
1626 d19d94db Guido Trotter
                                     " must be specified")
1627 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
1628 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
1629 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
1630 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
1631 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
1632 d19d94db Guido Trotter
1633 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
1634 b451c4c7 Andrea Spadaccini
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
1635 b1cb62bd Andrea Spadaccini
    if spice_bind:
1636 b1cb62bd Andrea Spadaccini
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1637 b1cb62bd Andrea Spadaccini
        # if an IP version is specified, the spice_bind parameter must be an
1638 b1cb62bd Andrea Spadaccini
        # IP of that family
1639 b1cb62bd Andrea Spadaccini
        if (netutils.IP4Address.IsValid(spice_bind) and
1640 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP4_VERSION):
1641 b1cb62bd Andrea Spadaccini
          raise errors.HypervisorError("spice: got an IPv4 address (%s), but"
1642 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
1643 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
1644 b1cb62bd Andrea Spadaccini
1645 b1cb62bd Andrea Spadaccini
        if (netutils.IP6Address.IsValid(spice_bind) and
1646 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP6_VERSION):
1647 b1cb62bd Andrea Spadaccini
          raise errors.HypervisorError("spice: got an IPv6 address (%s), but"
1648 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
1649 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
1650 b451c4c7 Andrea Spadaccini
    else:
1651 0e1b03b9 Andrea Spadaccini
      # All the other SPICE parameters depend on spice_bind being set. Raise an
1652 0e1b03b9 Andrea Spadaccini
      # error if any of them is set without it.
1653 0e1b03b9 Andrea Spadaccini
      spice_additional_params = frozenset([
1654 0e1b03b9 Andrea Spadaccini
        constants.HV_KVM_SPICE_IP_VERSION,
1655 0e1b03b9 Andrea Spadaccini
        constants.HV_KVM_SPICE_PASSWORD_FILE,
1656 ea064d24 Andrea Spadaccini
        constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR,
1657 ea064d24 Andrea Spadaccini
        constants.HV_KVM_SPICE_JPEG_IMG_COMPR,
1658 ea064d24 Andrea Spadaccini
        constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR,
1659 ea064d24 Andrea Spadaccini
        constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION,
1660 0e1b03b9 Andrea Spadaccini
        ])
1661 0e1b03b9 Andrea Spadaccini
      for param in spice_additional_params:
1662 0e1b03b9 Andrea Spadaccini
        if hvparams[param]:
1663 0e1b03b9 Andrea Spadaccini
          raise errors.HypervisorError("spice: %s requires %s to be set" %
1664 0e1b03b9 Andrea Spadaccini
                                       (param, constants.HV_KVM_SPICE_BIND))
1665 b1cb62bd Andrea Spadaccini
1666 d19d94db Guido Trotter
  @classmethod
1667 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
1668 d19d94db Guido Trotter
    """Check the given parameters for validity.
1669 d19d94db Guido Trotter

1670 d19d94db Guido Trotter
    @type hvparams:  dict
1671 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
1672 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
1673 d19d94db Guido Trotter

1674 d19d94db Guido Trotter
    """
1675 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
1676 d19d94db Guido Trotter
1677 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
1678 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
1679 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
1680 d19d94db Guido Trotter
      try:
1681 1feb39ec Guido Trotter
        pwd.getpwnam(username)
1682 d19d94db Guido Trotter
      except KeyError:
1683 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
1684 d19d94db Guido Trotter
                                     % username)
1685 d19d94db Guido Trotter
1686 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
1687 b1cb62bd Andrea Spadaccini
    if spice_bind:
1688 b1cb62bd Andrea Spadaccini
      # only one of VNC and SPICE can be used currently.
1689 b1cb62bd Andrea Spadaccini
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
1690 b1cb62bd Andrea Spadaccini
        raise errors.HypervisorError("both SPICE and VNC are configured, but"
1691 b1cb62bd Andrea Spadaccini
                                     " only one of them can be used at a"
1692 b1cb62bd Andrea Spadaccini
                                     " given time.")
1693 b1cb62bd Andrea Spadaccini
1694 b1cb62bd Andrea Spadaccini
      # KVM version should be >= 0.14.0
1695 b1cb62bd Andrea Spadaccini
      _, v_major, v_min, _ = cls._GetKVMVersion()
1696 b1cb62bd Andrea Spadaccini
      if (v_major, v_min) < (0, 14):
1697 b1cb62bd Andrea Spadaccini
        raise errors.HypervisorError("spice is configured, but it is not"
1698 b1cb62bd Andrea Spadaccini
                                     " available in versions of KVM < 0.14")
1699 b1cb62bd Andrea Spadaccini
1700 b1cb62bd Andrea Spadaccini
      # if spice_bind is not an IP address, it must be a valid interface
1701 b1cb62bd Andrea Spadaccini
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind)
1702 b1cb62bd Andrea Spadaccini
                       or netutils.IP6Address.IsValid(spice_bind))
1703 b1cb62bd Andrea Spadaccini
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
1704 b1cb62bd Andrea Spadaccini
        raise errors.HypervisorError("spice: the %s parameter must be either"
1705 b1cb62bd Andrea Spadaccini
                                     " a valid IP address or interface name" %
1706 b1cb62bd Andrea Spadaccini
                                     constants.HV_KVM_SPICE_BIND)
1707 b1cb62bd Andrea Spadaccini
1708 f5118ade Iustin Pop
  @classmethod
1709 f5118ade Iustin Pop
  def PowercycleNode(cls):
1710 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
1711 f5118ade Iustin Pop

1712 f5118ade Iustin Pop
    """
1713 f5118ade Iustin Pop
    cls.LinuxPowercycle()