Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 95a74ef3

History | View | Annotate | Download (80.8 kB)

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

24 eb58f9b1 Guido Trotter
"""
25 eb58f9b1 Guido Trotter
26 547a63b7 Balazs Lecz
import errno
27 eb58f9b1 Guido Trotter
import os
28 eb58f9b1 Guido Trotter
import os.path
29 eb58f9b1 Guido Trotter
import re
30 eb58f9b1 Guido Trotter
import tempfile
31 6567aff3 Guido Trotter
import time
32 30e42c4e Guido Trotter
import logging
33 d19d94db Guido Trotter
import pwd
34 199b2053 Apollon Oikonomopoulos
import struct
35 199b2053 Apollon Oikonomopoulos
import fcntl
36 5d9bfd87 Apollon Oikonomopoulos
import shutil
37 91c10532 Andrea Spadaccini
import socket
38 fc84cd5d Guido Trotter
import stat
39 91c10532 Andrea Spadaccini
import StringIO
40 1642a1d0 Dimitris Aragiorgis
import fdsend
41 2435f63b Dimitris Aragiorgis
from bitarray import bitarray
42 b693125f Tsachy Shacham
try:
43 471a31b6 Andrea Spadaccini
  import affinity   # pylint: disable=F0401
44 b693125f Tsachy Shacham
except ImportError:
45 b693125f Tsachy Shacham
  affinity = None
46 eb58f9b1 Guido Trotter
47 eb58f9b1 Guido Trotter
from ganeti import utils
48 eb58f9b1 Guido Trotter
from ganeti import constants
49 eb58f9b1 Guido Trotter
from ganeti import errors
50 38e250ba Guido Trotter
from ganeti import serializer
51 38e250ba Guido Trotter
from ganeti import objects
52 76431533 Guido Trotter
from ganeti import uidpool
53 76431533 Guido Trotter
from ganeti import ssconf
54 eb58f9b1 Guido Trotter
from ganeti.hypervisor import hv_base
55 a744b676 Manuel Franceschini
from ganeti import netutils
56 5d9bfd87 Apollon Oikonomopoulos
from ganeti.utils import wrapper as utils_wrapper
57 eb58f9b1 Guido Trotter
58 eb58f9b1 Guido Trotter
59 748e4b5a Michael Hanselmann
_KVM_NETWORK_SCRIPT = constants.SYSCONFDIR + "/ganeti/kvm-vif-bridge"
60 b693125f Tsachy Shacham
_KVM_START_PAUSED_FLAG = "-S"
61 748e4b5a Michael Hanselmann
62 199b2053 Apollon Oikonomopoulos
# TUN/TAP driver constants, taken from <linux/if_tun.h>
63 199b2053 Apollon Oikonomopoulos
# They are architecture-independent and already hardcoded in qemu-kvm source,
64 199b2053 Apollon Oikonomopoulos
# so we can safely include them here.
65 199b2053 Apollon Oikonomopoulos
TUNSETIFF = 0x400454ca
66 199b2053 Apollon Oikonomopoulos
TUNGETIFF = 0x800454d2
67 199b2053 Apollon Oikonomopoulos
TUNGETFEATURES = 0x800454cf
68 199b2053 Apollon Oikonomopoulos
IFF_TAP = 0x0002
69 199b2053 Apollon Oikonomopoulos
IFF_NO_PI = 0x1000
70 199b2053 Apollon Oikonomopoulos
IFF_VNET_HDR = 0x4000
71 199b2053 Apollon Oikonomopoulos
72 2435f63b Dimitris Aragiorgis
FREE = bitarray("0")
73 199b2053 Apollon Oikonomopoulos
74 199b2053 Apollon Oikonomopoulos
def _ProbeTapVnetHdr(fd):
75 199b2053 Apollon Oikonomopoulos
  """Check whether to enable the IFF_VNET_HDR flag.
76 199b2053 Apollon Oikonomopoulos

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

87 199b2053 Apollon Oikonomopoulos
   @type fd: int
88 199b2053 Apollon Oikonomopoulos
   @param fd: the file descriptor of /dev/net/tun
89 199b2053 Apollon Oikonomopoulos

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

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

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

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

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

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

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

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

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

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

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

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

216 91c10532 Andrea Spadaccini
    @type monitor_filename: string
217 91c10532 Andrea Spadaccini
    @param monitor_filename: the filename of the UNIX raw socket on which the
218 91c10532 Andrea Spadaccini
                             QMP monitor is listening
219 91c10532 Andrea Spadaccini

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

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

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

256 91c10532 Andrea Spadaccini
    @raise errors.HypervisorError: when there are communication errors
257 91c10532 Andrea Spadaccini
    @raise errors.ProgrammerError: when there are data serialization errors
258 91c10532 Andrea Spadaccini

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

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

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

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

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

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

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

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

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

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

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

539 98ec75d6 Iustin Pop
    """
540 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
541 98ec75d6 Iustin Pop
542 263b8de6 Guido Trotter
  @classmethod
543 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
544 7548396c Guido Trotter
    """Returns the instance uidfile.
545 7548396c Guido Trotter

546 7548396c Guido Trotter
    """
547 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
548 7548396c Guido Trotter
549 7548396c Guido Trotter
  @classmethod
550 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
551 263b8de6 Guido Trotter
    """Check pid file for instance information.
552 263b8de6 Guido Trotter

553 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
554 263b8de6 Guido Trotter
    information from its command line.
555 263b8de6 Guido Trotter

556 263b8de6 Guido Trotter
    @type pid: string or int
557 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
558 263b8de6 Guido Trotter
    @rtype: tuple
559 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
560 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
561 263b8de6 Guido Trotter

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

597 263b8de6 Guido Trotter
    @type instance_name: string
598 263b8de6 Guido Trotter
    @param instance_name: instance name
599 263b8de6 Guido Trotter
    @rtype: tuple
600 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
601 1f8b3a27 Guido Trotter

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

618 5905901c Iustin Pop
    """
619 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
620 5905901c Iustin Pop
    if alive:
621 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
622 5905901c Iustin Pop
                                   (instance_name, "already running"))
623 5905901c Iustin Pop
624 0df4d98a Guido Trotter
  @classmethod
625 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
626 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
627 c4fbefc8 Guido Trotter

628 c4fbefc8 Guido Trotter
    """
629 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
630 c4fbefc8 Guido Trotter
631 0df4d98a Guido Trotter
  @classmethod
632 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
633 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
634 c4fbefc8 Guido Trotter

635 c4fbefc8 Guido Trotter
    """
636 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
637 c4fbefc8 Guido Trotter
638 91c10532 Andrea Spadaccini
  @classmethod
639 91c10532 Andrea Spadaccini
  def _InstanceQmpMonitor(cls, instance_name):
640 91c10532 Andrea Spadaccini
    """Returns the instance serial QMP socket name
641 91c10532 Andrea Spadaccini

642 91c10532 Andrea Spadaccini
    """
643 91c10532 Andrea Spadaccini
    return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
644 91c10532 Andrea Spadaccini
645 86d6bc2a Guido Trotter
  @staticmethod
646 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
647 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
648 86d6bc2a Guido Trotter

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

651 86d6bc2a Guido Trotter
    """
652 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
653 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
654 86d6bc2a Guido Trotter
    else:
655 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
656 86d6bc2a Guido Trotter
657 0df4d98a Guido Trotter
  @classmethod
658 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
659 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
660 38e250ba Guido Trotter

661 38e250ba Guido Trotter
    """
662 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
663 38e250ba Guido Trotter
664 7e66c35b Guido Trotter
  @classmethod
665 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
666 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
667 547a63b7 Balazs Lecz

668 547a63b7 Balazs Lecz
    """
669 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
670 547a63b7 Balazs Lecz
671 547a63b7 Balazs Lecz
  @classmethod
672 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
673 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
674 5d9bfd87 Apollon Oikonomopoulos
    given instance.
675 5d9bfd87 Apollon Oikonomopoulos

676 5d9bfd87 Apollon Oikonomopoulos
    """
677 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
678 5d9bfd87 Apollon Oikonomopoulos
679 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
680 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
681 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
682 5d9bfd87 Apollon Oikonomopoulos

683 5d9bfd87 Apollon Oikonomopoulos
    """
684 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
685 5d9bfd87 Apollon Oikonomopoulos
686 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
687 4f580fef Sรฉbastien Bocahu
  def _InstanceKeymapFile(cls, instance_name):
688 4f580fef Sรฉbastien Bocahu
    """Returns the name of the file containing the keymap for a given instance
689 4f580fef Sรฉbastien Bocahu

690 4f580fef Sรฉbastien Bocahu
    """
691 4f580fef Sรฉbastien Bocahu
    return utils.PathJoin(cls._KEYMAP_DIR, instance_name)
692 4f580fef Sรฉbastien Bocahu
693 4f580fef Sรฉbastien Bocahu
  @classmethod
694 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
695 7548396c Guido Trotter
    """Try to read a uid file
696 7548396c Guido Trotter

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

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

752 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
753 eb58f9b1 Guido Trotter
    @type instance: instance object
754 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
755 eb58f9b1 Guido Trotter
    @type seq: int
756 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
757 eb58f9b1 Guido Trotter
    @type nic: nic object
758 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
759 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
760 eb58f9b1 Guido Trotter

761 eb58f9b1 Guido Trotter
    """
762 5d9bfd87 Apollon Oikonomopoulos
    if instance.tags:
763 5d9bfd87 Apollon Oikonomopoulos
      tags = " ".join(instance.tags)
764 5d9bfd87 Apollon Oikonomopoulos
    else:
765 5d9bfd87 Apollon Oikonomopoulos
      tags = ""
766 5d9bfd87 Apollon Oikonomopoulos
767 5d9bfd87 Apollon Oikonomopoulos
    env = {
768 5d9bfd87 Apollon Oikonomopoulos
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
769 5d9bfd87 Apollon Oikonomopoulos
      "INSTANCE": instance.name,
770 5d9bfd87 Apollon Oikonomopoulos
      "MAC": nic.mac,
771 5d9bfd87 Apollon Oikonomopoulos
      "MODE": nic.nicparams[constants.NIC_MODE],
772 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE": tap,
773 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE_INDEX": str(seq),
774 5d9bfd87 Apollon Oikonomopoulos
      "TAGS": tags,
775 5d9bfd87 Apollon Oikonomopoulos
    }
776 5d9bfd87 Apollon Oikonomopoulos
777 5d9bfd87 Apollon Oikonomopoulos
    if nic.ip:
778 5d9bfd87 Apollon Oikonomopoulos
      env["IP"] = nic.ip
779 5d9bfd87 Apollon Oikonomopoulos
780 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_LINK]:
781 5d9bfd87 Apollon Oikonomopoulos
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
782 5d9bfd87 Apollon Oikonomopoulos
783 8c4771b1 Dimitris Aragiorgis
    def _BuildNetworkEnv(name, network, gateway, network6, gateway6,
784 8c4771b1 Dimitris Aragiorgis
                         network_type, mac_prefix, tags, env):
785 8c4771b1 Dimitris Aragiorgis
      if name:
786 8c4771b1 Dimitris Aragiorgis
        env["NETWORK_NAME"] = name
787 8c4771b1 Dimitris Aragiorgis
      if network:
788 8c4771b1 Dimitris Aragiorgis
        env["NETWORK_SUBNET"] = network
789 8c4771b1 Dimitris Aragiorgis
      if gateway:
790 8c4771b1 Dimitris Aragiorgis
        env["NETWORK_GATEWAY"] = gateway
791 8c4771b1 Dimitris Aragiorgis
      if network6:
792 8c4771b1 Dimitris Aragiorgis
        env["NETWORK_SUBNET6"] = network6
793 8c4771b1 Dimitris Aragiorgis
      if gateway6:
794 8c4771b1 Dimitris Aragiorgis
        env["NETWORK_GATEWAY6"] = gateway6
795 8c4771b1 Dimitris Aragiorgis
      if mac_prefix:
796 8c4771b1 Dimitris Aragiorgis
        env["NETWORK_MAC_PREFIX"] = mac_prefix
797 8c4771b1 Dimitris Aragiorgis
      if network_type:
798 8c4771b1 Dimitris Aragiorgis
        env["NETWORK_TYPE"] = network_type
799 8c4771b1 Dimitris Aragiorgis
      if tags:
800 8c4771b1 Dimitris Aragiorgis
        env["NETWORK_TAGS"] = " ".join(tags)
801 8c4771b1 Dimitris Aragiorgis
802 8c4771b1 Dimitris Aragiorgis
      return env
803 8c4771b1 Dimitris Aragiorgis
804 8c4771b1 Dimitris Aragiorgis
805 d45473fb Dimitris Aragiorgis
    if nic.network:
806 8c4771b1 Dimitris Aragiorgis
      n = objects.Network.FromDict(nic.netinfo)
807 8c4771b1 Dimitris Aragiorgis
      _BuildNetworkEnv(nic.network, n.network, n.gateway,
808 8c4771b1 Dimitris Aragiorgis
                       n.network6, n.gateway6, n.network_type,
809 8c4771b1 Dimitris Aragiorgis
                       n.mac_prefix, n.tags, env)
810 d45473fb Dimitris Aragiorgis
811 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
812 5d9bfd87 Apollon Oikonomopoulos
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
813 5d9bfd87 Apollon Oikonomopoulos
814 5d9bfd87 Apollon Oikonomopoulos
    result = utils.RunCmd([constants.KVM_IFUP, tap], env=env)
815 5d9bfd87 Apollon Oikonomopoulos
    if result.failed:
816 5d9bfd87 Apollon Oikonomopoulos
      raise errors.HypervisorError("Failed to configure interface %s: %s."
817 5d9bfd87 Apollon Oikonomopoulos
                                   " Network configuration script output: %s" %
818 5d9bfd87 Apollon Oikonomopoulos
                                   (tap, result.fail_reason, result.output))
819 eb58f9b1 Guido Trotter
820 b693125f Tsachy Shacham
  @staticmethod
821 b693125f Tsachy Shacham
  def _VerifyAffinityPackage():
822 b693125f Tsachy Shacham
    if affinity is None:
823 b693125f Tsachy Shacham
      raise errors.HypervisorError("affinity Python package not"
824 b693125f Tsachy Shacham
        " found; cannot use CPU pinning under KVM")
825 b693125f Tsachy Shacham
826 b693125f Tsachy Shacham
  @staticmethod
827 b693125f Tsachy Shacham
  def _BuildAffinityCpuMask(cpu_list):
828 b693125f Tsachy Shacham
    """Create a CPU mask suitable for sched_setaffinity from a list of
829 b693125f Tsachy Shacham
    CPUs.
830 b693125f Tsachy Shacham

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

834 b693125f Tsachy Shacham
    @type cpu_list: list of int
835 b693125f Tsachy Shacham
    @param cpu_list: list of physical CPU numbers to map to vCPUs in order
836 b693125f Tsachy Shacham
    @rtype: int
837 b693125f Tsachy Shacham
    @return: a bit mask of CPU affinities
838 b693125f Tsachy Shacham

839 b693125f Tsachy Shacham
    """
840 b693125f Tsachy Shacham
    if cpu_list == constants.CPU_PINNING_OFF:
841 b693125f Tsachy Shacham
      return constants.CPU_PINNING_ALL_KVM
842 b693125f Tsachy Shacham
    else:
843 b693125f Tsachy Shacham
      return sum(2 ** cpu for cpu in cpu_list)
844 b693125f Tsachy Shacham
845 b693125f Tsachy Shacham
  @classmethod
846 b693125f Tsachy Shacham
  def _AssignCpuAffinity(cls, cpu_mask, process_id, thread_dict):
847 b693125f Tsachy Shacham
    """Change CPU affinity for running VM according to given CPU mask.
848 b693125f Tsachy Shacham

849 b693125f Tsachy Shacham
    @param cpu_mask: CPU mask as given by the user. e.g. "0-2,4:all:1,3"
850 b693125f Tsachy Shacham
    @type cpu_mask: string
851 b693125f Tsachy Shacham
    @param process_id: process ID of KVM process. Used to pin entire VM
852 b693125f Tsachy Shacham
                       to physical CPUs.
853 b693125f Tsachy Shacham
    @type process_id: int
854 b693125f Tsachy Shacham
    @param thread_dict: map of virtual CPUs to KVM thread IDs
855 b693125f Tsachy Shacham
    @type thread_dict: dict int:int
856 b693125f Tsachy Shacham

857 b693125f Tsachy Shacham
    """
858 b693125f Tsachy Shacham
    # Convert the string CPU mask to a list of list of int's
859 b693125f Tsachy Shacham
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
860 b693125f Tsachy Shacham
861 b693125f Tsachy Shacham
    if len(cpu_list) == 1:
862 b693125f Tsachy Shacham
      all_cpu_mapping = cpu_list[0]
863 b693125f Tsachy Shacham
      if all_cpu_mapping == constants.CPU_PINNING_OFF:
864 b693125f Tsachy Shacham
        # If CPU pinning has 1 entry that's "all", then do nothing
865 b693125f Tsachy Shacham
        pass
866 b693125f Tsachy Shacham
      else:
867 b693125f Tsachy Shacham
        # If CPU pinning has one non-all entry, map the entire VM to
868 b693125f Tsachy Shacham
        # one set of physical CPUs
869 b693125f Tsachy Shacham
        cls._VerifyAffinityPackage()
870 b693125f Tsachy Shacham
        affinity.set_process_affinity_mask(process_id,
871 b693125f Tsachy Shacham
          cls._BuildAffinityCpuMask(all_cpu_mapping))
872 b693125f Tsachy Shacham
    else:
873 b693125f Tsachy Shacham
      # The number of vCPUs mapped should match the number of vCPUs
874 b693125f Tsachy Shacham
      # reported by KVM. This was already verified earlier, so
875 b693125f Tsachy Shacham
      # here only as a sanity check.
876 b693125f Tsachy Shacham
      assert len(thread_dict) == len(cpu_list)
877 b693125f Tsachy Shacham
      cls._VerifyAffinityPackage()
878 b693125f Tsachy Shacham
879 b693125f Tsachy Shacham
      # For each vCPU, map it to the proper list of physical CPUs
880 b693125f Tsachy Shacham
      for vcpu, i in zip(cpu_list, range(len(cpu_list))):
881 b693125f Tsachy Shacham
        affinity.set_process_affinity_mask(thread_dict[i],
882 b693125f Tsachy Shacham
          cls._BuildAffinityCpuMask(vcpu))
883 b693125f Tsachy Shacham
884 b693125f Tsachy Shacham
  def _GetVcpuThreadIds(self, instance_name):
885 b693125f Tsachy Shacham
    """Get a mapping of vCPU no. to thread IDs for the instance
886 b693125f Tsachy Shacham

887 b693125f Tsachy Shacham
    @type instance_name: string
888 b693125f Tsachy Shacham
    @param instance_name: instance in question
889 b693125f Tsachy Shacham
    @rtype: dictionary of int:int
890 b693125f Tsachy Shacham
    @return: a dictionary mapping vCPU numbers to thread IDs
891 b693125f Tsachy Shacham

892 b693125f Tsachy Shacham
    """
893 b693125f Tsachy Shacham
    result = {}
894 b693125f Tsachy Shacham
    output = self._CallMonitorCommand(instance_name, self._CPU_INFO_CMD)
895 b693125f Tsachy Shacham
    for line in output.stdout.splitlines():
896 b693125f Tsachy Shacham
      match = self._CPU_INFO_RE.search(line)
897 b693125f Tsachy Shacham
      if not match:
898 b693125f Tsachy Shacham
        continue
899 b693125f Tsachy Shacham
      grp = map(int, match.groups())
900 b693125f Tsachy Shacham
      result[grp[0]] = grp[1]
901 b693125f Tsachy Shacham
902 b693125f Tsachy Shacham
    return result
903 b693125f Tsachy Shacham
904 1d8a7812 Andrea Spadaccini
  def _ExecuteCpuAffinity(self, instance_name, cpu_mask):
905 1d8a7812 Andrea Spadaccini
    """Complete CPU pinning.
906 b693125f Tsachy Shacham

907 b693125f Tsachy Shacham
    @type instance_name: string
908 b693125f Tsachy Shacham
    @param instance_name: name of instance
909 b693125f Tsachy Shacham
    @type cpu_mask: string
910 b693125f Tsachy Shacham
    @param cpu_mask: CPU pinning mask as entered by user
911 b693125f Tsachy Shacham

912 b693125f Tsachy Shacham
    """
913 1d8a7812 Andrea Spadaccini
    # Get KVM process ID, to be used if need to pin entire VM
914 1d8a7812 Andrea Spadaccini
    _, pid, _ = self._InstancePidAlive(instance_name)
915 1d8a7812 Andrea Spadaccini
    # Get vCPU thread IDs, to be used if need to pin vCPUs separately
916 1d8a7812 Andrea Spadaccini
    thread_dict = self._GetVcpuThreadIds(instance_name)
917 1d8a7812 Andrea Spadaccini
    # Run CPU pinning, based on configured mask
918 1d8a7812 Andrea Spadaccini
    self._AssignCpuAffinity(cpu_mask, pid, thread_dict)
919 b693125f Tsachy Shacham
920 eb58f9b1 Guido Trotter
  def ListInstances(self):
921 eb58f9b1 Guido Trotter
    """Get the list of running instances.
922 eb58f9b1 Guido Trotter

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

926 eb58f9b1 Guido Trotter
    """
927 eb58f9b1 Guido Trotter
    result = []
928 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
929 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
930 eb58f9b1 Guido Trotter
        result.append(name)
931 eb58f9b1 Guido Trotter
    return result
932 eb58f9b1 Guido Trotter
933 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
934 eb58f9b1 Guido Trotter
    """Get instance properties.
935 eb58f9b1 Guido Trotter

936 4fbb3c60 Guido Trotter
    @type instance_name: string
937 c41eea6e Iustin Pop
    @param instance_name: the instance name
938 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
939 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
940 eb58f9b1 Guido Trotter

941 eb58f9b1 Guido Trotter
    """
942 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
943 1f8b3a27 Guido Trotter
    if not alive:
944 eb58f9b1 Guido Trotter
      return None
945 eb58f9b1 Guido Trotter
946 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
947 fc84cd5d Guido Trotter
    istat = "---b-"
948 eb58f9b1 Guido Trotter
    times = "0"
949 eb58f9b1 Guido Trotter
950 89da2ff3 Guido Trotter
    try:
951 89da2ff3 Guido Trotter
      qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
952 89da2ff3 Guido Trotter
      qmp.connect()
953 89da2ff3 Guido Trotter
      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
954 89da2ff3 Guido Trotter
      # Will fail if ballooning is not enabled, but we can then just resort to
955 89da2ff3 Guido Trotter
      # the value above.
956 89da2ff3 Guido Trotter
      mem_bytes = qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
957 89da2ff3 Guido Trotter
      memory = mem_bytes / 1048576
958 89da2ff3 Guido Trotter
    except errors.HypervisorError:
959 89da2ff3 Guido Trotter
      pass
960 89da2ff3 Guido Trotter
961 fc84cd5d Guido Trotter
    return (instance_name, pid, memory, vcpus, istat, times)
962 eb58f9b1 Guido Trotter
963 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
964 eb58f9b1 Guido Trotter
    """Get properties of all instances.
965 eb58f9b1 Guido Trotter

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

968 eb58f9b1 Guido Trotter
    """
969 eb58f9b1 Guido Trotter
    data = []
970 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
971 263b8de6 Guido Trotter
      try:
972 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
973 263b8de6 Guido Trotter
      except errors.HypervisorError:
974 3bc145d8 Bernardo Dal Seno
        # Ignore exceptions due to instances being shut down
975 263b8de6 Guido Trotter
        continue
976 263b8de6 Guido Trotter
      if info:
977 263b8de6 Guido Trotter
        data.append(info)
978 eb58f9b1 Guido Trotter
    return data
979 eb58f9b1 Guido Trotter
980 644e5023 Dimitris Aragriorgs
  def _GenerateKVMBlockDevicesOptions(self, instance, kvm_cmd, block_devices):
981 644e5023 Dimitris Aragriorgs
982 644e5023 Dimitris Aragriorgs
    hvp = instance.hvparams
983 644e5023 Dimitris Aragriorgs
    boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
984 644e5023 Dimitris Aragriorgs
985 644e5023 Dimitris Aragriorgs
    _, v_major, v_min, _ = self._GetKVMVersion()
986 644e5023 Dimitris Aragriorgs
987 644e5023 Dimitris Aragriorgs
    # whether this is an older KVM version that uses the boot=on flag
988 644e5023 Dimitris Aragriorgs
    # on devices
989 644e5023 Dimitris Aragriorgs
    needs_boot_flag = (v_major, v_min) < (0, 14)
990 644e5023 Dimitris Aragriorgs
991 644e5023 Dimitris Aragriorgs
    disk_type = hvp[constants.HV_DISK_TYPE]
992 644e5023 Dimitris Aragriorgs
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
993 644e5023 Dimitris Aragriorgs
      if_val = ",if=virtio"
994 644e5023 Dimitris Aragriorgs
      if (v_major, v_min) >= (0, 12):
995 644e5023 Dimitris Aragriorgs
        disk_model = "virtio-blk-pci"
996 644e5023 Dimitris Aragriorgs
      else:
997 644e5023 Dimitris Aragriorgs
        disk_model = "virtio"
998 644e5023 Dimitris Aragriorgs
    else:
999 644e5023 Dimitris Aragriorgs
      if_val = ",if=%s" % disk_type
1000 644e5023 Dimitris Aragriorgs
      disk_model = disk_type
1001 644e5023 Dimitris Aragriorgs
    # Cache mode
1002 644e5023 Dimitris Aragriorgs
    disk_cache = hvp[constants.HV_DISK_CACHE]
1003 644e5023 Dimitris Aragriorgs
    if instance.disk_template in constants.DTS_EXT_MIRROR:
1004 644e5023 Dimitris Aragriorgs
      if disk_cache != "none":
1005 644e5023 Dimitris Aragriorgs
        # TODO: make this a hard error, instead of a silent overwrite
1006 644e5023 Dimitris Aragriorgs
        logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
1007 644e5023 Dimitris Aragriorgs
                        " to prevent shared storage corruption on migration",
1008 644e5023 Dimitris Aragriorgs
                        disk_cache)
1009 644e5023 Dimitris Aragriorgs
      cache_val = ",cache=none"
1010 644e5023 Dimitris Aragriorgs
    elif disk_cache != constants.HT_CACHE_DEFAULT:
1011 644e5023 Dimitris Aragriorgs
      cache_val = ",cache=%s" % disk_cache
1012 644e5023 Dimitris Aragriorgs
    else:
1013 644e5023 Dimitris Aragriorgs
      cache_val = ""
1014 644e5023 Dimitris Aragriorgs
    for cfdev, dev_path in block_devices:
1015 644e5023 Dimitris Aragriorgs
      if cfdev.mode != constants.DISK_RDWR:
1016 644e5023 Dimitris Aragriorgs
        raise errors.HypervisorError("Instance has read-only disks which"
1017 644e5023 Dimitris Aragriorgs
                                     " are not supported by KVM")
1018 644e5023 Dimitris Aragriorgs
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
1019 644e5023 Dimitris Aragriorgs
      boot_val = ""
1020 644e5023 Dimitris Aragriorgs
      if boot_disk:
1021 644e5023 Dimitris Aragriorgs
        kvm_cmd.extend(["-boot", "c"])
1022 644e5023 Dimitris Aragriorgs
        boot_disk = False
1023 644e5023 Dimitris Aragriorgs
        if needs_boot_flag and disk_type != constants.HT_DISK_IDE:
1024 644e5023 Dimitris Aragriorgs
          boot_val = ",boot=on"
1025 644e5023 Dimitris Aragriorgs
      drive_val = "file=%s,format=raw%s%s" % \
1026 644e5023 Dimitris Aragriorgs
                  (dev_path, boot_val, cache_val)
1027 2435f63b Dimitris Aragiorgis
      if cfdev.idx is not None:
1028 644e5023 Dimitris Aragriorgs
        #TODO: name id after model
1029 2435f63b Dimitris Aragiorgis
        drive_val += (",if=none,id=drive%d" % cfdev.idx)
1030 2435f63b Dimitris Aragiorgis
        if cfdev.pci is not None:
1031 2435f63b Dimitris Aragiorgis
          drive_val += (",bus=0,unit=%d" % cfdev.pci)
1032 644e5023 Dimitris Aragriorgs
      else:
1033 644e5023 Dimitris Aragriorgs
        drive_val += if_val
1034 644e5023 Dimitris Aragriorgs
1035 644e5023 Dimitris Aragriorgs
      kvm_cmd.extend(["-drive", drive_val])
1036 644e5023 Dimitris Aragriorgs
1037 2435f63b Dimitris Aragiorgis
      if cfdev.idx is not None:
1038 2435f63b Dimitris Aragiorgis
        dev_val = ("%s,drive=drive%d,id=virtio-blk-pci.%d" %
1039 2435f63b Dimitris Aragiorgis
                    (disk_model, cfdev.idx, cfdev.idx))
1040 2435f63b Dimitris Aragiorgis
        if cfdev.pci is not None:
1041 2435f63b Dimitris Aragiorgis
          dev_val += ",bus=pci.0,addr=%s" % hex(cfdev.pci)
1042 644e5023 Dimitris Aragriorgs
        kvm_cmd.extend(["-device", dev_val])
1043 644e5023 Dimitris Aragriorgs
1044 644e5023 Dimitris Aragriorgs
    return kvm_cmd
1045 644e5023 Dimitris Aragriorgs
1046 323f9095 Stephen Shirley
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused):
1047 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
1048 eb58f9b1 Guido Trotter

1049 839642c2 Iustin Pop
    @attention: this function must not have any side-effects; for
1050 839642c2 Iustin Pop
        example, it must not write to the filesystem, or read values
1051 839642c2 Iustin Pop
        from the current system the are expected to differ between
1052 839642c2 Iustin Pop
        nodes, since it is only run once at instance startup;
1053 839642c2 Iustin Pop
        actions/kvm arguments that can vary between systems should be
1054 839642c2 Iustin Pop
        done in L{_ExecuteKVMRuntime}
1055 839642c2 Iustin Pop

1056 eb58f9b1 Guido Trotter
    """
1057 b6267745 Andrea Spadaccini
    # pylint: disable=R0914,R0915
1058 440351f8 Andrea Spadaccini
    _, v_major, v_min, _ = self._GetKVMVersion()
1059 4304964a Guido Trotter
1060 e687ec01 Michael Hanselmann
    pidfile = self._InstancePidFile(instance.name)
1061 eb58f9b1 Guido Trotter
    kvm = constants.KVM_PATH
1062 eb58f9b1 Guido Trotter
    kvm_cmd = [kvm]
1063 c6a39fc2 Guido Trotter
    # used just by the vnc server, if enabled
1064 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-name", instance.name])
1065 f5a4b9ce Guido Trotter
    kvm_cmd.extend(["-m", instance.beparams[constants.BE_MAXMEM]])
1066 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-smp", instance.beparams[constants.BE_VCPUS]])
1067 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-pidfile", pidfile])
1068 fcf5b670 Guido Trotter
    kvm_cmd.extend(["-balloon", "virtio"])
1069 d0c8c01d Iustin Pop
    kvm_cmd.extend(["-daemonize"])
1070 6b5605e8 Iustin Pop
    if not instance.hvparams[constants.HV_ACPI]:
1071 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-no-acpi"])
1072 990ade2d Stephen Shirley
    if instance.hvparams[constants.HV_REBOOT_BEHAVIOR] == \
1073 990ade2d Stephen Shirley
        constants.INSTANCE_REBOOT_EXIT:
1074 990ade2d Stephen Shirley
      kvm_cmd.extend(["-no-reboot"])
1075 eb58f9b1 Guido Trotter
1076 a985b417 Iustin Pop
    hvp = instance.hvparams
1077 2b846304 Iustin Pop
    kernel_path = hvp[constants.HV_KERNEL_PATH]
1078 2b846304 Iustin Pop
    if kernel_path:
1079 59a5de9e Dimitris Aragiorgis
      boot_cdrom = boot_floppy = boot_network = False
1080 2b846304 Iustin Pop
    else:
1081 2b846304 Iustin Pop
      boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
1082 2b846304 Iustin Pop
      boot_floppy = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_FLOPPY
1083 2b846304 Iustin Pop
      boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
1084 8745c3d7 Guido Trotter
1085 b1cb62bd Andrea Spadaccini
    self.ValidateParameters(hvp)
1086 b1cb62bd Andrea Spadaccini
1087 b693125f Tsachy Shacham
    if startup_paused:
1088 b693125f Tsachy Shacham
      kvm_cmd.extend([_KVM_START_PAUSED_FLAG])
1089 b693125f Tsachy Shacham
1090 7ba594c0 Guido Trotter
    if hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED:
1091 7ba594c0 Guido Trotter
      kvm_cmd.extend(["-enable-kvm"])
1092 7ba594c0 Guido Trotter
    elif hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED:
1093 7ba594c0 Guido Trotter
      kvm_cmd.extend(["-disable-kvm"])
1094 7ba594c0 Guido Trotter
1095 8745c3d7 Guido Trotter
    if boot_network:
1096 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-boot", "n"])
1097 1213604d Guido Trotter
1098 24be50e0 Iustin Pop
    # whether this is an older KVM version that uses the boot=on flag
1099 24be50e0 Iustin Pop
    # on devices
1100 24be50e0 Iustin Pop
    needs_boot_flag = (v_major, v_min) < (0, 14)
1101 24be50e0 Iustin Pop
1102 a985b417 Iustin Pop
    disk_type = hvp[constants.HV_DISK_TYPE]
1103 644e5023 Dimitris Aragriorgs
    if not instance.hotplug_info:
1104 644e5023 Dimitris Aragriorgs
      kvm_cmd = self._GenerateKVMBlockDevicesOptions(instance, kvm_cmd,
1105 644e5023 Dimitris Aragriorgs
                                                     block_devices)
1106 eb58f9b1 Guido Trotter
1107 cc130cc7 Marco Casavecchia
    #Now we can specify a different device type for CDROM devices.
1108 cc130cc7 Marco Casavecchia
    cdrom_disk_type = hvp[constants.HV_KVM_CDROM_DISK_TYPE]
1109 cc130cc7 Marco Casavecchia
    if not cdrom_disk_type:
1110 cc130cc7 Marco Casavecchia
      cdrom_disk_type = disk_type
1111 cc130cc7 Marco Casavecchia
1112 a985b417 Iustin Pop
    iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
1113 66d5dbef Guido Trotter
    if iso_image:
1114 d0c8c01d Iustin Pop
      options = ",format=raw,media=cdrom"
1115 24be50e0 Iustin Pop
      # set cdrom 'if' type
1116 66d5dbef Guido Trotter
      if boot_cdrom:
1117 24be50e0 Iustin Pop
        actual_cdrom_type = constants.HT_DISK_IDE
1118 24be50e0 Iustin Pop
      elif cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1119 24be50e0 Iustin Pop
        actual_cdrom_type = "virtio"
1120 9dd363eb Guido Trotter
      else:
1121 24be50e0 Iustin Pop
        actual_cdrom_type = cdrom_disk_type
1122 24be50e0 Iustin Pop
      if_val = ",if=%s" % actual_cdrom_type
1123 24be50e0 Iustin Pop
      # set boot flag, if needed
1124 24be50e0 Iustin Pop
      boot_val = ""
1125 24be50e0 Iustin Pop
      if boot_cdrom:
1126 24be50e0 Iustin Pop
        kvm_cmd.extend(["-boot", "d"])
1127 24be50e0 Iustin Pop
        if needs_boot_flag:
1128 24be50e0 Iustin Pop
          boot_val = ",boot=on"
1129 24be50e0 Iustin Pop
      # and finally build the entire '-drive' value
1130 24be50e0 Iustin Pop
      drive_val = "file=%s%s%s%s" % (iso_image, options, if_val, boot_val)
1131 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1132 66d5dbef Guido Trotter
1133 cc130cc7 Marco Casavecchia
    iso_image2 = hvp[constants.HV_KVM_CDROM2_IMAGE_PATH]
1134 cc130cc7 Marco Casavecchia
    if iso_image2:
1135 d0c8c01d Iustin Pop
      options = ",format=raw,media=cdrom"
1136 cc130cc7 Marco Casavecchia
      if cdrom_disk_type == constants.HT_DISK_PARAVIRTUAL:
1137 d0c8c01d Iustin Pop
        if_val = ",if=virtio"
1138 cc130cc7 Marco Casavecchia
      else:
1139 d0c8c01d Iustin Pop
        if_val = ",if=%s" % cdrom_disk_type
1140 24be50e0 Iustin Pop
      drive_val = "file=%s%s%s" % (iso_image2, options, if_val)
1141 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1142 cc130cc7 Marco Casavecchia
1143 cc130cc7 Marco Casavecchia
    floppy_image = hvp[constants.HV_KVM_FLOPPY_IMAGE_PATH]
1144 cc130cc7 Marco Casavecchia
    if floppy_image:
1145 d0c8c01d Iustin Pop
      options = ",format=raw,media=disk"
1146 cc130cc7 Marco Casavecchia
      if boot_floppy:
1147 d0c8c01d Iustin Pop
        kvm_cmd.extend(["-boot", "a"])
1148 d0c8c01d Iustin Pop
        options = "%s,boot=on" % options
1149 d0c8c01d Iustin Pop
      if_val = ",if=floppy"
1150 d0c8c01d Iustin Pop
      options = "%s%s" % (options, if_val)
1151 d0c8c01d Iustin Pop
      drive_val = "file=%s%s" % (floppy_image, options)
1152 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-drive", drive_val])
1153 cc130cc7 Marco Casavecchia
1154 df5ab9f0 Guido Trotter
    if kernel_path:
1155 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-kernel", kernel_path])
1156 a985b417 Iustin Pop
      initrd_path = hvp[constants.HV_INITRD_PATH]
1157 df5ab9f0 Guido Trotter
      if initrd_path:
1158 d0c8c01d Iustin Pop
        kvm_cmd.extend(["-initrd", initrd_path])
1159 d0c8c01d Iustin Pop
      root_append = ["root=%s" % hvp[constants.HV_ROOT_PATH],
1160 07813a9e Iustin Pop
                     hvp[constants.HV_KERNEL_ARGS]]
1161 07813a9e Iustin Pop
      if hvp[constants.HV_SERIAL_CONSOLE]:
1162 d0c8c01d Iustin Pop
        root_append.append("console=ttyS0,38400")
1163 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-append", " ".join(root_append)])
1164 eb58f9b1 Guido Trotter
1165 4f958b0b Miguel Di Ciurcio Filho
    mem_path = hvp[constants.HV_MEM_PATH]
1166 4f958b0b Miguel Di Ciurcio Filho
    if mem_path:
1167 9d3015f9 Guido Trotter
      kvm_cmd.extend(["-mem-path", mem_path, "-mem-prealloc"])
1168 4f958b0b Miguel Di Ciurcio Filho
1169 596b2459 Guido Trotter
    monitor_dev = ("unix:%s,server,nowait" %
1170 596b2459 Guido Trotter
                   self._InstanceMonitor(instance.name))
1171 596b2459 Guido Trotter
    kvm_cmd.extend(["-monitor", monitor_dev])
1172 596b2459 Guido Trotter
    if hvp[constants.HV_SERIAL_CONSOLE]:
1173 596b2459 Guido Trotter
      serial_dev = ("unix:%s,server,nowait" %
1174 596b2459 Guido Trotter
                    self._InstanceSerial(instance.name))
1175 596b2459 Guido Trotter
      kvm_cmd.extend(["-serial", serial_dev])
1176 596b2459 Guido Trotter
    else:
1177 596b2459 Guido Trotter
      kvm_cmd.extend(["-serial", "none"])
1178 596b2459 Guido Trotter
1179 a985b417 Iustin Pop
    mouse_type = hvp[constants.HV_USB_MOUSE]
1180 31f6f67a Guido Trotter
    vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
1181 596b2459 Guido Trotter
    spice_bind = hvp[constants.HV_KVM_SPICE_BIND]
1182 596b2459 Guido Trotter
    spice_ip_version = None
1183 31f6f67a Guido Trotter
1184 11344a50 Guido Trotter
    if mouse_type:
1185 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-usb"])
1186 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-usbdevice", mouse_type])
1187 31f6f67a Guido Trotter
    elif vnc_bind_address:
1188 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-usbdevice", constants.HT_MOUSE_TABLET])
1189 11344a50 Guido Trotter
1190 8470c8db Guido Trotter
    if vnc_bind_address:
1191 8b312c1d Manuel Franceschini
      if netutils.IP4Address.IsValid(vnc_bind_address):
1192 377d74c9 Guido Trotter
        if instance.network_port > constants.VNC_BASE_PORT:
1193 377d74c9 Guido Trotter
          display = instance.network_port - constants.VNC_BASE_PORT
1194 14f5f1b6 Manuel Franceschini
          if vnc_bind_address == constants.IP4_ADDRESS_ANY:
1195 d0c8c01d Iustin Pop
            vnc_arg = ":%d" % (display)
1196 8447f52b Guido Trotter
          else:
1197 d0c8c01d Iustin Pop
            vnc_arg = "%s:%d" % (vnc_bind_address, display)
1198 8470c8db Guido Trotter
        else:
1199 8447f52b Guido Trotter
          logging.error("Network port is not a valid VNC display (%d < %d)."
1200 07b8a2b5 Iustin Pop
                        " Not starting VNC", instance.network_port,
1201 07b8a2b5 Iustin Pop
                        constants.VNC_BASE_PORT)
1202 d0c8c01d Iustin Pop
          vnc_arg = "none"
1203 8b2d1013 Guido Trotter
1204 8b2d1013 Guido Trotter
        # Only allow tls and other option when not binding to a file, for now.
1205 8b2d1013 Guido Trotter
        # kvm/qemu gets confused otherwise about the filename to use.
1206 d0c8c01d Iustin Pop
        vnc_append = ""
1207 a985b417 Iustin Pop
        if hvp[constants.HV_VNC_TLS]:
1208 d0c8c01d Iustin Pop
          vnc_append = "%s,tls" % vnc_append
1209 a985b417 Iustin Pop
          if hvp[constants.HV_VNC_X509_VERIFY]:
1210 d0c8c01d Iustin Pop
            vnc_append = "%s,x509verify=%s" % (vnc_append,
1211 a985b417 Iustin Pop
                                               hvp[constants.HV_VNC_X509])
1212 a985b417 Iustin Pop
          elif hvp[constants.HV_VNC_X509]:
1213 d0c8c01d Iustin Pop
            vnc_append = "%s,x509=%s" % (vnc_append,
1214 a985b417 Iustin Pop
                                         hvp[constants.HV_VNC_X509])
1215 6e6bb8d5 Guido Trotter
        if hvp[constants.HV_VNC_PASSWORD_FILE]:
1216 d0c8c01d Iustin Pop
          vnc_append = "%s,password" % vnc_append
1217 6e6bb8d5 Guido Trotter
1218 d0c8c01d Iustin Pop
        vnc_arg = "%s%s" % (vnc_arg, vnc_append)
1219 8b2d1013 Guido Trotter
1220 8470c8db Guido Trotter
      else:
1221 d0c8c01d Iustin Pop
        vnc_arg = "unix:%s/%s.vnc" % (vnc_bind_address, instance.name)
1222 8b2d1013 Guido Trotter
1223 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-vnc", vnc_arg])
1224 596b2459 Guido Trotter
    elif spice_bind:
1225 839642c2 Iustin Pop
      # FIXME: this is wrong here; the iface ip address differs
1226 839642c2 Iustin Pop
      # between systems, so it should be done in _ExecuteKVMRuntime
1227 b1cb62bd Andrea Spadaccini
      if netutils.IsValidInterface(spice_bind):
1228 b1cb62bd Andrea Spadaccini
        # The user specified a network interface, we have to figure out the IP
1229 b1cb62bd Andrea Spadaccini
        # address.
1230 b1cb62bd Andrea Spadaccini
        addresses = netutils.GetInterfaceIpAddresses(spice_bind)
1231 b1cb62bd Andrea Spadaccini
        spice_ip_version = hvp[constants.HV_KVM_SPICE_IP_VERSION]
1232 b1cb62bd Andrea Spadaccini
1233 b1cb62bd Andrea Spadaccini
        # if the user specified an IP version and the interface does not
1234 b1cb62bd Andrea Spadaccini
        # have that kind of IP addresses, throw an exception
1235 b1cb62bd Andrea Spadaccini
        if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
1236 b1cb62bd Andrea Spadaccini
          if not addresses[spice_ip_version]:
1237 b1cb62bd Andrea Spadaccini
            raise errors.HypervisorError("spice: unable to get an IPv%s address"
1238 b1cb62bd Andrea Spadaccini
                                         " for %s" % (spice_ip_version,
1239 b1cb62bd Andrea Spadaccini
                                                      spice_bind))
1240 b1cb62bd Andrea Spadaccini
1241 b1cb62bd Andrea Spadaccini
        # the user did not specify an IP version, we have to figure it out
1242 b1cb62bd Andrea Spadaccini
        elif (addresses[constants.IP4_VERSION] and
1243 b1cb62bd Andrea Spadaccini
              addresses[constants.IP6_VERSION]):
1244 b1cb62bd Andrea Spadaccini
          # we have both ipv4 and ipv6, let's use the cluster default IP
1245 b1cb62bd Andrea Spadaccini
          # version
1246 b1cb62bd Andrea Spadaccini
          cluster_family = ssconf.SimpleStore().GetPrimaryIPFamily()
1247 65107a2f Michael Hanselmann
          spice_ip_version = \
1248 65107a2f Michael Hanselmann
            netutils.IPAddress.GetVersionFromAddressFamily(cluster_family)
1249 b1cb62bd Andrea Spadaccini
        elif addresses[constants.IP4_VERSION]:
1250 b1cb62bd Andrea Spadaccini
          spice_ip_version = constants.IP4_VERSION
1251 b845c8a1 Andrea Spadaccini
        elif addresses[constants.IP6_VERSION]:
1252 b1cb62bd Andrea Spadaccini
          spice_ip_version = constants.IP6_VERSION
1253 b845c8a1 Andrea Spadaccini
        else:
1254 b845c8a1 Andrea Spadaccini
          raise errors.HypervisorError("spice: unable to get an IP address"
1255 b845c8a1 Andrea Spadaccini
                                       " for %s" % (spice_bind))
1256 b1cb62bd Andrea Spadaccini
1257 b1cb62bd Andrea Spadaccini
        spice_address = addresses[spice_ip_version][0]
1258 b1cb62bd Andrea Spadaccini
1259 b1cb62bd Andrea Spadaccini
      else:
1260 b1cb62bd Andrea Spadaccini
        # spice_bind is known to be a valid IP address, because
1261 b1cb62bd Andrea Spadaccini
        # ValidateParameters checked it.
1262 b1cb62bd Andrea Spadaccini
        spice_address = spice_bind
1263 b1cb62bd Andrea Spadaccini
1264 bfe86c76 Andrea Spadaccini
      spice_arg = "addr=%s" % spice_address
1265 bfe86c76 Andrea Spadaccini
      if hvp[constants.HV_KVM_SPICE_USE_TLS]:
1266 bfe86c76 Andrea Spadaccini
        spice_arg = "%s,tls-port=%s,x509-cacert-file=%s" % (spice_arg,
1267 bfe86c76 Andrea Spadaccini
            instance.network_port, constants.SPICE_CACERT_FILE)
1268 bfe86c76 Andrea Spadaccini
        spice_arg = "%s,x509-key-file=%s,x509-cert-file=%s" % (spice_arg,
1269 bfe86c76 Andrea Spadaccini
            constants.SPICE_CERT_FILE, constants.SPICE_CERT_FILE)
1270 3e40b587 Andrea Spadaccini
        tls_ciphers = hvp[constants.HV_KVM_SPICE_TLS_CIPHERS]
1271 3e40b587 Andrea Spadaccini
        if tls_ciphers:
1272 3e40b587 Andrea Spadaccini
          spice_arg = "%s,tls-ciphers=%s" % (spice_arg, tls_ciphers)
1273 bfe86c76 Andrea Spadaccini
      else:
1274 bfe86c76 Andrea Spadaccini
        spice_arg = "%s,port=%s" % (spice_arg, instance.network_port)
1275 bfe86c76 Andrea Spadaccini
1276 b451c4c7 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]:
1277 b451c4c7 Andrea Spadaccini
        spice_arg = "%s,disable-ticketing" % spice_arg
1278 b451c4c7 Andrea Spadaccini
1279 11ae7a0a Andrea Spadaccini
      if spice_ip_version:
1280 11ae7a0a Andrea Spadaccini
        spice_arg = "%s,ipv%s" % (spice_arg, spice_ip_version)
1281 b1cb62bd Andrea Spadaccini
1282 ea064d24 Andrea Spadaccini
      # Image compression options
1283 ea064d24 Andrea Spadaccini
      img_lossless = hvp[constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR]
1284 ea064d24 Andrea Spadaccini
      img_jpeg = hvp[constants.HV_KVM_SPICE_JPEG_IMG_COMPR]
1285 ea064d24 Andrea Spadaccini
      img_zlib_glz = hvp[constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR]
1286 ea064d24 Andrea Spadaccini
      if img_lossless:
1287 ea064d24 Andrea Spadaccini
        spice_arg = "%s,image-compression=%s" % (spice_arg, img_lossless)
1288 ea064d24 Andrea Spadaccini
      if img_jpeg:
1289 ea064d24 Andrea Spadaccini
        spice_arg = "%s,jpeg-wan-compression=%s" % (spice_arg, img_jpeg)
1290 ea064d24 Andrea Spadaccini
      if img_zlib_glz:
1291 ea064d24 Andrea Spadaccini
        spice_arg = "%s,zlib-glz-wan-compression=%s" % (spice_arg, img_zlib_glz)
1292 ea064d24 Andrea Spadaccini
1293 ea064d24 Andrea Spadaccini
      # Video stream detection
1294 ea064d24 Andrea Spadaccini
      video_streaming = hvp[constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION]
1295 ea064d24 Andrea Spadaccini
      if video_streaming:
1296 ea064d24 Andrea Spadaccini
        spice_arg = "%s,streaming-video=%s" % (spice_arg, video_streaming)
1297 ea064d24 Andrea Spadaccini
1298 ea064d24 Andrea Spadaccini
      # Audio compression, by default in qemu-kvm it is on
1299 ea064d24 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_AUDIO_COMPR]:
1300 ea064d24 Andrea Spadaccini
        spice_arg = "%s,playback-compression=off" % spice_arg
1301 3e40b587 Andrea Spadaccini
      if not hvp[constants.HV_KVM_SPICE_USE_VDAGENT]:
1302 3e40b587 Andrea Spadaccini
        spice_arg = "%s,agent-mouse=off" % spice_arg
1303 447af814 Nikos Skalkotos
      else:
1304 447af814 Nikos Skalkotos
        # Enable the spice agent communication channel between the host and the
1305 447af814 Nikos Skalkotos
        # agent.
1306 447af814 Nikos Skalkotos
        kvm_cmd.extend(["-device", "virtio-serial-pci"])
1307 447af814 Nikos Skalkotos
        kvm_cmd.extend(["-device", "virtserialport,chardev=spicechannel0,"
1308 447af814 Nikos Skalkotos
                                                   "name=com.redhat.spice.0"])
1309 447af814 Nikos Skalkotos
        kvm_cmd.extend(["-chardev", "spicevmc,id=spicechannel0,name=vdagent"])
1310 ea064d24 Andrea Spadaccini
1311 b1cb62bd Andrea Spadaccini
      logging.info("KVM: SPICE will listen on port %s", instance.network_port)
1312 b1cb62bd Andrea Spadaccini
      kvm_cmd.extend(["-spice", spice_arg])
1313 b1cb62bd Andrea Spadaccini
1314 2ebdfbb5 Andrea Spadaccini
      # Tell kvm to use the paravirtualized graphic card, optimized for SPICE
1315 2ebdfbb5 Andrea Spadaccini
      kvm_cmd.extend(["-vga", "qxl"])
1316 2ebdfbb5 Andrea Spadaccini
1317 596b2459 Guido Trotter
    else:
1318 596b2459 Guido Trotter
      kvm_cmd.extend(["-nographic"])
1319 596b2459 Guido Trotter
1320 6b970cef Jun Futagawa
    if hvp[constants.HV_USE_LOCALTIME]:
1321 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-localtime"])
1322 6b970cef Jun Futagawa
1323 547a63b7 Balazs Lecz
    if hvp[constants.HV_KVM_USE_CHROOT]:
1324 d0c8c01d Iustin Pop
      kvm_cmd.extend(["-chroot", self._InstanceChrootDir(instance.name)])
1325 547a63b7 Balazs Lecz
1326 ee5f20b0 Guido Trotter
    # Save the current instance nics, but defer their expansion as parameters,
1327 ee5f20b0 Guido Trotter
    # as we'll need to generate executable temp files for them.
1328 ee5f20b0 Guido Trotter
    kvm_nics = instance.nics
1329 a985b417 Iustin Pop
    hvparams = hvp
1330 ee5f20b0 Guido Trotter
1331 644e5023 Dimitris Aragriorgs
    if instance.hotplug_info:
1332 644e5023 Dimitris Aragriorgs
      return (kvm_cmd, kvm_nics, hvparams, block_devices)
1333 644e5023 Dimitris Aragriorgs
    else:
1334 644e5023 Dimitris Aragriorgs
      return (kvm_cmd, kvm_nics, hvparams)
1335 ee5f20b0 Guido Trotter
1336 38e250ba Guido Trotter
  def _WriteKVMRuntime(self, instance_name, data):
1337 38e250ba Guido Trotter
    """Write an instance's KVM runtime
1338 38e250ba Guido Trotter

1339 38e250ba Guido Trotter
    """
1340 38e250ba Guido Trotter
    try:
1341 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
1342 38e250ba Guido Trotter
                      data=data)
1343 90c024f6 Guido Trotter
    except EnvironmentError, err:
1344 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
1345 38e250ba Guido Trotter
1346 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
1347 38e250ba Guido Trotter
    """Read an instance's KVM runtime
1348 38e250ba Guido Trotter

1349 38e250ba Guido Trotter
    """
1350 38e250ba Guido Trotter
    try:
1351 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
1352 90c024f6 Guido Trotter
    except EnvironmentError, err:
1353 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
1354 38e250ba Guido Trotter
    return file_content
1355 38e250ba Guido Trotter
1356 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
1357 38e250ba Guido Trotter
    """Save an instance's KVM runtime
1358 38e250ba Guido Trotter

1359 38e250ba Guido Trotter
    """
1360 644e5023 Dimitris Aragriorgs
    if instance.hotplug_info:
1361 644e5023 Dimitris Aragriorgs
      kvm_cmd, kvm_nics, hvparams, block_devices = kvm_runtime
1362 644e5023 Dimitris Aragriorgs
      serialized_blockdevs = [(blk.ToDict(), link)
1363 644e5023 Dimitris Aragriorgs
                              for blk,link in block_devices]
1364 644e5023 Dimitris Aragriorgs
    else:
1365 644e5023 Dimitris Aragriorgs
      kvm_cmd, kvm_nics, hvparams = kvm_runtime
1366 644e5023 Dimitris Aragriorgs
1367 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1368 644e5023 Dimitris Aragriorgs
1369 644e5023 Dimitris Aragriorgs
    if instance.hotplug_info:
1370 644e5023 Dimitris Aragriorgs
      serialized_form = serializer.Dump((kvm_cmd, serialized_nics,
1371 644e5023 Dimitris Aragriorgs
                                        hvparams, serialized_blockdevs))
1372 644e5023 Dimitris Aragriorgs
    else:
1373 644e5023 Dimitris Aragriorgs
      serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
1374 644e5023 Dimitris Aragriorgs
1375 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
1376 38e250ba Guido Trotter
1377 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
1378 38e250ba Guido Trotter
    """Load an instance's KVM runtime
1379 38e250ba Guido Trotter

1380 38e250ba Guido Trotter
    """
1381 30e42c4e Guido Trotter
    if not serialized_runtime:
1382 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1383 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
1384 644e5023 Dimitris Aragriorgs
    if instance.hotplug_info:
1385 644e5023 Dimitris Aragriorgs
      kvm_cmd, serialized_nics, hvparams, serialized_blockdevs = loaded_runtime
1386 644e5023 Dimitris Aragriorgs
      block_devices = [(objects.Disk.FromDict(sdisk), link)
1387 644e5023 Dimitris Aragriorgs
                       for sdisk, link in serialized_blockdevs]
1388 644e5023 Dimitris Aragriorgs
    else:
1389 644e5023 Dimitris Aragriorgs
      kvm_cmd, serialized_nics, hvparams = loaded_runtime
1390 644e5023 Dimitris Aragriorgs
1391 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
1392 644e5023 Dimitris Aragriorgs
1393 644e5023 Dimitris Aragriorgs
    if instance.hotplug_info:
1394 644e5023 Dimitris Aragriorgs
      return (kvm_cmd, kvm_nics, hvparams, block_devices)
1395 644e5023 Dimitris Aragriorgs
    else:
1396 644e5023 Dimitris Aragriorgs
      return (kvm_cmd, kvm_nics, hvparams)
1397 38e250ba Guido Trotter
1398 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1399 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
1400 76431533 Guido Trotter

1401 76431533 Guido Trotter
    @type name: string
1402 76431533 Guido Trotter
    @param name: instance name
1403 76431533 Guido Trotter
    @type kvm_cmd: list of strings
1404 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
1405 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
1406 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
1407 76431533 Guido Trotter

1408 76431533 Guido Trotter
    """
1409 5d9bfd87 Apollon Oikonomopoulos
    try:
1410 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
1411 5d9bfd87 Apollon Oikonomopoulos
    finally:
1412 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
1413 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
1414 5d9bfd87 Apollon Oikonomopoulos
1415 76431533 Guido Trotter
    if result.failed:
1416 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
1417 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
1418 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
1419 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
1420 76431533 Guido Trotter
1421 30e42c4e Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
1422 839642c2 Iustin Pop
    """Execute a KVM cmd, after completing it with some last minute data.
1423 ee5f20b0 Guido Trotter

1424 30e42c4e Guido Trotter
    @type incoming: tuple of strings
1425 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
1426 30e42c4e Guido Trotter

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

1641 ee5f20b0 Guido Trotter
    """
1642 5905901c Iustin Pop
    self._CheckDown(instance.name)
1643 7238edb5 Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
1644 7238edb5 Iustin Pop
                                           startup_paused)
1645 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1646 ee5f20b0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
1647 ee5f20b0 Guido Trotter
1648 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
1649 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
1650 6567aff3 Guido Trotter

1651 6567aff3 Guido Trotter
    """
1652 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
1653 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
1654 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
1655 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
1656 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
1657 6567aff3 Guido Trotter
    if result.failed:
1658 6567aff3 Guido Trotter
      msg = ("Failed to send command '%s' to instance %s."
1659 6567aff3 Guido Trotter
             " output: %s, error: %s, fail_reason: %s" %
1660 9798fcae Guido Trotter
             (command, instance_name,
1661 9798fcae Guido Trotter
              result.stdout, result.stderr, result.fail_reason))
1662 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
1663 6567aff3 Guido Trotter
1664 6567aff3 Guido Trotter
    return result
1665 6567aff3 Guido Trotter
1666 2435f63b Dimitris Aragiorgis
  def _FindFreePCISlot(self, instance_name):
1667 2435f63b Dimitris Aragiorgis
    slots = bitarray(32)
1668 2435f63b Dimitris Aragiorgis
    slots.setall(False)
1669 2435f63b Dimitris Aragiorgis
    output = self._CallMonitorCommand(instance_name, self._INFO_PCI_CMD)
1670 2435f63b Dimitris Aragiorgis
    for line in output.stdout.splitlines():
1671 2435f63b Dimitris Aragiorgis
      match = self._INFO_PCI_RE.search(line)
1672 2435f63b Dimitris Aragiorgis
      if match:
1673 2435f63b Dimitris Aragiorgis
        slot = int(match.group(1))
1674 2435f63b Dimitris Aragiorgis
        slots[slot] = True
1675 2435f63b Dimitris Aragiorgis
1676 2435f63b Dimitris Aragiorgis
    free = slots.search(FREE, 1)
1677 2435f63b Dimitris Aragiorgis
    if not free:
1678 2435f63b Dimitris Aragiorgis
      raise errors.HypervisorError("All PCI slots occupied")
1679 2435f63b Dimitris Aragiorgis
1680 2435f63b Dimitris Aragiorgis
    return int(free[0])
1681 2435f63b Dimitris Aragiorgis
1682 2435f63b Dimitris Aragiorgis
  def _HotplugEnabled(self, instance_name):
1683 2435f63b Dimitris Aragiorgis
    if not self._InstancePidAlive(instance_name)[2]:
1684 2435f63b Dimitris Aragiorgis
      logging.info("Cannot hotplug. Instance %s not alive", instance_name)
1685 2435f63b Dimitris Aragiorgis
      return False
1686 2435f63b Dimitris Aragiorgis
1687 2435f63b Dimitris Aragiorgis
    _, v_major, v_min, _ = self._GetKVMVersion()
1688 2435f63b Dimitris Aragiorgis
    return (v_major, v_min) >= (1, 0)
1689 2435f63b Dimitris Aragiorgis
1690 59a5de9e Dimitris Aragiorgis
  def HotAddDisk(self, instance, disk, dev_path, _):
1691 1642a1d0 Dimitris Aragiorgis
    """Hotadd new disk to the VM
1692 1642a1d0 Dimitris Aragiorgis

1693 1642a1d0 Dimitris Aragiorgis
    """
1694 2435f63b Dimitris Aragiorgis
    if self._HotplugEnabled(instance.name):
1695 2435f63b Dimitris Aragiorgis
      disk.pci = self._FindFreePCISlot(instance.name)
1696 1642a1d0 Dimitris Aragiorgis
      idx = disk.idx
1697 1642a1d0 Dimitris Aragiorgis
      command = ("drive_add dummy file=%s,if=none,id=drive%d,format=raw" %
1698 1642a1d0 Dimitris Aragiorgis
                 (dev_path, idx))
1699 1642a1d0 Dimitris Aragiorgis
1700 59a5de9e Dimitris Aragiorgis
      logging.info("Run cmd %s", command)
1701 1642a1d0 Dimitris Aragiorgis
      output = self._CallMonitorCommand(instance.name, command)
1702 1642a1d0 Dimitris Aragiorgis
1703 1642a1d0 Dimitris Aragiorgis
      command = ("device_add virtio-blk-pci,bus=pci.0,addr=%s,"
1704 1642a1d0 Dimitris Aragiorgis
                 "drive=drive%d,id=virtio-blk-pci.%d"
1705 1642a1d0 Dimitris Aragiorgis
                 % (hex(disk.pci), idx, idx))
1706 59a5de9e Dimitris Aragiorgis
      logging.info("Run cmd %s", command)
1707 1642a1d0 Dimitris Aragiorgis
      output = self._CallMonitorCommand(instance.name, command)
1708 1642a1d0 Dimitris Aragiorgis
      for line in output.stdout.splitlines():
1709 59a5de9e Dimitris Aragiorgis
        logging.info("%s", line)
1710 1642a1d0 Dimitris Aragiorgis
1711 1642a1d0 Dimitris Aragiorgis
      (kvm_cmd, kvm_nics,
1712 1642a1d0 Dimitris Aragiorgis
       hvparams, block_devices) = self._LoadKVMRuntime(instance)
1713 1642a1d0 Dimitris Aragiorgis
      block_devices.append((disk, dev_path))
1714 1642a1d0 Dimitris Aragiorgis
      new_kvm_runtime = (kvm_cmd, kvm_nics, hvparams, block_devices)
1715 1642a1d0 Dimitris Aragiorgis
      self._SaveKVMRuntime(instance, new_kvm_runtime)
1716 1642a1d0 Dimitris Aragiorgis
1717 2435f63b Dimitris Aragiorgis
    return disk.pci
1718 1642a1d0 Dimitris Aragiorgis
1719 59a5de9e Dimitris Aragiorgis
  def HotDelDisk(self, instance, disk, _):
1720 1642a1d0 Dimitris Aragiorgis
    """Hotdel disk to the VM
1721 1642a1d0 Dimitris Aragiorgis

1722 1642a1d0 Dimitris Aragiorgis
    """
1723 2435f63b Dimitris Aragiorgis
    if self._HotplugEnabled(instance.name):
1724 1642a1d0 Dimitris Aragiorgis
      idx = disk.idx
1725 1642a1d0 Dimitris Aragiorgis
1726 1642a1d0 Dimitris Aragiorgis
      command = "device_del virtio-blk-pci.%d" % idx
1727 59a5de9e Dimitris Aragiorgis
      logging.info("Run cmd %s", command)
1728 1642a1d0 Dimitris Aragiorgis
      output = self._CallMonitorCommand(instance.name, command)
1729 1642a1d0 Dimitris Aragiorgis
      for line in output.stdout.splitlines():
1730 59a5de9e Dimitris Aragiorgis
        logging.info("%s", line)
1731 1642a1d0 Dimitris Aragiorgis
1732 1642a1d0 Dimitris Aragiorgis
      command = "drive_del drive%d" % idx
1733 59a5de9e Dimitris Aragiorgis
      logging.info("Run cmd %s", command)
1734 1642a1d0 Dimitris Aragiorgis
      #output = self._CallMonitorCommand(instance.name, command)
1735 1642a1d0 Dimitris Aragiorgis
      #for line in output.stdout.splitlines():
1736 1642a1d0 Dimitris Aragiorgis
      #  logging.info("%s" % line)
1737 1642a1d0 Dimitris Aragiorgis
1738 1642a1d0 Dimitris Aragiorgis
      (kvm_cmd, kvm_nics,
1739 1642a1d0 Dimitris Aragiorgis
       hvparams, block_devices) = self._LoadKVMRuntime(instance)
1740 1642a1d0 Dimitris Aragiorgis
      rem  = [(d, p) for d, p in block_devices
1741 1642a1d0 Dimitris Aragiorgis
                     if d.idx is not None and d.idx == idx]
1742 1642a1d0 Dimitris Aragiorgis
      try:
1743 1642a1d0 Dimitris Aragiorgis
        block_devices.remove(rem[0])
1744 1642a1d0 Dimitris Aragiorgis
      except (ValueError, IndexError):
1745 1642a1d0 Dimitris Aragiorgis
        logging.info("Disk with %d idx disappeared from runtime file", idx)
1746 1642a1d0 Dimitris Aragiorgis
      new_kvm_runtime = (kvm_cmd, kvm_nics, hvparams, block_devices)
1747 1642a1d0 Dimitris Aragiorgis
      self._SaveKVMRuntime(instance, new_kvm_runtime)
1748 1642a1d0 Dimitris Aragiorgis
1749 1642a1d0 Dimitris Aragiorgis
  def HotAddNic(self, instance, nic, seq):
1750 1642a1d0 Dimitris Aragiorgis
    """Hotadd new nic to the VM
1751 1642a1d0 Dimitris Aragiorgis

1752 1642a1d0 Dimitris Aragiorgis
    """
1753 2435f63b Dimitris Aragiorgis
    if self._HotplugEnabled(instance.name):
1754 2435f63b Dimitris Aragiorgis
      nic.pci = self._FindFreePCISlot(instance.name)
1755 1642a1d0 Dimitris Aragiorgis
      mac = nic.mac
1756 1642a1d0 Dimitris Aragiorgis
      idx = nic.idx
1757 1642a1d0 Dimitris Aragiorgis
1758 1642a1d0 Dimitris Aragiorgis
      (tap, fd) = _OpenTap()
1759 1642a1d0 Dimitris Aragiorgis
      logging.info("%s %d", tap, fd)
1760 1642a1d0 Dimitris Aragiorgis
1761 1642a1d0 Dimitris Aragiorgis
      self._PassTapFd(instance, fd, nic)
1762 1642a1d0 Dimitris Aragiorgis
1763 1642a1d0 Dimitris Aragiorgis
      command = ("netdev_add tap,id=netdev%d,fd=netdev%d"
1764 1642a1d0 Dimitris Aragiorgis
                 % (idx, idx))
1765 59a5de9e Dimitris Aragiorgis
      logging.info("Run cmd %s", command)
1766 1642a1d0 Dimitris Aragiorgis
      output = self._CallMonitorCommand(instance.name, command)
1767 1642a1d0 Dimitris Aragiorgis
      for line in output.stdout.splitlines():
1768 59a5de9e Dimitris Aragiorgis
        logging.info("%s", line)
1769 1642a1d0 Dimitris Aragiorgis
1770 1642a1d0 Dimitris Aragiorgis
      command = ("device_add virtio-net-pci,bus=pci.0,addr=%s,mac=%s,"
1771 1642a1d0 Dimitris Aragiorgis
                 "netdev=netdev%d,id=virtio-net-pci.%d"
1772 1642a1d0 Dimitris Aragiorgis
                 % (hex(nic.pci), mac, idx, idx))
1773 59a5de9e Dimitris Aragiorgis
      logging.info("Run cmd %s", command)
1774 1642a1d0 Dimitris Aragiorgis
      output = self._CallMonitorCommand(instance.name, command)
1775 1642a1d0 Dimitris Aragiorgis
      for line in output.stdout.splitlines():
1776 59a5de9e Dimitris Aragiorgis
        logging.info("%s", line)
1777 1642a1d0 Dimitris Aragiorgis
1778 1642a1d0 Dimitris Aragiorgis
      self._ConfigureNIC(instance, seq, nic, tap)
1779 1642a1d0 Dimitris Aragiorgis
1780 1642a1d0 Dimitris Aragiorgis
      (kvm_cmd, kvm_nics,
1781 1642a1d0 Dimitris Aragiorgis
       hvparams, block_devices) = self._LoadKVMRuntime(instance)
1782 1642a1d0 Dimitris Aragiorgis
      kvm_nics.append(nic)
1783 1642a1d0 Dimitris Aragiorgis
      new_kvm_runtime = (kvm_cmd, kvm_nics, hvparams, block_devices)
1784 1642a1d0 Dimitris Aragiorgis
      self._SaveKVMRuntime(instance, new_kvm_runtime)
1785 1642a1d0 Dimitris Aragiorgis
1786 2435f63b Dimitris Aragiorgis
    return nic.pci
1787 1642a1d0 Dimitris Aragiorgis
1788 59a5de9e Dimitris Aragiorgis
  def HotDelNic(self, instance, nic, _):
1789 1642a1d0 Dimitris Aragiorgis
    """Hotadd new nic to the VM
1790 1642a1d0 Dimitris Aragiorgis

1791 1642a1d0 Dimitris Aragiorgis
    """
1792 2435f63b Dimitris Aragiorgis
    if self._HotplugEnabled(instance.name):
1793 1642a1d0 Dimitris Aragiorgis
      idx = nic.idx
1794 1642a1d0 Dimitris Aragiorgis
1795 1642a1d0 Dimitris Aragiorgis
      command = "device_del virtio-net-pci.%d" % idx
1796 59a5de9e Dimitris Aragiorgis
      logging.info("Run cmd %s", command)
1797 1642a1d0 Dimitris Aragiorgis
      output = self._CallMonitorCommand(instance.name, command)
1798 1642a1d0 Dimitris Aragiorgis
      for line in output.stdout.splitlines():
1799 59a5de9e Dimitris Aragiorgis
        logging.info("%s", line)
1800 1642a1d0 Dimitris Aragiorgis
1801 1642a1d0 Dimitris Aragiorgis
      command = "netdev_del netdev%d" % idx
1802 59a5de9e Dimitris Aragiorgis
      logging.info("Run cmd %s", command)
1803 1642a1d0 Dimitris Aragiorgis
      output = self._CallMonitorCommand(instance.name, command)
1804 1642a1d0 Dimitris Aragiorgis
      for line in output.stdout.splitlines():
1805 59a5de9e Dimitris Aragiorgis
        logging.info("%s", line)
1806 1642a1d0 Dimitris Aragiorgis
1807 1642a1d0 Dimitris Aragiorgis
      (kvm_cmd, kvm_nics,
1808 1642a1d0 Dimitris Aragiorgis
       hvparams, block_devices) = self._LoadKVMRuntime(instance)
1809 1642a1d0 Dimitris Aragiorgis
      rem  = [n for n in kvm_nics if n.idx is not None and n.idx == nic.idx]
1810 1642a1d0 Dimitris Aragiorgis
      try:
1811 1642a1d0 Dimitris Aragiorgis
        kvm_nics.remove(rem[0])
1812 1642a1d0 Dimitris Aragiorgis
      except (ValueError, IndexError):
1813 1642a1d0 Dimitris Aragiorgis
        logging.info("NIC with %d idx disappeared from runtime file", nic.idx)
1814 1642a1d0 Dimitris Aragiorgis
      new_kvm_runtime = (kvm_cmd, kvm_nics, hvparams, block_devices)
1815 1642a1d0 Dimitris Aragiorgis
      self._SaveKVMRuntime(instance, new_kvm_runtime)
1816 1642a1d0 Dimitris Aragiorgis
1817 1642a1d0 Dimitris Aragiorgis
1818 1642a1d0 Dimitris Aragiorgis
  def _PassTapFd(self, instance, fd, nic):
1819 1642a1d0 Dimitris Aragiorgis
    monsock = utils.ShellQuote(self._InstanceMonitor(instance.name))
1820 1642a1d0 Dimitris Aragiorgis
    s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
1821 1642a1d0 Dimitris Aragiorgis
    s.connect(monsock)
1822 1642a1d0 Dimitris Aragiorgis
    idx = nic.idx
1823 1642a1d0 Dimitris Aragiorgis
    command = "getfd netdev%d\n" % idx
1824 1642a1d0 Dimitris Aragiorgis
    fds = [fd]
1825 1642a1d0 Dimitris Aragiorgis
    logging.info("%s", fds)
1826 1642a1d0 Dimitris Aragiorgis
    fdsend.sendfds(s, command, fds = fds)
1827 1642a1d0 Dimitris Aragiorgis
    s.close()
1828 1642a1d0 Dimitris Aragiorgis
1829 b52d85c1 Guido Trotter
  @classmethod
1830 585c8187 Guido Trotter
  def _ParseKVMVersion(cls, text):
1831 585c8187 Guido Trotter
    """Parse the KVM version from the --help output.
1832 585c8187 Guido Trotter

1833 585c8187 Guido Trotter
    @type text: string
1834 585c8187 Guido Trotter
    @param text: output of kvm --help
1835 585c8187 Guido Trotter
    @return: (version, v_maj, v_min, v_rev)
1836 5c3d5dfd Iustin Pop
    @raise errors.HypervisorError: when the KVM version cannot be retrieved
1837 585c8187 Guido Trotter

1838 585c8187 Guido Trotter
    """
1839 585c8187 Guido Trotter
    match = cls._VERSION_RE.search(text.splitlines()[0])
1840 585c8187 Guido Trotter
    if not match:
1841 585c8187 Guido Trotter
      raise errors.HypervisorError("Unable to get KVM version")
1842 585c8187 Guido Trotter
1843 585c8187 Guido Trotter
    v_all = match.group(0)
1844 585c8187 Guido Trotter
    v_maj = int(match.group(1))
1845 585c8187 Guido Trotter
    v_min = int(match.group(2))
1846 585c8187 Guido Trotter
    if match.group(4):
1847 585c8187 Guido Trotter
      v_rev = int(match.group(4))
1848 585c8187 Guido Trotter
    else:
1849 585c8187 Guido Trotter
      v_rev = 0
1850 585c8187 Guido Trotter
    return (v_all, v_maj, v_min, v_rev)
1851 585c8187 Guido Trotter
1852 585c8187 Guido Trotter
  @classmethod
1853 b52d85c1 Guido Trotter
  def _GetKVMVersion(cls):
1854 d7e4a2b1 Andrea Spadaccini
    """Return the installed KVM version.
1855 b52d85c1 Guido Trotter

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

1859 b52d85c1 Guido Trotter
    """
1860 b52d85c1 Guido Trotter
    result = utils.RunCmd([constants.KVM_PATH, "--help"])
1861 b52d85c1 Guido Trotter
    if result.failed:
1862 440351f8 Andrea Spadaccini
      raise errors.HypervisorError("Unable to get KVM version")
1863 585c8187 Guido Trotter
    return cls._ParseKVMVersion(result.output)
1864 b52d85c1 Guido Trotter
1865 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
1866 eb58f9b1 Guido Trotter
    """Stop an instance.
1867 eb58f9b1 Guido Trotter

1868 eb58f9b1 Guido Trotter
    """
1869 bbcf7ad0 Iustin Pop
    if name is not None and not force:
1870 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
1871 bbcf7ad0 Iustin Pop
    if name is None:
1872 bbcf7ad0 Iustin Pop
      name = instance.name
1873 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
1874 bbcf7ad0 Iustin Pop
    else:
1875 bbcf7ad0 Iustin Pop
      acpi = False
1876 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
1877 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
1878 bbcf7ad0 Iustin Pop
      if force or not acpi:
1879 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
1880 eb58f9b1 Guido Trotter
      else:
1881 d0c8c01d Iustin Pop
        self._CallMonitorCommand(name, "system_powerdown")
1882 eb58f9b1 Guido Trotter
1883 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
1884 8904b35c Guido Trotter
    """Cleanup after a stopped instance
1885 8904b35c Guido Trotter

1886 8904b35c Guido Trotter
    """
1887 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1888 8904b35c Guido Trotter
    if pid > 0 and alive:
1889 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
1890 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1891 eb58f9b1 Guido Trotter
1892 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
1893 eb58f9b1 Guido Trotter
    """Reboot an instance.
1894 eb58f9b1 Guido Trotter

1895 eb58f9b1 Guido Trotter
    """
1896 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
1897 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
1898 eb58f9b1 Guido Trotter
    # to shutdown and restart.
1899 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
1900 1f8b3a27 Guido Trotter
    if not alive:
1901 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
1902 78411c60 Iustin Pop
                                   " not running" % instance.name)
1903 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
1904 f02881e0 Guido Trotter
    # ...first load it...
1905 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
1906 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
1907 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
1908 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
1909 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
1910 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1911 f02881e0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
1912 eb58f9b1 Guido Trotter
1913 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
1914 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
1915 30e42c4e Guido Trotter

1916 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1917 30e42c4e Guido Trotter
    @param instance: instance to be migrated
1918 30e42c4e Guido Trotter
    @rtype: string
1919 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
1920 30e42c4e Guido Trotter

1921 30e42c4e Guido Trotter
    """
1922 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
1923 30e42c4e Guido Trotter
1924 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
1925 30e42c4e Guido Trotter
    """Prepare to accept an instance.
1926 30e42c4e Guido Trotter

1927 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1928 30e42c4e Guido Trotter
    @param instance: instance to be accepted
1929 30e42c4e Guido Trotter
    @type info: string
1930 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
1931 30e42c4e Guido Trotter
    @type target: string
1932 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
1933 30e42c4e Guido Trotter

1934 30e42c4e Guido Trotter
    """
1935 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1936 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1937 30e42c4e Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
1938 30e42c4e Guido Trotter
1939 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
1940 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
1941 30e42c4e Guido Trotter

1942 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
1943 30e42c4e Guido Trotter

1944 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1945 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
1946 30e42c4e Guido Trotter

1947 30e42c4e Guido Trotter
    """
1948 30e42c4e Guido Trotter
    if success:
1949 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1950 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
1951 5d9bfd87 Apollon Oikonomopoulos
1952 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
1953 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1954 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
1955 cc8a8ed7 Apollon Oikonomopoulos
          continue
1956 5d9bfd87 Apollon Oikonomopoulos
        try:
1957 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
1958 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
1959 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
1960 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
1961 5d9bfd87 Apollon Oikonomopoulos
          continue
1962 5d9bfd87 Apollon Oikonomopoulos
        try:
1963 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
1964 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
1965 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
1966 5d9bfd87 Apollon Oikonomopoulos
1967 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
1968 30e42c4e Guido Trotter
    else:
1969 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
1970 30e42c4e Guido Trotter
1971 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
1972 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
1973 30e42c4e Guido Trotter

1974 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
1975 30e42c4e Guido Trotter
    currently running.
1976 30e42c4e Guido Trotter

1977 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
1978 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
1979 30e42c4e Guido Trotter
    @type target: string
1980 30e42c4e Guido Trotter
    @param target: ip address of the target node
1981 30e42c4e Guido Trotter
    @type live: boolean
1982 30e42c4e Guido Trotter
    @param live: perform a live migration
1983 30e42c4e Guido Trotter

1984 30e42c4e Guido Trotter
    """
1985 58d38b02 Iustin Pop
    instance_name = instance.name
1986 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
1987 6a1434d7 Andrea Spadaccini
    _, _, alive = self._InstancePidAlive(instance_name)
1988 30e42c4e Guido Trotter
    if not alive:
1989 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
1990 30e42c4e Guido Trotter
1991 30e42c4e Guido Trotter
    if not live:
1992 d0c8c01d Iustin Pop
      self._CallMonitorCommand(instance_name, "stop")
1993 30e42c4e Guido Trotter
1994 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_speed %dm" %
1995 e43d4f9f Apollon Oikonomopoulos
        instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1996 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
1997 e43d4f9f Apollon Oikonomopoulos
1998 d0c8c01d Iustin Pop
    migrate_command = ("migrate_set_downtime %dms" %
1999 e43d4f9f Apollon Oikonomopoulos
        instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
2000 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
2001 e43d4f9f Apollon Oikonomopoulos
2002 d0c8c01d Iustin Pop
    migrate_command = "migrate -d tcp:%s:%s" % (target, port)
2003 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
2004 30e42c4e Guido Trotter
2005 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
2006 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
2007 6a1434d7 Andrea Spadaccini

2008 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2009 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
2010 6a1434d7 Andrea Spadaccini
    @type success: bool
2011 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
2012 6a1434d7 Andrea Spadaccini
    @type live: bool
2013 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
2014 6a1434d7 Andrea Spadaccini

2015 6a1434d7 Andrea Spadaccini
    """
2016 6a1434d7 Andrea Spadaccini
    if success:
2017 6a1434d7 Andrea Spadaccini
      pidfile, pid, _ = self._InstancePidAlive(instance.name)
2018 6a1434d7 Andrea Spadaccini
      utils.KillProcess(pid)
2019 6a1434d7 Andrea Spadaccini
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
2020 6a1434d7 Andrea Spadaccini
    elif live:
2021 6a1434d7 Andrea Spadaccini
      self._CallMonitorCommand(instance.name, self._CONT_CMD)
2022 6a1434d7 Andrea Spadaccini
2023 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
2024 6a1434d7 Andrea Spadaccini
    """Get the migration status
2025 6a1434d7 Andrea Spadaccini

2026 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
2027 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
2028 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
2029 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
2030 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
2031 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
2032 6a1434d7 Andrea Spadaccini

2033 6a1434d7 Andrea Spadaccini
    """
2034 d0c8c01d Iustin Pop
    info_command = "info migrate"
2035 6a1434d7 Andrea Spadaccini
    for _ in range(self._MIGRATION_INFO_MAX_BAD_ANSWERS):
2036 6a1434d7 Andrea Spadaccini
      result = self._CallMonitorCommand(instance.name, info_command)
2037 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
2038 30e42c4e Guido Trotter
      if not match:
2039 c4e388a5 Guido Trotter
        if not result.stdout:
2040 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
2041 c4e388a5 Guido Trotter
        else:
2042 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
2043 c4e388a5 Guido Trotter
                          result.stdout)
2044 30e42c4e Guido Trotter
      else:
2045 30e42c4e Guido Trotter
        status = match.group(1)
2046 6a1434d7 Andrea Spadaccini
        if status in constants.HV_KVM_MIGRATION_VALID_STATUSES:
2047 6a1434d7 Andrea Spadaccini
          migration_status = objects.MigrationStatus(status=status)
2048 61643226 Andrea Spadaccini
          match = self._MIGRATION_PROGRESS_RE.search(result.stdout)
2049 61643226 Andrea Spadaccini
          if match:
2050 61643226 Andrea Spadaccini
            migration_status.transferred_ram = match.group("transferred")
2051 61643226 Andrea Spadaccini
            migration_status.total_ram = match.group("total")
2052 61643226 Andrea Spadaccini
2053 6a1434d7 Andrea Spadaccini
          return migration_status
2054 30e42c4e Guido Trotter
2055 6a1434d7 Andrea Spadaccini
        logging.warning("KVM: unknown migration status '%s'", status)
2056 6a1434d7 Andrea Spadaccini
2057 6a1434d7 Andrea Spadaccini
      time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
2058 6a1434d7 Andrea Spadaccini
2059 6a1434d7 Andrea Spadaccini
    return objects.MigrationStatus(status=constants.HV_MIGRATION_FAILED,
2060 6a1434d7 Andrea Spadaccini
                                  info="Too many 'info migrate' broken answers")
2061 30e42c4e Guido Trotter
2062 3d836750 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
2063 3d836750 Guido Trotter
    """Balloon an instance memory to a certain value.
2064 3d836750 Guido Trotter

2065 3d836750 Guido Trotter
    @type instance: L{objects.Instance}
2066 3d836750 Guido Trotter
    @param instance: instance to be accepted
2067 3d836750 Guido Trotter
    @type mem: int
2068 3d836750 Guido Trotter
    @param mem: actual memory size to use for instance runtime
2069 3d836750 Guido Trotter

2070 3d836750 Guido Trotter
    """
2071 3d836750 Guido Trotter
    self._CallMonitorCommand(instance.name, "balloon %d" % mem)
2072 3d836750 Guido Trotter
2073 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
2074 eb58f9b1 Guido Trotter
    """Return information about the node.
2075 eb58f9b1 Guido Trotter

2076 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
2077 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
2078 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
2079 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
2080 34fbc862 Andrea Spadaccini
          - hv_version: the hypervisor version in the form (major, minor,
2081 34fbc862 Andrea Spadaccini
                        revision)
2082 eb58f9b1 Guido Trotter

2083 eb58f9b1 Guido Trotter
    """
2084 34fbc862 Andrea Spadaccini
    result = self.GetLinuxNodeInfo()
2085 34fbc862 Andrea Spadaccini
    _, v_major, v_min, v_rev = self._GetKVMVersion()
2086 34fbc862 Andrea Spadaccini
    result[constants.HV_NODEINFO_KEY_VERSION] = (v_major, v_min, v_rev)
2087 34fbc862 Andrea Spadaccini
    return result
2088 eb58f9b1 Guido Trotter
2089 637ce7f9 Guido Trotter
  @classmethod
2090 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
2091 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
2092 eb58f9b1 Guido Trotter

2093 eb58f9b1 Guido Trotter
    """
2094 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
2095 2f4c951e Stephen Shirley
      cmd = [constants.KVM_CONSOLE_WRAPPER,
2096 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
2097 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
2098 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
2099 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
2100 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2101 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
2102 55cc0a44 Michael Hanselmann
                                     host=instance.primary_node,
2103 55cc0a44 Michael Hanselmann
                                     user=constants.GANETI_RUNAS,
2104 55cc0a44 Michael Hanselmann
                                     command=cmd)
2105 3be34f57 Guido Trotter
2106 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
2107 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
2108 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
2109 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
2110 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
2111 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
2112 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
2113 55cc0a44 Michael Hanselmann
                                     display=display)
2114 55cc0a44 Michael Hanselmann
2115 4d2cdb5a Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2116 4d2cdb5a Andrea Spadaccini
    if spice_bind:
2117 4d2cdb5a Andrea Spadaccini
      return objects.InstanceConsole(instance=instance.name,
2118 4d2cdb5a Andrea Spadaccini
                                     kind=constants.CONS_SPICE,
2119 4d2cdb5a Andrea Spadaccini
                                     host=spice_bind,
2120 4d2cdb5a Andrea Spadaccini
                                     port=instance.network_port)
2121 4d2cdb5a Andrea Spadaccini
2122 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
2123 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
2124 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
2125 55cc0a44 Michael Hanselmann
                                            instance.name))
2126 eb58f9b1 Guido Trotter
2127 eb58f9b1 Guido Trotter
  def Verify(self):
2128 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
2129 eb58f9b1 Guido Trotter

2130 eb58f9b1 Guido Trotter
    Check that the binary exists.
2131 eb58f9b1 Guido Trotter

2132 eb58f9b1 Guido Trotter
    """
2133 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
2134 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
2135 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
2136 14aa53cb Guido Trotter
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
2137 14aa53cb Guido Trotter
2138 6b5605e8 Iustin Pop
  @classmethod
2139 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
2140 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
2141 6b5605e8 Iustin Pop

2142 6b5605e8 Iustin Pop
    @type hvparams:  dict
2143 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
2144 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
2145 6b5605e8 Iustin Pop

2146 6b5605e8 Iustin Pop
    """
2147 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
2148 6b5605e8 Iustin Pop
2149 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
2150 df5ab9f0 Guido Trotter
    if kernel_path:
2151 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
2152 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
2153 205ab586 Iustin Pop
                                     " if a kernel is defined")
2154 6b5605e8 Iustin Pop
2155 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
2156 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
2157 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
2158 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
2159 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
2160 66d5dbef Guido Trotter
2161 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
2162 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
2163 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
2164 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
2165 835528af Iustin Pop
                                   " ISO path")
2166 f5118ade Iustin Pop
2167 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2168 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2169 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
2170 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
2171 d19d94db Guido Trotter
                                     " must be specified")
2172 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
2173 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
2174 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
2175 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
2176 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
2177 d19d94db Guido Trotter
2178 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2179 b451c4c7 Andrea Spadaccini
    spice_ip_version = hvparams[constants.HV_KVM_SPICE_IP_VERSION]
2180 b1cb62bd Andrea Spadaccini
    if spice_bind:
2181 b1cb62bd Andrea Spadaccini
      if spice_ip_version != constants.IFACE_NO_IP_VERSION_SPECIFIED:
2182 b1cb62bd Andrea Spadaccini
        # if an IP version is specified, the spice_bind parameter must be an
2183 b1cb62bd Andrea Spadaccini
        # IP of that family
2184 b1cb62bd Andrea Spadaccini
        if (netutils.IP4Address.IsValid(spice_bind) and
2185 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP4_VERSION):
2186 b1cb62bd Andrea Spadaccini
          raise errors.HypervisorError("spice: got an IPv4 address (%s), but"
2187 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2188 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2189 b1cb62bd Andrea Spadaccini
2190 b1cb62bd Andrea Spadaccini
        if (netutils.IP6Address.IsValid(spice_bind) and
2191 b1cb62bd Andrea Spadaccini
            spice_ip_version != constants.IP6_VERSION):
2192 b1cb62bd Andrea Spadaccini
          raise errors.HypervisorError("spice: got an IPv6 address (%s), but"
2193 b1cb62bd Andrea Spadaccini
                                       " the specified IP version is %s" %
2194 b1cb62bd Andrea Spadaccini
                                       (spice_bind, spice_ip_version))
2195 b451c4c7 Andrea Spadaccini
    else:
2196 0e1b03b9 Andrea Spadaccini
      # All the other SPICE parameters depend on spice_bind being set. Raise an
2197 0e1b03b9 Andrea Spadaccini
      # error if any of them is set without it.
2198 0e1b03b9 Andrea Spadaccini
      spice_additional_params = frozenset([
2199 0e1b03b9 Andrea Spadaccini
        constants.HV_KVM_SPICE_IP_VERSION,
2200 0e1b03b9 Andrea Spadaccini
        constants.HV_KVM_SPICE_PASSWORD_FILE,
2201 ea064d24 Andrea Spadaccini
        constants.HV_KVM_SPICE_LOSSLESS_IMG_COMPR,
2202 ea064d24 Andrea Spadaccini
        constants.HV_KVM_SPICE_JPEG_IMG_COMPR,
2203 ea064d24 Andrea Spadaccini
        constants.HV_KVM_SPICE_ZLIB_GLZ_IMG_COMPR,
2204 ea064d24 Andrea Spadaccini
        constants.HV_KVM_SPICE_STREAMING_VIDEO_DETECTION,
2205 bfe86c76 Andrea Spadaccini
        constants.HV_KVM_SPICE_USE_TLS,
2206 0e1b03b9 Andrea Spadaccini
        ])
2207 0e1b03b9 Andrea Spadaccini
      for param in spice_additional_params:
2208 0e1b03b9 Andrea Spadaccini
        if hvparams[param]:
2209 0e1b03b9 Andrea Spadaccini
          raise errors.HypervisorError("spice: %s requires %s to be set" %
2210 0e1b03b9 Andrea Spadaccini
                                       (param, constants.HV_KVM_SPICE_BIND))
2211 b1cb62bd Andrea Spadaccini
2212 d19d94db Guido Trotter
  @classmethod
2213 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
2214 d19d94db Guido Trotter
    """Check the given parameters for validity.
2215 d19d94db Guido Trotter

2216 d19d94db Guido Trotter
    @type hvparams:  dict
2217 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
2218 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
2219 d19d94db Guido Trotter

2220 d19d94db Guido Trotter
    """
2221 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
2222 d19d94db Guido Trotter
2223 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
2224 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
2225 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
2226 d19d94db Guido Trotter
      try:
2227 1feb39ec Guido Trotter
        pwd.getpwnam(username)
2228 d19d94db Guido Trotter
      except KeyError:
2229 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
2230 d19d94db Guido Trotter
                                     % username)
2231 d19d94db Guido Trotter
2232 b1cb62bd Andrea Spadaccini
    spice_bind = hvparams[constants.HV_KVM_SPICE_BIND]
2233 b1cb62bd Andrea Spadaccini
    if spice_bind:
2234 b1cb62bd Andrea Spadaccini
      # only one of VNC and SPICE can be used currently.
2235 b1cb62bd Andrea Spadaccini
      if hvparams[constants.HV_VNC_BIND_ADDRESS]:
2236 b1cb62bd Andrea Spadaccini
        raise errors.HypervisorError("both SPICE and VNC are configured, but"
2237 b1cb62bd Andrea Spadaccini
                                     " only one of them can be used at a"
2238 b1cb62bd Andrea Spadaccini
                                     " given time.")
2239 b1cb62bd Andrea Spadaccini
2240 b1cb62bd Andrea Spadaccini
      # KVM version should be >= 0.14.0
2241 b1cb62bd Andrea Spadaccini
      _, v_major, v_min, _ = cls._GetKVMVersion()
2242 b1cb62bd Andrea Spadaccini
      if (v_major, v_min) < (0, 14):
2243 b1cb62bd Andrea Spadaccini
        raise errors.HypervisorError("spice is configured, but it is not"
2244 b1cb62bd Andrea Spadaccini
                                     " available in versions of KVM < 0.14")
2245 b1cb62bd Andrea Spadaccini
2246 b1cb62bd Andrea Spadaccini
      # if spice_bind is not an IP address, it must be a valid interface
2247 b1cb62bd Andrea Spadaccini
      bound_to_addr = (netutils.IP4Address.IsValid(spice_bind)
2248 b1cb62bd Andrea Spadaccini
                       or netutils.IP6Address.IsValid(spice_bind))
2249 b1cb62bd Andrea Spadaccini
      if not bound_to_addr and not netutils.IsValidInterface(spice_bind):
2250 b1cb62bd Andrea Spadaccini
        raise errors.HypervisorError("spice: the %s parameter must be either"
2251 b1cb62bd Andrea Spadaccini
                                     " a valid IP address or interface name" %
2252 b1cb62bd Andrea Spadaccini
                                     constants.HV_KVM_SPICE_BIND)
2253 b1cb62bd Andrea Spadaccini
2254 f5118ade Iustin Pop
  @classmethod
2255 f5118ade Iustin Pop
  def PowercycleNode(cls):
2256 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
2257 f5118ade Iustin Pop

2258 f5118ade Iustin Pop
    """
2259 f5118ade Iustin Pop
    cls.LinuxPowercycle()