Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ e5395072

History | View | Annotate | Download (41.6 kB)

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

24 eb58f9b1 Guido Trotter
"""
25 eb58f9b1 Guido Trotter
26 547a63b7 Balazs Lecz
import errno
27 eb58f9b1 Guido Trotter
import os
28 eb58f9b1 Guido Trotter
import os.path
29 eb58f9b1 Guido Trotter
import re
30 eb58f9b1 Guido Trotter
import tempfile
31 6567aff3 Guido Trotter
import time
32 30e42c4e Guido Trotter
import logging
33 d19d94db Guido Trotter
import pwd
34 199b2053 Apollon Oikonomopoulos
import struct
35 199b2053 Apollon Oikonomopoulos
import fcntl
36 5d9bfd87 Apollon Oikonomopoulos
import shutil
37 eb58f9b1 Guido Trotter
38 eb58f9b1 Guido Trotter
from ganeti import utils
39 eb58f9b1 Guido Trotter
from ganeti import constants
40 eb58f9b1 Guido Trotter
from ganeti import errors
41 38e250ba Guido Trotter
from ganeti import serializer
42 38e250ba Guido Trotter
from ganeti import objects
43 76431533 Guido Trotter
from ganeti import uidpool
44 76431533 Guido Trotter
from ganeti import ssconf
45 eb58f9b1 Guido Trotter
from ganeti.hypervisor import hv_base
46 a744b676 Manuel Franceschini
from ganeti import netutils
47 5d9bfd87 Apollon Oikonomopoulos
from ganeti.utils import wrapper as utils_wrapper
48 eb58f9b1 Guido Trotter
49 eb58f9b1 Guido Trotter
50 748e4b5a Michael Hanselmann
_KVM_NETWORK_SCRIPT = constants.SYSCONFDIR + "/ganeti/kvm-vif-bridge"
51 748e4b5a Michael Hanselmann
52 199b2053 Apollon Oikonomopoulos
# TUN/TAP driver constants, taken from <linux/if_tun.h>
53 199b2053 Apollon Oikonomopoulos
# They are architecture-independent and already hardcoded in qemu-kvm source,
54 199b2053 Apollon Oikonomopoulos
# so we can safely include them here.
55 199b2053 Apollon Oikonomopoulos
TUNSETIFF = 0x400454ca
56 199b2053 Apollon Oikonomopoulos
TUNGETIFF = 0x800454d2
57 199b2053 Apollon Oikonomopoulos
TUNGETFEATURES = 0x800454cf
58 199b2053 Apollon Oikonomopoulos
IFF_TAP = 0x0002
59 199b2053 Apollon Oikonomopoulos
IFF_NO_PI = 0x1000
60 199b2053 Apollon Oikonomopoulos
IFF_VNET_HDR = 0x4000
61 199b2053 Apollon Oikonomopoulos
62 199b2053 Apollon Oikonomopoulos
63 199b2053 Apollon Oikonomopoulos
def _ProbeTapVnetHdr(fd):
64 199b2053 Apollon Oikonomopoulos
  """Check whether to enable the IFF_VNET_HDR flag.
65 199b2053 Apollon Oikonomopoulos

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

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

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

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

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

106 199b2053 Apollon Oikonomopoulos
  """
107 199b2053 Apollon Oikonomopoulos
  try:
108 199b2053 Apollon Oikonomopoulos
    tapfd = os.open("/dev/net/tun", os.O_RDWR)
109 199b2053 Apollon Oikonomopoulos
  except EnvironmentError:
110 199b2053 Apollon Oikonomopoulos
    raise errors.HypervisorError("Failed to open /dev/net/tun")
111 199b2053 Apollon Oikonomopoulos
112 199b2053 Apollon Oikonomopoulos
  flags = IFF_TAP | IFF_NO_PI
113 199b2053 Apollon Oikonomopoulos
114 199b2053 Apollon Oikonomopoulos
  if vnet_hdr and _ProbeTapVnetHdr(tapfd):
115 199b2053 Apollon Oikonomopoulos
    flags |= IFF_VNET_HDR
116 199b2053 Apollon Oikonomopoulos
117 199b2053 Apollon Oikonomopoulos
  # The struct ifreq ioctl request (see netdevice(7))
118 199b2053 Apollon Oikonomopoulos
  ifr = struct.pack("16sh", "", flags)
119 199b2053 Apollon Oikonomopoulos
120 199b2053 Apollon Oikonomopoulos
  try:
121 199b2053 Apollon Oikonomopoulos
    res = fcntl.ioctl(tapfd, TUNSETIFF, ifr)
122 199b2053 Apollon Oikonomopoulos
  except EnvironmentError:
123 199b2053 Apollon Oikonomopoulos
    raise errors.HypervisorError("Failed to allocate a new TAP device")
124 199b2053 Apollon Oikonomopoulos
125 199b2053 Apollon Oikonomopoulos
  # Get the interface name from the ioctl
126 199b2053 Apollon Oikonomopoulos
  ifname = struct.unpack("16sh", res)[0].strip("\x00")
127 199b2053 Apollon Oikonomopoulos
  return (ifname, tapfd)
128 199b2053 Apollon Oikonomopoulos
129 748e4b5a Michael Hanselmann
130 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
131 c4469f75 Guido Trotter
  """KVM hypervisor interface"""
132 d271c6fd Iustin Pop
  CAN_MIGRATE = True
133 eb58f9b1 Guido Trotter
134 eb58f9b1 Guido Trotter
  _ROOT_DIR = constants.RUN_GANETI_DIR + "/kvm-hypervisor"
135 a1d79fc6 Guido Trotter
  _PIDS_DIR = _ROOT_DIR + "/pid" # contains live instances pids
136 7548396c Guido Trotter
  _UIDS_DIR = _ROOT_DIR + "/uid" # contains instances reserved uids
137 a1d79fc6 Guido Trotter
  _CTRL_DIR = _ROOT_DIR + "/ctrl" # contains instances control sockets
138 a1d79fc6 Guido Trotter
  _CONF_DIR = _ROOT_DIR + "/conf" # contains instances startup data
139 5d9bfd87 Apollon Oikonomopoulos
  _NICS_DIR = _ROOT_DIR + "/nic" # contains instances nic <-> tap associations
140 547a63b7 Balazs Lecz
  # KVM instances with chroot enabled are started in empty chroot directories.
141 547a63b7 Balazs Lecz
  _CHROOT_DIR = _ROOT_DIR + "/chroot" # for empty chroot directories
142 547a63b7 Balazs Lecz
  # After an instance is stopped, its chroot directory is removed.
143 547a63b7 Balazs Lecz
  # If the chroot directory is not empty, it can't be removed.
144 547a63b7 Balazs Lecz
  # A non-empty chroot directory indicates a possible security incident.
145 547a63b7 Balazs Lecz
  # To support forensics, the non-empty chroot directory is quarantined in
146 547a63b7 Balazs Lecz
  # a separate directory, called 'chroot-quarantine'.
147 547a63b7 Balazs Lecz
  _CHROOT_QUARANTINE_DIR = _ROOT_DIR + "/chroot-quarantine"
148 5d9bfd87 Apollon Oikonomopoulos
  _DIRS = [_ROOT_DIR, _PIDS_DIR, _UIDS_DIR, _CTRL_DIR, _CONF_DIR, _NICS_DIR,
149 547a63b7 Balazs Lecz
           _CHROOT_DIR, _CHROOT_QUARANTINE_DIR]
150 eb58f9b1 Guido Trotter
151 205ab586 Iustin Pop
  PARAMETERS = {
152 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK,
153 205ab586 Iustin Pop
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
154 205ab586 Iustin Pop
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
155 205ab586 Iustin Pop
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
156 205ab586 Iustin Pop
    constants.HV_ACPI: hv_base.NO_CHECK,
157 205ab586 Iustin Pop
    constants.HV_SERIAL_CONSOLE: hv_base.NO_CHECK,
158 d73ef63f Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS:
159 8b312c1d Manuel Franceschini
      (False, lambda x: (netutils.IP4Address.IsValid(x) or
160 8b312c1d Manuel Franceschini
                         utils.IsNormAbsPath(x)),
161 d73ef63f Michael Hanselmann
       "the VNC bind address must be either a valid IP address or an absolute"
162 d73ef63f Michael Hanselmann
       " pathname", None, None),
163 205ab586 Iustin Pop
    constants.HV_VNC_TLS: hv_base.NO_CHECK,
164 205ab586 Iustin Pop
    constants.HV_VNC_X509: hv_base.OPT_DIR_CHECK,
165 205ab586 Iustin Pop
    constants.HV_VNC_X509_VERIFY: hv_base.NO_CHECK,
166 6e6bb8d5 Guido Trotter
    constants.HV_VNC_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
167 205ab586 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
168 d73ef63f Michael Hanselmann
    constants.HV_BOOT_ORDER:
169 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
170 d73ef63f Michael Hanselmann
    constants.HV_NIC_TYPE:
171 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
172 d73ef63f Michael Hanselmann
    constants.HV_DISK_TYPE:
173 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
174 d73ef63f Michael Hanselmann
    constants.HV_USB_MOUSE:
175 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
176 78411c60 Iustin Pop
    constants.HV_MIGRATION_PORT: hv_base.NET_PORT_CHECK,
177 e43d4f9f Apollon Oikonomopoulos
    constants.HV_MIGRATION_BANDWIDTH: hv_base.NO_CHECK,
178 e43d4f9f Apollon Oikonomopoulos
    constants.HV_MIGRATION_DOWNTIME: hv_base.NO_CHECK,
179 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
180 6b970cef Jun Futagawa
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
181 19572932 Iustin Pop
    constants.HV_DISK_CACHE:
182 19572932 Iustin Pop
      hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
183 d19d94db Guido Trotter
    constants.HV_SECURITY_MODEL:
184 d19d94db Guido Trotter
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_SM_TYPES),
185 d19d94db Guido Trotter
    constants.HV_SECURITY_DOMAIN: hv_base.NO_CHECK,
186 7ba594c0 Guido Trotter
    constants.HV_KVM_FLAG:
187 7ba594c0 Guido Trotter
      hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES),
188 fbe27e2b Guido Trotter
    constants.HV_VHOST_NET: hv_base.NO_CHECK,
189 547a63b7 Balazs Lecz
    constants.HV_KVM_USE_CHROOT: hv_base.NO_CHECK,
190 4f958b0b Miguel Di Ciurcio Filho
    constants.HV_MEM_PATH: hv_base.OPT_DIR_CHECK,
191 205ab586 Iustin Pop
    }
192 6b5605e8 Iustin Pop
193 30e42c4e Guido Trotter
  _MIGRATION_STATUS_RE = re.compile('Migration\s+status:\s+(\w+)',
194 30e42c4e Guido Trotter
                                    re.M | re.I)
195 c4e388a5 Guido Trotter
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
196 c4e388a5 Guido Trotter
  _MIGRATION_INFO_RETRY_DELAY = 2
197 30e42c4e Guido Trotter
198 b52d85c1 Guido Trotter
  _VERSION_RE = re.compile(r"\b(\d+)\.(\d+)\.(\d+)\b")
199 b52d85c1 Guido Trotter
200 64bfbc08 Guido Trotter
  ANCILLARY_FILES = [
201 64bfbc08 Guido Trotter
    _KVM_NETWORK_SCRIPT,
202 64bfbc08 Guido Trotter
    ]
203 64bfbc08 Guido Trotter
204 eb58f9b1 Guido Trotter
  def __init__(self):
205 eb58f9b1 Guido Trotter
    hv_base.BaseHypervisor.__init__(self)
206 eb58f9b1 Guido Trotter
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
207 eb58f9b1 Guido Trotter
    # in a tmpfs filesystem or has been otherwise wiped out.
208 29921401 Iustin Pop
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
209 9afb67fe Guido Trotter
    utils.EnsureDirs(dirs)
210 eb58f9b1 Guido Trotter
211 30786fc9 Iustin Pop
  @classmethod
212 30786fc9 Iustin Pop
  def _InstancePidFile(cls, instance_name):
213 98ec75d6 Iustin Pop
    """Returns the instance pidfile.
214 98ec75d6 Iustin Pop

215 98ec75d6 Iustin Pop
    """
216 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
217 98ec75d6 Iustin Pop
218 263b8de6 Guido Trotter
  @classmethod
219 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
220 7548396c Guido Trotter
    """Returns the instance uidfile.
221 7548396c Guido Trotter

222 7548396c Guido Trotter
    """
223 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
224 7548396c Guido Trotter
225 7548396c Guido Trotter
  @classmethod
226 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
227 263b8de6 Guido Trotter
    """Check pid file for instance information.
228 263b8de6 Guido Trotter

229 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
230 263b8de6 Guido Trotter
    information from its command line.
231 263b8de6 Guido Trotter

232 263b8de6 Guido Trotter
    @type pid: string or int
233 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
234 263b8de6 Guido Trotter
    @rtype: tuple
235 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
236 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
237 263b8de6 Guido Trotter

238 263b8de6 Guido Trotter
    """
239 263b8de6 Guido Trotter
    alive = utils.IsProcessAlive(pid)
240 263b8de6 Guido Trotter
    if not alive:
241 263b8de6 Guido Trotter
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
242 263b8de6 Guido Trotter
243 263b8de6 Guido Trotter
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
244 263b8de6 Guido Trotter
    try:
245 263b8de6 Guido Trotter
      cmdline = utils.ReadFile(cmdline_file)
246 263b8de6 Guido Trotter
    except EnvironmentError, err:
247 263b8de6 Guido Trotter
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
248 263b8de6 Guido Trotter
                                   (pid, err))
249 263b8de6 Guido Trotter
250 263b8de6 Guido Trotter
    instance = None
251 263b8de6 Guido Trotter
    memory = 0
252 263b8de6 Guido Trotter
    vcpus = 0
253 263b8de6 Guido Trotter
254 263b8de6 Guido Trotter
    arg_list = cmdline.split('\x00')
255 263b8de6 Guido Trotter
    while arg_list:
256 263b8de6 Guido Trotter
      arg =  arg_list.pop(0)
257 263b8de6 Guido Trotter
      if arg == "-name":
258 263b8de6 Guido Trotter
        instance = arg_list.pop(0)
259 263b8de6 Guido Trotter
      elif arg == "-m":
260 263b8de6 Guido Trotter
        memory = int(arg_list.pop(0))
261 263b8de6 Guido Trotter
      elif arg == "-smp":
262 263b8de6 Guido Trotter
        vcpus = int(arg_list.pop(0))
263 263b8de6 Guido Trotter
264 263b8de6 Guido Trotter
    if instance is None:
265 263b8de6 Guido Trotter
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
266 263b8de6 Guido Trotter
                                   " instance" % pid)
267 263b8de6 Guido Trotter
268 263b8de6 Guido Trotter
    return (instance, memory, vcpus)
269 263b8de6 Guido Trotter
270 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
271 263b8de6 Guido Trotter
    """Returns the instance pidfile, pid, and liveness.
272 263b8de6 Guido Trotter

273 263b8de6 Guido Trotter
    @type instance_name: string
274 263b8de6 Guido Trotter
    @param instance_name: instance name
275 263b8de6 Guido Trotter
    @rtype: tuple
276 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
277 1f8b3a27 Guido Trotter

278 1f8b3a27 Guido Trotter
    """
279 98ec75d6 Iustin Pop
    pidfile = self._InstancePidFile(instance_name)
280 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
281 263b8de6 Guido Trotter
282 263b8de6 Guido Trotter
    alive = False
283 263b8de6 Guido Trotter
    try:
284 263b8de6 Guido Trotter
      cmd_instance = self._InstancePidInfo(pid)[0]
285 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
286 263b8de6 Guido Trotter
    except errors.HypervisorError:
287 263b8de6 Guido Trotter
      pass
288 1f8b3a27 Guido Trotter
289 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
290 1f8b3a27 Guido Trotter
291 5905901c Iustin Pop
  def _CheckDown(self, instance_name):
292 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
293 5905901c Iustin Pop

294 5905901c Iustin Pop
    """
295 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
296 5905901c Iustin Pop
    if alive:
297 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
298 5905901c Iustin Pop
                                   (instance_name, "already running"))
299 5905901c Iustin Pop
300 0df4d98a Guido Trotter
  @classmethod
301 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
302 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
303 c4fbefc8 Guido Trotter

304 c4fbefc8 Guido Trotter
    """
305 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
306 c4fbefc8 Guido Trotter
307 0df4d98a Guido Trotter
  @classmethod
308 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
309 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
310 c4fbefc8 Guido Trotter

311 c4fbefc8 Guido Trotter
    """
312 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
313 c4fbefc8 Guido Trotter
314 86d6bc2a Guido Trotter
  @staticmethod
315 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
316 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
317 86d6bc2a Guido Trotter

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

320 86d6bc2a Guido Trotter
    """
321 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
322 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
323 86d6bc2a Guido Trotter
    else:
324 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
325 86d6bc2a Guido Trotter
326 0df4d98a Guido Trotter
  @classmethod
327 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
328 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
329 38e250ba Guido Trotter

330 38e250ba Guido Trotter
    """
331 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
332 38e250ba Guido Trotter
333 7e66c35b Guido Trotter
  @classmethod
334 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
335 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
336 547a63b7 Balazs Lecz

337 547a63b7 Balazs Lecz
    """
338 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
339 547a63b7 Balazs Lecz
340 547a63b7 Balazs Lecz
  @classmethod
341 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
342 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
343 5d9bfd87 Apollon Oikonomopoulos
    given instance.
344 5d9bfd87 Apollon Oikonomopoulos

345 5d9bfd87 Apollon Oikonomopoulos
    """
346 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
347 5d9bfd87 Apollon Oikonomopoulos
348 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
349 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
350 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
351 5d9bfd87 Apollon Oikonomopoulos

352 5d9bfd87 Apollon Oikonomopoulos
    """
353 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
354 5d9bfd87 Apollon Oikonomopoulos
355 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
356 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
357 7548396c Guido Trotter
    """Try to read a uid file
358 7548396c Guido Trotter

359 7548396c Guido Trotter
    """
360 7548396c Guido Trotter
    if os.path.exists(uid_file):
361 7548396c Guido Trotter
      try:
362 682f7601 Guido Trotter
        uid = int(utils.ReadOneLineFile(uid_file))
363 aa0b600b Guido Trotter
        return uid
364 7548396c Guido Trotter
      except EnvironmentError:
365 7548396c Guido Trotter
        logging.warning("Can't read uid file", exc_info=True)
366 7548396c Guido Trotter
      except (TypeError, ValueError):
367 7548396c Guido Trotter
        logging.warning("Can't parse uid file contents", exc_info=True)
368 aa0b600b Guido Trotter
    return None
369 7548396c Guido Trotter
370 7548396c Guido Trotter
  @classmethod
371 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
372 547a63b7 Balazs Lecz
    """Removes an instance's rutime sockets/files/dirs.
373 7e66c35b Guido Trotter

374 7e66c35b Guido Trotter
    """
375 7e66c35b Guido Trotter
    utils.RemoveFile(pidfile)
376 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
377 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceSerial(instance_name))
378 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
379 7548396c Guido Trotter
    uid_file = cls._InstanceUidFile(instance_name)
380 7548396c Guido Trotter
    uid = cls._TryReadUidFile(uid_file)
381 7548396c Guido Trotter
    utils.RemoveFile(uid_file)
382 7548396c Guido Trotter
    if uid is not None:
383 7548396c Guido Trotter
      uidpool.ReleaseUid(uid)
384 7be85163 Guido Trotter
    try:
385 7be85163 Guido Trotter
      shutil.rmtree(cls._InstanceNICDir(instance_name))
386 7be85163 Guido Trotter
    except OSError, err:
387 7be85163 Guido Trotter
      if err.errno != errno.ENOENT:
388 7be85163 Guido Trotter
        raise
389 547a63b7 Balazs Lecz
    try:
390 547a63b7 Balazs Lecz
      chroot_dir = cls._InstanceChrootDir(instance_name)
391 547a63b7 Balazs Lecz
      utils.RemoveDir(chroot_dir)
392 547a63b7 Balazs Lecz
    except OSError, err:
393 547a63b7 Balazs Lecz
      if err.errno == errno.ENOTEMPTY:
394 547a63b7 Balazs Lecz
        # The chroot directory is expected to be empty, but it isn't.
395 547a63b7 Balazs Lecz
        new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
396 547a63b7 Balazs Lecz
                                          prefix="%s-%s-" %
397 547a63b7 Balazs Lecz
                                          (instance_name,
398 547a63b7 Balazs Lecz
                                           utils.TimestampForFilename()))
399 547a63b7 Balazs Lecz
        logging.warning("The chroot directory of instance %s can not be"
400 547a63b7 Balazs Lecz
                        " removed as it is not empty. Moving it to the"
401 547a63b7 Balazs Lecz
                        " quarantine instead. Please investigate the"
402 547a63b7 Balazs Lecz
                        " contents (%s) and clean up manually",
403 547a63b7 Balazs Lecz
                        instance_name, new_chroot_dir)
404 547a63b7 Balazs Lecz
        utils.RenameFile(chroot_dir, new_chroot_dir)
405 547a63b7 Balazs Lecz
      else:
406 547a63b7 Balazs Lecz
        raise
407 7e66c35b Guido Trotter
408 748e4b5a Michael Hanselmann
  @staticmethod
409 5d9bfd87 Apollon Oikonomopoulos
  def _ConfigureNIC(instance, seq, nic, tap):
410 5d9bfd87 Apollon Oikonomopoulos
    """Run the network configuration script for a specified NIC
411 eb58f9b1 Guido Trotter

412 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
413 eb58f9b1 Guido Trotter
    @type instance: instance object
414 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
415 eb58f9b1 Guido Trotter
    @type seq: int
416 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
417 eb58f9b1 Guido Trotter
    @type nic: nic object
418 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
419 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
420 eb58f9b1 Guido Trotter

421 eb58f9b1 Guido Trotter
    """
422 748e4b5a Michael Hanselmann
423 5d9bfd87 Apollon Oikonomopoulos
    if instance.tags:
424 5d9bfd87 Apollon Oikonomopoulos
      tags = " ".join(instance.tags)
425 5d9bfd87 Apollon Oikonomopoulos
    else:
426 5d9bfd87 Apollon Oikonomopoulos
      tags = ""
427 5d9bfd87 Apollon Oikonomopoulos
428 5d9bfd87 Apollon Oikonomopoulos
    env = {
429 5d9bfd87 Apollon Oikonomopoulos
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
430 5d9bfd87 Apollon Oikonomopoulos
      "INSTANCE": instance.name,
431 5d9bfd87 Apollon Oikonomopoulos
      "MAC": nic.mac,
432 5d9bfd87 Apollon Oikonomopoulos
      "MODE": nic.nicparams[constants.NIC_MODE],
433 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE": tap,
434 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE_INDEX": str(seq),
435 5d9bfd87 Apollon Oikonomopoulos
      "TAGS": tags,
436 5d9bfd87 Apollon Oikonomopoulos
    }
437 5d9bfd87 Apollon Oikonomopoulos
438 5d9bfd87 Apollon Oikonomopoulos
    if nic.ip:
439 5d9bfd87 Apollon Oikonomopoulos
      env["IP"] = nic.ip
440 5d9bfd87 Apollon Oikonomopoulos
441 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_LINK]:
442 5d9bfd87 Apollon Oikonomopoulos
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
443 5d9bfd87 Apollon Oikonomopoulos
444 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
445 5d9bfd87 Apollon Oikonomopoulos
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
446 5d9bfd87 Apollon Oikonomopoulos
447 5d9bfd87 Apollon Oikonomopoulos
    result = utils.RunCmd([constants.KVM_IFUP, tap], env=env)
448 5d9bfd87 Apollon Oikonomopoulos
    if result.failed:
449 5d9bfd87 Apollon Oikonomopoulos
      raise errors.HypervisorError("Failed to configure interface %s: %s."
450 5d9bfd87 Apollon Oikonomopoulos
                                   " Network configuration script output: %s" %
451 5d9bfd87 Apollon Oikonomopoulos
                                   (tap, result.fail_reason, result.output))
452 eb58f9b1 Guido Trotter
453 eb58f9b1 Guido Trotter
  def ListInstances(self):
454 eb58f9b1 Guido Trotter
    """Get the list of running instances.
455 eb58f9b1 Guido Trotter

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

459 eb58f9b1 Guido Trotter
    """
460 eb58f9b1 Guido Trotter
    result = []
461 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
462 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
463 eb58f9b1 Guido Trotter
        result.append(name)
464 eb58f9b1 Guido Trotter
    return result
465 eb58f9b1 Guido Trotter
466 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
467 eb58f9b1 Guido Trotter
    """Get instance properties.
468 eb58f9b1 Guido Trotter

469 4fbb3c60 Guido Trotter
    @type instance_name: string
470 c41eea6e Iustin Pop
    @param instance_name: the instance name
471 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
472 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
473 eb58f9b1 Guido Trotter

474 eb58f9b1 Guido Trotter
    """
475 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
476 1f8b3a27 Guido Trotter
    if not alive:
477 eb58f9b1 Guido Trotter
      return None
478 eb58f9b1 Guido Trotter
479 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
480 eb58f9b1 Guido Trotter
    stat = "---b-"
481 eb58f9b1 Guido Trotter
    times = "0"
482 eb58f9b1 Guido Trotter
483 eb58f9b1 Guido Trotter
    return (instance_name, pid, memory, vcpus, stat, times)
484 eb58f9b1 Guido Trotter
485 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
486 eb58f9b1 Guido Trotter
    """Get properties of all instances.
487 eb58f9b1 Guido Trotter

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

490 eb58f9b1 Guido Trotter
    """
491 eb58f9b1 Guido Trotter
    data = []
492 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
493 263b8de6 Guido Trotter
      try:
494 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
495 263b8de6 Guido Trotter
      except errors.HypervisorError:
496 263b8de6 Guido Trotter
        continue
497 263b8de6 Guido Trotter
      if info:
498 263b8de6 Guido Trotter
        data.append(info)
499 eb58f9b1 Guido Trotter
    return data
500 eb58f9b1 Guido Trotter
501 07813a9e Iustin Pop
  def _GenerateKVMRuntime(self, instance, block_devices):
502 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
503 eb58f9b1 Guido Trotter

504 eb58f9b1 Guido Trotter
    """
505 98ec75d6 Iustin Pop
    pidfile  = self._InstancePidFile(instance.name)
506 eb58f9b1 Guido Trotter
    kvm = constants.KVM_PATH
507 eb58f9b1 Guido Trotter
    kvm_cmd = [kvm]
508 c6a39fc2 Guido Trotter
    # used just by the vnc server, if enabled
509 c6a39fc2 Guido Trotter
    kvm_cmd.extend(['-name', instance.name])
510 8b3fd458 Iustin Pop
    kvm_cmd.extend(['-m', instance.beparams[constants.BE_MEMORY]])
511 8b3fd458 Iustin Pop
    kvm_cmd.extend(['-smp', instance.beparams[constants.BE_VCPUS]])
512 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-pidfile', pidfile])
513 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-daemonize'])
514 6b5605e8 Iustin Pop
    if not instance.hvparams[constants.HV_ACPI]:
515 eb58f9b1 Guido Trotter
      kvm_cmd.extend(['-no-acpi'])
516 eb58f9b1 Guido Trotter
517 a985b417 Iustin Pop
    hvp = instance.hvparams
518 835528af Iustin Pop
    boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
519 835528af Iustin Pop
    boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
520 835528af Iustin Pop
    boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
521 8745c3d7 Guido Trotter
522 7ba594c0 Guido Trotter
    if hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED:
523 7ba594c0 Guido Trotter
      kvm_cmd.extend(["-enable-kvm"])
524 7ba594c0 Guido Trotter
    elif hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED:
525 7ba594c0 Guido Trotter
      kvm_cmd.extend(["-disable-kvm"])
526 7ba594c0 Guido Trotter
527 8745c3d7 Guido Trotter
    if boot_network:
528 8745c3d7 Guido Trotter
      kvm_cmd.extend(['-boot', 'n'])
529 1213604d Guido Trotter
530 a985b417 Iustin Pop
    disk_type = hvp[constants.HV_DISK_TYPE]
531 1213604d Guido Trotter
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
532 1213604d Guido Trotter
      if_val = ',if=virtio'
533 1213604d Guido Trotter
    else:
534 1213604d Guido Trotter
      if_val = ',if=%s' % disk_type
535 19572932 Iustin Pop
    # Cache mode
536 19572932 Iustin Pop
    disk_cache = hvp[constants.HV_DISK_CACHE]
537 41e794f6 Apollon Oikonomopoulos
    if instance.disk_template in constants.DTS_EXT_MIRROR:
538 41e794f6 Apollon Oikonomopoulos
      if disk_cache != "none":
539 41e794f6 Apollon Oikonomopoulos
        # TODO: make this a hard error, instead of a silent overwrite
540 41e794f6 Apollon Oikonomopoulos
        logging.warning("KVM: overriding disk_cache setting '%s' with 'none'"
541 41e794f6 Apollon Oikonomopoulos
                        " to prevent shared storage corruption on migration",
542 41e794f6 Apollon Oikonomopoulos
                        disk_cache)
543 41e794f6 Apollon Oikonomopoulos
      cache_val = ",cache=none"
544 41e794f6 Apollon Oikonomopoulos
    elif disk_cache != constants.HT_CACHE_DEFAULT:
545 19572932 Iustin Pop
      cache_val = ",cache=%s" % disk_cache
546 19572932 Iustin Pop
    else:
547 19572932 Iustin Pop
      cache_val = ""
548 069cfbf1 Iustin Pop
    for cfdev, dev_path in block_devices:
549 d34b16d7 Iustin Pop
      if cfdev.mode != constants.DISK_RDWR:
550 d34b16d7 Iustin Pop
        raise errors.HypervisorError("Instance has read-only disks which"
551 d34b16d7 Iustin Pop
                                     " are not supported by KVM")
552 eb58f9b1 Guido Trotter
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
553 66d5dbef Guido Trotter
      if boot_disk:
554 9dd363eb Guido Trotter
        kvm_cmd.extend(['-boot', 'c'])
555 9cf4321f Apollon Oikonomopoulos
        if disk_type != constants.HT_DISK_IDE:
556 74a4c11b Guido Trotter
          boot_val = ',boot=on'
557 9cf4321f Apollon Oikonomopoulos
        else:
558 74a4c11b Guido Trotter
          boot_val = ''
559 8745c3d7 Guido Trotter
        # We only boot from the first disk
560 66d5dbef Guido Trotter
        boot_disk = False
561 eb58f9b1 Guido Trotter
      else:
562 eb58f9b1 Guido Trotter
        boot_val = ''
563 eb58f9b1 Guido Trotter
564 19572932 Iustin Pop
      drive_val = 'file=%s,format=raw%s%s%s' % (dev_path, if_val, boot_val,
565 19572932 Iustin Pop
                                                cache_val)
566 eb58f9b1 Guido Trotter
      kvm_cmd.extend(['-drive', drive_val])
567 eb58f9b1 Guido Trotter
568 a985b417 Iustin Pop
    iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
569 66d5dbef Guido Trotter
    if iso_image:
570 9dd363eb Guido Trotter
      options = ',format=raw,media=cdrom'
571 66d5dbef Guido Trotter
      if boot_cdrom:
572 9dd363eb Guido Trotter
        kvm_cmd.extend(['-boot', 'd'])
573 9cf4321f Apollon Oikonomopoulos
        if disk_type != constants.HT_DISK_IDE:
574 74a4c11b Guido Trotter
          options = '%s,boot=on' % options
575 9dd363eb Guido Trotter
      else:
576 9cf4321f Apollon Oikonomopoulos
        if disk_type == constants.HT_DISK_PARAVIRTUAL:
577 9cf4321f Apollon Oikonomopoulos
          if_val = ',if=virtio'
578 9cf4321f Apollon Oikonomopoulos
        else:
579 9cf4321f Apollon Oikonomopoulos
          if_val = ',if=%s' % disk_type
580 9cf4321f Apollon Oikonomopoulos
        options = '%s%s' % (options, if_val)
581 66d5dbef Guido Trotter
      drive_val = 'file=%s%s' % (iso_image, options)
582 66d5dbef Guido Trotter
      kvm_cmd.extend(['-drive', drive_val])
583 66d5dbef Guido Trotter
584 a985b417 Iustin Pop
    kernel_path = hvp[constants.HV_KERNEL_PATH]
585 df5ab9f0 Guido Trotter
    if kernel_path:
586 df5ab9f0 Guido Trotter
      kvm_cmd.extend(['-kernel', kernel_path])
587 a985b417 Iustin Pop
      initrd_path = hvp[constants.HV_INITRD_PATH]
588 df5ab9f0 Guido Trotter
      if initrd_path:
589 df5ab9f0 Guido Trotter
        kvm_cmd.extend(['-initrd', initrd_path])
590 07813a9e Iustin Pop
      root_append = ['root=%s' % hvp[constants.HV_ROOT_PATH],
591 07813a9e Iustin Pop
                     hvp[constants.HV_KERNEL_ARGS]]
592 07813a9e Iustin Pop
      if hvp[constants.HV_SERIAL_CONSOLE]:
593 07813a9e Iustin Pop
        root_append.append('console=ttyS0,38400')
594 07813a9e Iustin Pop
      kvm_cmd.extend(['-append', ' '.join(root_append)])
595 eb58f9b1 Guido Trotter
596 4f958b0b Miguel Di Ciurcio Filho
    mem_path = hvp[constants.HV_MEM_PATH]
597 4f958b0b Miguel Di Ciurcio Filho
    if mem_path:
598 9d3015f9 Guido Trotter
      kvm_cmd.extend(["-mem-path", mem_path, "-mem-prealloc"])
599 4f958b0b Miguel Di Ciurcio Filho
600 a985b417 Iustin Pop
    mouse_type = hvp[constants.HV_USB_MOUSE]
601 31f6f67a Guido Trotter
    vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
602 31f6f67a Guido Trotter
603 11344a50 Guido Trotter
    if mouse_type:
604 11344a50 Guido Trotter
      kvm_cmd.extend(['-usb'])
605 11344a50 Guido Trotter
      kvm_cmd.extend(['-usbdevice', mouse_type])
606 31f6f67a Guido Trotter
    elif vnc_bind_address:
607 31f6f67a Guido Trotter
      kvm_cmd.extend(['-usbdevice', constants.HT_MOUSE_TABLET])
608 11344a50 Guido Trotter
609 8470c8db Guido Trotter
    if vnc_bind_address:
610 8b312c1d Manuel Franceschini
      if netutils.IP4Address.IsValid(vnc_bind_address):
611 377d74c9 Guido Trotter
        if instance.network_port > constants.VNC_BASE_PORT:
612 377d74c9 Guido Trotter
          display = instance.network_port - constants.VNC_BASE_PORT
613 14f5f1b6 Manuel Franceschini
          if vnc_bind_address == constants.IP4_ADDRESS_ANY:
614 8447f52b Guido Trotter
            vnc_arg = ':%d' % (display)
615 8447f52b Guido Trotter
          else:
616 19498d6c Guido Trotter
            vnc_arg = '%s:%d' % (vnc_bind_address, display)
617 8470c8db Guido Trotter
        else:
618 8447f52b Guido Trotter
          logging.error("Network port is not a valid VNC display (%d < %d)."
619 07b8a2b5 Iustin Pop
                        " Not starting VNC", instance.network_port,
620 07b8a2b5 Iustin Pop
                        constants.VNC_BASE_PORT)
621 8447f52b Guido Trotter
          vnc_arg = 'none'
622 8b2d1013 Guido Trotter
623 8b2d1013 Guido Trotter
        # Only allow tls and other option when not binding to a file, for now.
624 8b2d1013 Guido Trotter
        # kvm/qemu gets confused otherwise about the filename to use.
625 8b2d1013 Guido Trotter
        vnc_append = ''
626 a985b417 Iustin Pop
        if hvp[constants.HV_VNC_TLS]:
627 8b2d1013 Guido Trotter
          vnc_append = '%s,tls' % vnc_append
628 a985b417 Iustin Pop
          if hvp[constants.HV_VNC_X509_VERIFY]:
629 8b2d1013 Guido Trotter
            vnc_append = '%s,x509verify=%s' % (vnc_append,
630 a985b417 Iustin Pop
                                               hvp[constants.HV_VNC_X509])
631 a985b417 Iustin Pop
          elif hvp[constants.HV_VNC_X509]:
632 8b2d1013 Guido Trotter
            vnc_append = '%s,x509=%s' % (vnc_append,
633 a985b417 Iustin Pop
                                         hvp[constants.HV_VNC_X509])
634 6e6bb8d5 Guido Trotter
        if hvp[constants.HV_VNC_PASSWORD_FILE]:
635 6e6bb8d5 Guido Trotter
          vnc_append = '%s,password' % vnc_append
636 6e6bb8d5 Guido Trotter
637 8b2d1013 Guido Trotter
        vnc_arg = '%s%s' % (vnc_arg, vnc_append)
638 8b2d1013 Guido Trotter
639 8470c8db Guido Trotter
      else:
640 8b2d1013 Guido Trotter
        vnc_arg = 'unix:%s/%s.vnc' % (vnc_bind_address, instance.name)
641 8b2d1013 Guido Trotter
642 8447f52b Guido Trotter
      kvm_cmd.extend(['-vnc', vnc_arg])
643 8470c8db Guido Trotter
    else:
644 8470c8db Guido Trotter
      kvm_cmd.extend(['-nographic'])
645 8470c8db Guido Trotter
646 69b99987 Michael Hanselmann
    monitor_dev = ("unix:%s,server,nowait" %
647 69b99987 Michael Hanselmann
                   self._InstanceMonitor(instance.name))
648 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-monitor', monitor_dev])
649 a985b417 Iustin Pop
    if hvp[constants.HV_SERIAL_CONSOLE]:
650 a985b417 Iustin Pop
      serial_dev = ('unix:%s,server,nowait' %
651 a985b417 Iustin Pop
                    self._InstanceSerial(instance.name))
652 a2faf9ee Guido Trotter
      kvm_cmd.extend(['-serial', serial_dev])
653 a2faf9ee Guido Trotter
    else:
654 a2faf9ee Guido Trotter
      kvm_cmd.extend(['-serial', 'none'])
655 eb58f9b1 Guido Trotter
656 6b970cef Jun Futagawa
    if hvp[constants.HV_USE_LOCALTIME]:
657 6b970cef Jun Futagawa
      kvm_cmd.extend(['-localtime'])
658 6b970cef Jun Futagawa
659 547a63b7 Balazs Lecz
    if hvp[constants.HV_KVM_USE_CHROOT]:
660 547a63b7 Balazs Lecz
      kvm_cmd.extend(['-chroot', self._InstanceChrootDir(instance.name)])
661 547a63b7 Balazs Lecz
662 ee5f20b0 Guido Trotter
    # Save the current instance nics, but defer their expansion as parameters,
663 ee5f20b0 Guido Trotter
    # as we'll need to generate executable temp files for them.
664 ee5f20b0 Guido Trotter
    kvm_nics = instance.nics
665 a985b417 Iustin Pop
    hvparams = hvp
666 ee5f20b0 Guido Trotter
667 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
668 ee5f20b0 Guido Trotter
669 38e250ba Guido Trotter
  def _WriteKVMRuntime(self, instance_name, data):
670 38e250ba Guido Trotter
    """Write an instance's KVM runtime
671 38e250ba Guido Trotter

672 38e250ba Guido Trotter
    """
673 38e250ba Guido Trotter
    try:
674 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
675 38e250ba Guido Trotter
                      data=data)
676 90c024f6 Guido Trotter
    except EnvironmentError, err:
677 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
678 38e250ba Guido Trotter
679 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
680 38e250ba Guido Trotter
    """Read an instance's KVM runtime
681 38e250ba Guido Trotter

682 38e250ba Guido Trotter
    """
683 38e250ba Guido Trotter
    try:
684 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
685 90c024f6 Guido Trotter
    except EnvironmentError, err:
686 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
687 38e250ba Guido Trotter
    return file_content
688 38e250ba Guido Trotter
689 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
690 38e250ba Guido Trotter
    """Save an instance's KVM runtime
691 38e250ba Guido Trotter

692 38e250ba Guido Trotter
    """
693 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
694 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
695 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
696 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
697 38e250ba Guido Trotter
698 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
699 38e250ba Guido Trotter
    """Load an instance's KVM runtime
700 38e250ba Guido Trotter

701 38e250ba Guido Trotter
    """
702 30e42c4e Guido Trotter
    if not serialized_runtime:
703 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
704 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
705 c2672466 Guido Trotter
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
706 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
707 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
708 38e250ba Guido Trotter
709 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
710 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
711 76431533 Guido Trotter

712 76431533 Guido Trotter
    @type name: string
713 76431533 Guido Trotter
    @param name: instance name
714 76431533 Guido Trotter
    @type kvm_cmd: list of strings
715 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
716 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
717 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
718 76431533 Guido Trotter

719 76431533 Guido Trotter
    """
720 5d9bfd87 Apollon Oikonomopoulos
    try:
721 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
722 5d9bfd87 Apollon Oikonomopoulos
    finally:
723 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
724 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
725 5d9bfd87 Apollon Oikonomopoulos
726 76431533 Guido Trotter
    if result.failed:
727 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
728 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
729 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
730 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
731 76431533 Guido Trotter
732 30e42c4e Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
733 ee5f20b0 Guido Trotter
    """Execute a KVM cmd, after completing it with some last minute data
734 ee5f20b0 Guido Trotter

735 30e42c4e Guido Trotter
    @type incoming: tuple of strings
736 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
737 30e42c4e Guido Trotter

738 ee5f20b0 Guido Trotter
    """
739 297e6e53 Guido Trotter
    # Small _ExecuteKVMRuntime hv parameters programming howto:
740 297e6e53 Guido Trotter
    #  - conf_hvp contains the parameters as configured on ganeti. they might
741 297e6e53 Guido Trotter
    #    have changed since the instance started; only use them if the change
742 297e6e53 Guido Trotter
    #    won't affect the inside of the instance (which hasn't been rebooted).
743 297e6e53 Guido Trotter
    #  - up_hvp contains the parameters as they were when the instance was
744 297e6e53 Guido Trotter
    #    started, plus any new parameter which has been added between ganeti
745 297e6e53 Guido Trotter
    #    versions: it is paramount that those default to a value which won't
746 297e6e53 Guido Trotter
    #    affect the inside of the instance as well.
747 297e6e53 Guido Trotter
    conf_hvp = instance.hvparams
748 5905901c Iustin Pop
    name = instance.name
749 5905901c Iustin Pop
    self._CheckDown(name)
750 ee5f20b0 Guido Trotter
751 ee5f20b0 Guido Trotter
    temp_files = []
752 ee5f20b0 Guido Trotter
753 297e6e53 Guido Trotter
    kvm_cmd, kvm_nics, up_hvp = kvm_runtime
754 297e6e53 Guido Trotter
    up_hvp = objects.FillDict(conf_hvp, up_hvp)
755 ee5f20b0 Guido Trotter
756 4b784cf8 Miguel Di Ciurcio Filho
    kvm_version = self._GetKVMVersion()
757 4b784cf8 Miguel Di Ciurcio Filho
    if kvm_version:
758 049383d9 Adeodato Simo
      _, v_major, v_min, _ = kvm_version
759 4b784cf8 Miguel Di Ciurcio Filho
    else:
760 4b784cf8 Miguel Di Ciurcio Filho
      raise errors.HypervisorError("Unable to get KVM version")
761 4b784cf8 Miguel Di Ciurcio Filho
762 297e6e53 Guido Trotter
    # We know it's safe to run as a different user upon migration, so we'll use
763 297e6e53 Guido Trotter
    # the latest conf, from conf_hvp.
764 297e6e53 Guido Trotter
    security_model = conf_hvp[constants.HV_SECURITY_MODEL]
765 cef34868 Guido Trotter
    if security_model == constants.HT_SM_USER:
766 297e6e53 Guido Trotter
      kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
767 cef34868 Guido Trotter
768 297e6e53 Guido Trotter
    # We have reasons to believe changing something like the nic driver/type
769 297e6e53 Guido Trotter
    # upon migration won't exactly fly with the instance kernel, so for nic
770 297e6e53 Guido Trotter
    # related parameters we'll use up_hvp
771 5d9bfd87 Apollon Oikonomopoulos
    tapfds = []
772 5d9bfd87 Apollon Oikonomopoulos
    taps = []
773 ee5f20b0 Guido Trotter
    if not kvm_nics:
774 fbe27e2b Guido Trotter
      kvm_cmd.extend(["-net", "none"])
775 ee5f20b0 Guido Trotter
    else:
776 5d9bfd87 Apollon Oikonomopoulos
      vnet_hdr = False
777 fbe27e2b Guido Trotter
      tap_extra = ""
778 297e6e53 Guido Trotter
      nic_type = up_hvp[constants.HV_NIC_TYPE]
779 37f88dc6 Guido Trotter
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
780 4b784cf8 Miguel Di Ciurcio Filho
        # From version 0.12.0, kvm uses a new sintax for network configuration.
781 049383d9 Adeodato Simo
        if (v_major, v_min) >= (0, 12):
782 4b784cf8 Miguel Di Ciurcio Filho
          nic_model = "virtio-net-pci"
783 5d9bfd87 Apollon Oikonomopoulos
          vnet_hdr = True
784 4b784cf8 Miguel Di Ciurcio Filho
        else:
785 4b784cf8 Miguel Di Ciurcio Filho
          nic_model = "virtio"
786 4b784cf8 Miguel Di Ciurcio Filho
787 297e6e53 Guido Trotter
        if up_hvp[constants.HV_VHOST_NET]:
788 4b784cf8 Miguel Di Ciurcio Filho
          # vhost_net is only available from version 0.13.0 or newer
789 049383d9 Adeodato Simo
          if (v_major, v_min) >= (0, 13):
790 4b784cf8 Miguel Di Ciurcio Filho
            tap_extra = ",vhost=on"
791 4b784cf8 Miguel Di Ciurcio Filho
          else:
792 4b784cf8 Miguel Di Ciurcio Filho
            raise errors.HypervisorError("vhost_net is configured"
793 4b784cf8 Miguel Di Ciurcio Filho
                                        " but it is not available")
794 37f88dc6 Guido Trotter
      else:
795 4b784cf8 Miguel Di Ciurcio Filho
        nic_model = nic_type
796 37f88dc6 Guido Trotter
797 ee5f20b0 Guido Trotter
      for nic_seq, nic in enumerate(kvm_nics):
798 5d9bfd87 Apollon Oikonomopoulos
        tapname, tapfd = _OpenTap(vnet_hdr)
799 5d9bfd87 Apollon Oikonomopoulos
        tapfds.append(tapfd)
800 5d9bfd87 Apollon Oikonomopoulos
        taps.append(tapname)
801 049383d9 Adeodato Simo
        if (v_major, v_min) >= (0, 12):
802 4b784cf8 Miguel Di Ciurcio Filho
          nic_val = "%s,mac=%s,netdev=netdev%s" % (nic_model, nic.mac, nic_seq)
803 5d9bfd87 Apollon Oikonomopoulos
          tap_val = "type=tap,id=netdev%s,fd=%d%s" % (nic_seq, tapfd, tap_extra)
804 4b784cf8 Miguel Di Ciurcio Filho
          kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
805 4b784cf8 Miguel Di Ciurcio Filho
        else:
806 049383d9 Adeodato Simo
          nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq,
807 049383d9 Adeodato Simo
                                                         nic.mac, nic_model)
808 5d9bfd87 Apollon Oikonomopoulos
          tap_val = "tap,vlan=%s,fd=%d" % (nic_seq, tapfd)
809 4b784cf8 Miguel Di Ciurcio Filho
          kvm_cmd.extend(["-net", tap_val, "-net", nic_val])
810 ee5f20b0 Guido Trotter
811 30e42c4e Guido Trotter
    if incoming:
812 30e42c4e Guido Trotter
      target, port = incoming
813 30e42c4e Guido Trotter
      kvm_cmd.extend(['-incoming', 'tcp:%s:%s' % (target, port)])
814 30e42c4e Guido Trotter
815 297e6e53 Guido Trotter
    # Changing the vnc password doesn't bother the guest that much. At most it
816 297e6e53 Guido Trotter
    # will surprise people who connect to it. Whether positively or negatively
817 297e6e53 Guido Trotter
    # it's debatable.
818 297e6e53 Guido Trotter
    vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
819 6e6bb8d5 Guido Trotter
    vnc_pwd = None
820 6e6bb8d5 Guido Trotter
    if vnc_pwd_file:
821 6e6bb8d5 Guido Trotter
      try:
822 682f7601 Guido Trotter
        vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
823 6e6bb8d5 Guido Trotter
      except EnvironmentError, err:
824 6e6bb8d5 Guido Trotter
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
825 6e6bb8d5 Guido Trotter
                                     % (vnc_pwd_file, err))
826 6e6bb8d5 Guido Trotter
827 297e6e53 Guido Trotter
    if conf_hvp[constants.HV_KVM_USE_CHROOT]:
828 547a63b7 Balazs Lecz
      utils.EnsureDirs([(self._InstanceChrootDir(name),
829 547a63b7 Balazs Lecz
                         constants.SECURE_DIR_MODE)])
830 547a63b7 Balazs Lecz
831 5d9bfd87 Apollon Oikonomopoulos
    if not incoming:
832 5d9bfd87 Apollon Oikonomopoulos
      # Configure the network now for starting instances, during
833 5d9bfd87 Apollon Oikonomopoulos
      # FinalizeMigration for incoming instances
834 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
835 5d9bfd87 Apollon Oikonomopoulos
        self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
836 5d9bfd87 Apollon Oikonomopoulos
837 76431533 Guido Trotter
    if security_model == constants.HT_SM_POOL:
838 76431533 Guido Trotter
      ss = ssconf.SimpleStore()
839 76431533 Guido Trotter
      uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
840 76431533 Guido Trotter
      all_uids = set(uidpool.ExpandUidPool(uid_pool))
841 76431533 Guido Trotter
      uid = uidpool.RequestUnusedUid(all_uids)
842 76431533 Guido Trotter
      try:
843 76431533 Guido Trotter
        username = pwd.getpwuid(uid.GetUid()).pw_name
844 76431533 Guido Trotter
        kvm_cmd.extend(["-runas", username])
845 5d9bfd87 Apollon Oikonomopoulos
        self._RunKVMCmd(name, kvm_cmd, tapfds)
846 76431533 Guido Trotter
      except:
847 76431533 Guido Trotter
        uidpool.ReleaseUid(uid)
848 76431533 Guido Trotter
        raise
849 76431533 Guido Trotter
      else:
850 76431533 Guido Trotter
        uid.Unlock()
851 76431533 Guido Trotter
        utils.WriteFile(self._InstanceUidFile(name), data=str(uid))
852 76431533 Guido Trotter
    else:
853 5d9bfd87 Apollon Oikonomopoulos
      self._RunKVMCmd(name, kvm_cmd, tapfds)
854 5d9bfd87 Apollon Oikonomopoulos
855 5d9bfd87 Apollon Oikonomopoulos
    utils.EnsureDirs([(self._InstanceNICDir(instance.name),
856 5d9bfd87 Apollon Oikonomopoulos
                     constants.RUN_DIRS_MODE)])
857 5d9bfd87 Apollon Oikonomopoulos
    for nic_seq, tap in enumerate(taps):
858 5d9bfd87 Apollon Oikonomopoulos
      utils.WriteFile(self._InstanceNICFile(instance.name, nic_seq),
859 5d9bfd87 Apollon Oikonomopoulos
                      data=tap)
860 eb58f9b1 Guido Trotter
861 6e6bb8d5 Guido Trotter
    if vnc_pwd:
862 6e6bb8d5 Guido Trotter
      change_cmd = 'change vnc password %s' % vnc_pwd
863 6e6bb8d5 Guido Trotter
      self._CallMonitorCommand(instance.name, change_cmd)
864 6e6bb8d5 Guido Trotter
865 08137f9e Iustin Pop
    for filename in temp_files:
866 08137f9e Iustin Pop
      utils.RemoveFile(filename)
867 eb58f9b1 Guido Trotter
868 07813a9e Iustin Pop
  def StartInstance(self, instance, block_devices):
869 ee5f20b0 Guido Trotter
    """Start an instance.
870 ee5f20b0 Guido Trotter

871 ee5f20b0 Guido Trotter
    """
872 5905901c Iustin Pop
    self._CheckDown(instance.name)
873 07813a9e Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices)
874 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
875 ee5f20b0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
876 ee5f20b0 Guido Trotter
877 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
878 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
879 6567aff3 Guido Trotter

880 6567aff3 Guido Trotter
    """
881 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
882 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
883 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
884 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
885 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
886 6567aff3 Guido Trotter
    if result.failed:
887 6567aff3 Guido Trotter
      msg = ("Failed to send command '%s' to instance %s."
888 6567aff3 Guido Trotter
             " output: %s, error: %s, fail_reason: %s" %
889 9798fcae Guido Trotter
             (command, instance_name,
890 9798fcae Guido Trotter
              result.stdout, result.stderr, result.fail_reason))
891 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
892 6567aff3 Guido Trotter
893 6567aff3 Guido Trotter
    return result
894 6567aff3 Guido Trotter
895 b52d85c1 Guido Trotter
  @classmethod
896 b52d85c1 Guido Trotter
  def _GetKVMVersion(cls):
897 b52d85c1 Guido Trotter
    """Return the installed KVM version
898 b52d85c1 Guido Trotter

899 b52d85c1 Guido Trotter
    @return: (version, v_maj, v_min, v_rev), or None
900 b52d85c1 Guido Trotter

901 b52d85c1 Guido Trotter
    """
902 b52d85c1 Guido Trotter
    result = utils.RunCmd([constants.KVM_PATH, "--help"])
903 b52d85c1 Guido Trotter
    if result.failed:
904 b52d85c1 Guido Trotter
      return None
905 b52d85c1 Guido Trotter
    match = cls._VERSION_RE.search(result.output.splitlines()[0])
906 b52d85c1 Guido Trotter
    if not match:
907 b52d85c1 Guido Trotter
      return None
908 3f2eba25 Miguel Di Ciurcio Filho
909 3f2eba25 Miguel Di Ciurcio Filho
    return (match.group(0), int(match.group(1)), int(match.group(2)),
910 3f2eba25 Miguel Di Ciurcio Filho
            int(match.group(3)))
911 b52d85c1 Guido Trotter
912 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
913 eb58f9b1 Guido Trotter
    """Stop an instance.
914 eb58f9b1 Guido Trotter

915 eb58f9b1 Guido Trotter
    """
916 bbcf7ad0 Iustin Pop
    if name is not None and not force:
917 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
918 bbcf7ad0 Iustin Pop
    if name is None:
919 bbcf7ad0 Iustin Pop
      name = instance.name
920 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
921 bbcf7ad0 Iustin Pop
    else:
922 bbcf7ad0 Iustin Pop
      acpi = False
923 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
924 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
925 bbcf7ad0 Iustin Pop
      if force or not acpi:
926 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
927 eb58f9b1 Guido Trotter
      else:
928 bbcf7ad0 Iustin Pop
        self._CallMonitorCommand(name, 'system_powerdown')
929 eb58f9b1 Guido Trotter
930 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
931 8904b35c Guido Trotter
    """Cleanup after a stopped instance
932 8904b35c Guido Trotter

933 8904b35c Guido Trotter
    """
934 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
935 8904b35c Guido Trotter
    if pid > 0 and alive:
936 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
937 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
938 eb58f9b1 Guido Trotter
939 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
940 eb58f9b1 Guido Trotter
    """Reboot an instance.
941 eb58f9b1 Guido Trotter

942 eb58f9b1 Guido Trotter
    """
943 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
944 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
945 eb58f9b1 Guido Trotter
    # to shutdown and restart.
946 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
947 1f8b3a27 Guido Trotter
    if not alive:
948 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
949 78411c60 Iustin Pop
                                   " not running" % instance.name)
950 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
951 f02881e0 Guido Trotter
    # ...first load it...
952 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
953 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
954 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
955 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
956 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
957 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
958 f02881e0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
959 eb58f9b1 Guido Trotter
960 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
961 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
962 30e42c4e Guido Trotter

963 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
964 30e42c4e Guido Trotter
    @param instance: instance to be migrated
965 30e42c4e Guido Trotter
    @rtype: string
966 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
967 30e42c4e Guido Trotter

968 30e42c4e Guido Trotter
    """
969 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
970 30e42c4e Guido Trotter
971 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
972 30e42c4e Guido Trotter
    """Prepare to accept an instance.
973 30e42c4e Guido Trotter

974 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
975 30e42c4e Guido Trotter
    @param instance: instance to be accepted
976 30e42c4e Guido Trotter
    @type info: string
977 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
978 30e42c4e Guido Trotter
    @type target: string
979 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
980 30e42c4e Guido Trotter

981 30e42c4e Guido Trotter
    """
982 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
983 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
984 30e42c4e Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
985 30e42c4e Guido Trotter
986 30e42c4e Guido Trotter
  def FinalizeMigration(self, instance, info, success):
987 30e42c4e Guido Trotter
    """Finalize an instance migration.
988 30e42c4e Guido Trotter

989 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
990 30e42c4e Guido Trotter

991 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
992 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
993 30e42c4e Guido Trotter

994 30e42c4e Guido Trotter
    """
995 30e42c4e Guido Trotter
    if success:
996 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
997 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
998 5d9bfd87 Apollon Oikonomopoulos
999 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
1000 5d9bfd87 Apollon Oikonomopoulos
        try:
1001 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
1002 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
1003 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
1004 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
1005 5d9bfd87 Apollon Oikonomopoulos
          continue
1006 5d9bfd87 Apollon Oikonomopoulos
        try:
1007 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
1008 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
1009 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
1010 5d9bfd87 Apollon Oikonomopoulos
1011 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
1012 30e42c4e Guido Trotter
    else:
1013 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
1014 30e42c4e Guido Trotter
1015 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
1016 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
1017 30e42c4e Guido Trotter

1018 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
1019 30e42c4e Guido Trotter
    currently running.
1020 30e42c4e Guido Trotter

1021 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
1022 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
1023 30e42c4e Guido Trotter
    @type target: string
1024 30e42c4e Guido Trotter
    @param target: ip address of the target node
1025 30e42c4e Guido Trotter
    @type live: boolean
1026 30e42c4e Guido Trotter
    @param live: perform a live migration
1027 30e42c4e Guido Trotter

1028 30e42c4e Guido Trotter
    """
1029 58d38b02 Iustin Pop
    instance_name = instance.name
1030 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
1031 30e42c4e Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1032 30e42c4e Guido Trotter
    if not alive:
1033 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
1034 30e42c4e Guido Trotter
1035 30e42c4e Guido Trotter
    if not live:
1036 30e42c4e Guido Trotter
      self._CallMonitorCommand(instance_name, 'stop')
1037 30e42c4e Guido Trotter
1038 e43d4f9f Apollon Oikonomopoulos
    migrate_command = ('migrate_set_speed %dm' %
1039 e43d4f9f Apollon Oikonomopoulos
        instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1040 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
1041 e43d4f9f Apollon Oikonomopoulos
1042 e43d4f9f Apollon Oikonomopoulos
    migrate_command = ('migrate_set_downtime %dms' %
1043 e43d4f9f Apollon Oikonomopoulos
        instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
1044 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
1045 e43d4f9f Apollon Oikonomopoulos
1046 641ae041 Iustin Pop
    migrate_command = 'migrate -d tcp:%s:%s' % (target, port)
1047 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
1048 30e42c4e Guido Trotter
1049 30e42c4e Guido Trotter
    info_command = 'info migrate'
1050 30e42c4e Guido Trotter
    done = False
1051 c4e388a5 Guido Trotter
    broken_answers = 0
1052 30e42c4e Guido Trotter
    while not done:
1053 30e42c4e Guido Trotter
      result = self._CallMonitorCommand(instance_name, info_command)
1054 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
1055 30e42c4e Guido Trotter
      if not match:
1056 c4e388a5 Guido Trotter
        broken_answers += 1
1057 c4e388a5 Guido Trotter
        if not result.stdout:
1058 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
1059 c4e388a5 Guido Trotter
        else:
1060 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
1061 c4e388a5 Guido Trotter
                          result.stdout)
1062 c4e388a5 Guido Trotter
        time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1063 30e42c4e Guido Trotter
      else:
1064 30e42c4e Guido Trotter
        status = match.group(1)
1065 30e42c4e Guido Trotter
        if status == 'completed':
1066 30e42c4e Guido Trotter
          done = True
1067 30e42c4e Guido Trotter
        elif status == 'active':
1068 c4e388a5 Guido Trotter
          # reset the broken answers count
1069 c4e388a5 Guido Trotter
          broken_answers = 0
1070 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1071 c087266c Guido Trotter
        elif status == 'failed' or status == 'cancelled':
1072 c087266c Guido Trotter
          if not live:
1073 c087266c Guido Trotter
            self._CallMonitorCommand(instance_name, 'cont')
1074 c087266c Guido Trotter
          raise errors.HypervisorError("Migration %s at the kvm level" %
1075 c087266c Guido Trotter
                                       status)
1076 30e42c4e Guido Trotter
        else:
1077 c4e388a5 Guido Trotter
          logging.warning("KVM: unknown migration status '%s'", status)
1078 c4e388a5 Guido Trotter
          broken_answers += 1
1079 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1080 c4e388a5 Guido Trotter
      if broken_answers >= self._MIGRATION_INFO_MAX_BAD_ANSWERS:
1081 c4e388a5 Guido Trotter
        raise errors.HypervisorError("Too many 'info migrate' broken answers")
1082 30e42c4e Guido Trotter
1083 30e42c4e Guido Trotter
    utils.KillProcess(pid)
1084 7b381438 Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1085 30e42c4e Guido Trotter
1086 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
1087 eb58f9b1 Guido Trotter
    """Return information about the node.
1088 eb58f9b1 Guido Trotter

1089 572e52bf Iustin Pop
    This is just a wrapper over the base GetLinuxNodeInfo method.
1090 572e52bf Iustin Pop

1091 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
1092 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
1093 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
1094 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
1095 eb58f9b1 Guido Trotter

1096 eb58f9b1 Guido Trotter
    """
1097 572e52bf Iustin Pop
    return self.GetLinuxNodeInfo()
1098 eb58f9b1 Guido Trotter
1099 637ce7f9 Guido Trotter
  @classmethod
1100 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
1101 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
1102 eb58f9b1 Guido Trotter

1103 eb58f9b1 Guido Trotter
    """
1104 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
1105 55cc0a44 Michael Hanselmann
      cmd = [constants.SOCAT_PATH,
1106 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
1107 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
1108 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
1109 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
1110 55cc0a44 Michael Hanselmann
                                     host=instance.primary_node,
1111 55cc0a44 Michael Hanselmann
                                     user=constants.GANETI_RUNAS,
1112 55cc0a44 Michael Hanselmann
                                     command=cmd)
1113 3be34f57 Guido Trotter
1114 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
1115 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
1116 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
1117 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
1118 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
1119 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
1120 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
1121 55cc0a44 Michael Hanselmann
                                     display=display)
1122 55cc0a44 Michael Hanselmann
1123 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
1124 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
1125 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
1126 55cc0a44 Michael Hanselmann
                                            instance.name))
1127 eb58f9b1 Guido Trotter
1128 eb58f9b1 Guido Trotter
  def Verify(self):
1129 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
1130 eb58f9b1 Guido Trotter

1131 eb58f9b1 Guido Trotter
    Check that the binary exists.
1132 eb58f9b1 Guido Trotter

1133 eb58f9b1 Guido Trotter
    """
1134 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
1135 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
1136 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
1137 14aa53cb Guido Trotter
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
1138 14aa53cb Guido Trotter
1139 6b5605e8 Iustin Pop
  @classmethod
1140 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
1141 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
1142 6b5605e8 Iustin Pop

1143 6b5605e8 Iustin Pop
    @type hvparams:  dict
1144 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
1145 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
1146 6b5605e8 Iustin Pop

1147 6b5605e8 Iustin Pop
    """
1148 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
1149 6b5605e8 Iustin Pop
1150 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
1151 df5ab9f0 Guido Trotter
    if kernel_path:
1152 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
1153 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
1154 205ab586 Iustin Pop
                                     " if a kernel is defined")
1155 6b5605e8 Iustin Pop
1156 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
1157 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
1158 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
1159 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
1160 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
1161 66d5dbef Guido Trotter
1162 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
1163 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
1164 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
1165 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
1166 835528af Iustin Pop
                                   " ISO path")
1167 f5118ade Iustin Pop
1168 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
1169 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
1170 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
1171 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
1172 d19d94db Guido Trotter
                                     " must be specified")
1173 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
1174 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
1175 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
1176 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
1177 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
1178 d19d94db Guido Trotter
1179 d19d94db Guido Trotter
  @classmethod
1180 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
1181 d19d94db Guido Trotter
    """Check the given parameters for validity.
1182 d19d94db Guido Trotter

1183 d19d94db Guido Trotter
    @type hvparams:  dict
1184 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
1185 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
1186 d19d94db Guido Trotter

1187 d19d94db Guido Trotter
    """
1188 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
1189 d19d94db Guido Trotter
1190 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
1191 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
1192 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
1193 d19d94db Guido Trotter
      try:
1194 1feb39ec Guido Trotter
        pwd.getpwnam(username)
1195 d19d94db Guido Trotter
      except KeyError:
1196 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
1197 d19d94db Guido Trotter
                                     % username)
1198 d19d94db Guido Trotter
1199 f5118ade Iustin Pop
  @classmethod
1200 f5118ade Iustin Pop
  def PowercycleNode(cls):
1201 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
1202 f5118ade Iustin Pop

1203 f5118ade Iustin Pop
    """
1204 f5118ade Iustin Pop
    cls.LinuxPowercycle()