Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 45df0793

History | View | Annotate | Download (43.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 cc130cc7 Marco Casavecchia
    constants.HV_KVM_FLOPPY_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
168 205ab586 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
169 cc130cc7 Marco Casavecchia
    constants.HV_KVM_CDROM2_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
170 d73ef63f Michael Hanselmann
    constants.HV_BOOT_ORDER:
171 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
172 d73ef63f Michael Hanselmann
    constants.HV_NIC_TYPE:
173 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
174 d73ef63f Michael Hanselmann
    constants.HV_DISK_TYPE:
175 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
176 cc130cc7 Marco Casavecchia
    constants.HV_KVM_CDROM_DISK_TYPE:
177 cc130cc7 Marco Casavecchia
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_DISK_TYPES),
178 d73ef63f Michael Hanselmann
    constants.HV_USB_MOUSE:
179 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
180 78411c60 Iustin Pop
    constants.HV_MIGRATION_PORT: hv_base.NET_PORT_CHECK,
181 e43d4f9f Apollon Oikonomopoulos
    constants.HV_MIGRATION_BANDWIDTH: hv_base.NO_CHECK,
182 e43d4f9f Apollon Oikonomopoulos
    constants.HV_MIGRATION_DOWNTIME: hv_base.NO_CHECK,
183 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
184 6b970cef Jun Futagawa
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
185 19572932 Iustin Pop
    constants.HV_DISK_CACHE:
186 19572932 Iustin Pop
      hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
187 d19d94db Guido Trotter
    constants.HV_SECURITY_MODEL:
188 d19d94db Guido Trotter
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_SM_TYPES),
189 d19d94db Guido Trotter
    constants.HV_SECURITY_DOMAIN: hv_base.NO_CHECK,
190 7ba594c0 Guido Trotter
    constants.HV_KVM_FLAG:
191 7ba594c0 Guido Trotter
      hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES),
192 fbe27e2b Guido Trotter
    constants.HV_VHOST_NET: hv_base.NO_CHECK,
193 547a63b7 Balazs Lecz
    constants.HV_KVM_USE_CHROOT: hv_base.NO_CHECK,
194 4f958b0b Miguel Di Ciurcio Filho
    constants.HV_MEM_PATH: hv_base.OPT_DIR_CHECK,
195 205ab586 Iustin Pop
    }
196 6b5605e8 Iustin Pop
197 30e42c4e Guido Trotter
  _MIGRATION_STATUS_RE = re.compile('Migration\s+status:\s+(\w+)',
198 30e42c4e Guido Trotter
                                    re.M | re.I)
199 c4e388a5 Guido Trotter
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
200 c4e388a5 Guido Trotter
  _MIGRATION_INFO_RETRY_DELAY = 2
201 30e42c4e Guido Trotter
202 b52d85c1 Guido Trotter
  _VERSION_RE = re.compile(r"\b(\d+)\.(\d+)\.(\d+)\b")
203 b52d85c1 Guido Trotter
204 64bfbc08 Guido Trotter
  ANCILLARY_FILES = [
205 64bfbc08 Guido Trotter
    _KVM_NETWORK_SCRIPT,
206 64bfbc08 Guido Trotter
    ]
207 64bfbc08 Guido Trotter
208 eb58f9b1 Guido Trotter
  def __init__(self):
209 eb58f9b1 Guido Trotter
    hv_base.BaseHypervisor.__init__(self)
210 eb58f9b1 Guido Trotter
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
211 eb58f9b1 Guido Trotter
    # in a tmpfs filesystem or has been otherwise wiped out.
212 29921401 Iustin Pop
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
213 9afb67fe Guido Trotter
    utils.EnsureDirs(dirs)
214 eb58f9b1 Guido Trotter
215 30786fc9 Iustin Pop
  @classmethod
216 30786fc9 Iustin Pop
  def _InstancePidFile(cls, instance_name):
217 98ec75d6 Iustin Pop
    """Returns the instance pidfile.
218 98ec75d6 Iustin Pop

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

226 7548396c Guido Trotter
    """
227 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
228 7548396c Guido Trotter
229 7548396c Guido Trotter
  @classmethod
230 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
231 263b8de6 Guido Trotter
    """Check pid file for instance information.
232 263b8de6 Guido Trotter

233 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
234 263b8de6 Guido Trotter
    information from its command line.
235 263b8de6 Guido Trotter

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

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

277 263b8de6 Guido Trotter
    @type instance_name: string
278 263b8de6 Guido Trotter
    @param instance_name: instance name
279 263b8de6 Guido Trotter
    @rtype: tuple
280 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
281 1f8b3a27 Guido Trotter

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

473 4fbb3c60 Guido Trotter
    @type instance_name: string
474 c41eea6e Iustin Pop
    @param instance_name: the instance name
475 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
476 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
477 eb58f9b1 Guido Trotter

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

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

494 eb58f9b1 Guido Trotter
    """
495 eb58f9b1 Guido Trotter
    data = []
496 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
497 263b8de6 Guido Trotter
      try:
498 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
499 263b8de6 Guido Trotter
      except errors.HypervisorError:
500 263b8de6 Guido Trotter
        continue
501 263b8de6 Guido Trotter
      if info:
502 263b8de6 Guido Trotter
        data.append(info)
503 eb58f9b1 Guido Trotter
    return data
504 eb58f9b1 Guido Trotter
505 323f9095 Stephen Shirley
  def _GenerateKVMRuntime(self, instance, block_devices, startup_paused):
506 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
507 eb58f9b1 Guido Trotter

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

710 38e250ba Guido Trotter
    """
711 38e250ba Guido Trotter
    try:
712 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
713 38e250ba Guido Trotter
                      data=data)
714 90c024f6 Guido Trotter
    except EnvironmentError, err:
715 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
716 38e250ba Guido Trotter
717 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
718 38e250ba Guido Trotter
    """Read an instance's KVM runtime
719 38e250ba Guido Trotter

720 38e250ba Guido Trotter
    """
721 38e250ba Guido Trotter
    try:
722 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
723 90c024f6 Guido Trotter
    except EnvironmentError, err:
724 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
725 38e250ba Guido Trotter
    return file_content
726 38e250ba Guido Trotter
727 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
728 38e250ba Guido Trotter
    """Save an instance's KVM runtime
729 38e250ba Guido Trotter

730 38e250ba Guido Trotter
    """
731 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
732 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
733 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
734 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
735 38e250ba Guido Trotter
736 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
737 38e250ba Guido Trotter
    """Load an instance's KVM runtime
738 38e250ba Guido Trotter

739 38e250ba Guido Trotter
    """
740 30e42c4e Guido Trotter
    if not serialized_runtime:
741 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
742 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
743 c2672466 Guido Trotter
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
744 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
745 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
746 38e250ba Guido Trotter
747 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
748 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
749 76431533 Guido Trotter

750 76431533 Guido Trotter
    @type name: string
751 76431533 Guido Trotter
    @param name: instance name
752 76431533 Guido Trotter
    @type kvm_cmd: list of strings
753 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
754 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
755 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
756 76431533 Guido Trotter

757 76431533 Guido Trotter
    """
758 5d9bfd87 Apollon Oikonomopoulos
    try:
759 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
760 5d9bfd87 Apollon Oikonomopoulos
    finally:
761 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
762 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
763 5d9bfd87 Apollon Oikonomopoulos
764 76431533 Guido Trotter
    if result.failed:
765 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
766 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
767 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
768 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
769 76431533 Guido Trotter
770 30e42c4e Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
771 ee5f20b0 Guido Trotter
    """Execute a KVM cmd, after completing it with some last minute data
772 ee5f20b0 Guido Trotter

773 30e42c4e Guido Trotter
    @type incoming: tuple of strings
774 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
775 30e42c4e Guido Trotter

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

911 ee5f20b0 Guido Trotter
    """
912 5905901c Iustin Pop
    self._CheckDown(instance.name)
913 7238edb5 Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices,
914 7238edb5 Iustin Pop
                                           startup_paused)
915 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
916 ee5f20b0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
917 ee5f20b0 Guido Trotter
918 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
919 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
920 6567aff3 Guido Trotter

921 6567aff3 Guido Trotter
    """
922 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
923 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
924 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
925 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
926 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
927 6567aff3 Guido Trotter
    if result.failed:
928 6567aff3 Guido Trotter
      msg = ("Failed to send command '%s' to instance %s."
929 6567aff3 Guido Trotter
             " output: %s, error: %s, fail_reason: %s" %
930 9798fcae Guido Trotter
             (command, instance_name,
931 9798fcae Guido Trotter
              result.stdout, result.stderr, result.fail_reason))
932 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
933 6567aff3 Guido Trotter
934 6567aff3 Guido Trotter
    return result
935 6567aff3 Guido Trotter
936 b52d85c1 Guido Trotter
  @classmethod
937 b52d85c1 Guido Trotter
  def _GetKVMVersion(cls):
938 b52d85c1 Guido Trotter
    """Return the installed KVM version
939 b52d85c1 Guido Trotter

940 b52d85c1 Guido Trotter
    @return: (version, v_maj, v_min, v_rev), or None
941 b52d85c1 Guido Trotter

942 b52d85c1 Guido Trotter
    """
943 b52d85c1 Guido Trotter
    result = utils.RunCmd([constants.KVM_PATH, "--help"])
944 b52d85c1 Guido Trotter
    if result.failed:
945 b52d85c1 Guido Trotter
      return None
946 b52d85c1 Guido Trotter
    match = cls._VERSION_RE.search(result.output.splitlines()[0])
947 b52d85c1 Guido Trotter
    if not match:
948 b52d85c1 Guido Trotter
      return None
949 3f2eba25 Miguel Di Ciurcio Filho
950 3f2eba25 Miguel Di Ciurcio Filho
    return (match.group(0), int(match.group(1)), int(match.group(2)),
951 3f2eba25 Miguel Di Ciurcio Filho
            int(match.group(3)))
952 b52d85c1 Guido Trotter
953 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
954 eb58f9b1 Guido Trotter
    """Stop an instance.
955 eb58f9b1 Guido Trotter

956 eb58f9b1 Guido Trotter
    """
957 bbcf7ad0 Iustin Pop
    if name is not None and not force:
958 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
959 bbcf7ad0 Iustin Pop
    if name is None:
960 bbcf7ad0 Iustin Pop
      name = instance.name
961 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
962 bbcf7ad0 Iustin Pop
    else:
963 bbcf7ad0 Iustin Pop
      acpi = False
964 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
965 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
966 bbcf7ad0 Iustin Pop
      if force or not acpi:
967 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
968 eb58f9b1 Guido Trotter
      else:
969 bbcf7ad0 Iustin Pop
        self._CallMonitorCommand(name, 'system_powerdown')
970 eb58f9b1 Guido Trotter
971 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
972 8904b35c Guido Trotter
    """Cleanup after a stopped instance
973 8904b35c Guido Trotter

974 8904b35c Guido Trotter
    """
975 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
976 8904b35c Guido Trotter
    if pid > 0 and alive:
977 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
978 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
979 eb58f9b1 Guido Trotter
980 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
981 eb58f9b1 Guido Trotter
    """Reboot an instance.
982 eb58f9b1 Guido Trotter

983 eb58f9b1 Guido Trotter
    """
984 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
985 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
986 eb58f9b1 Guido Trotter
    # to shutdown and restart.
987 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
988 1f8b3a27 Guido Trotter
    if not alive:
989 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
990 78411c60 Iustin Pop
                                   " not running" % instance.name)
991 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
992 f02881e0 Guido Trotter
    # ...first load it...
993 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
994 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
995 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
996 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
997 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
998 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
999 f02881e0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
1000 eb58f9b1 Guido Trotter
1001 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
1002 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
1003 30e42c4e Guido Trotter

1004 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1005 30e42c4e Guido Trotter
    @param instance: instance to be migrated
1006 30e42c4e Guido Trotter
    @rtype: string
1007 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
1008 30e42c4e Guido Trotter

1009 30e42c4e Guido Trotter
    """
1010 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
1011 30e42c4e Guido Trotter
1012 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
1013 30e42c4e Guido Trotter
    """Prepare to accept an instance.
1014 30e42c4e Guido Trotter

1015 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1016 30e42c4e Guido Trotter
    @param instance: instance to be accepted
1017 30e42c4e Guido Trotter
    @type info: string
1018 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
1019 30e42c4e Guido Trotter
    @type target: string
1020 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
1021 30e42c4e Guido Trotter

1022 30e42c4e Guido Trotter
    """
1023 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1024 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1025 30e42c4e Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
1026 30e42c4e Guido Trotter
1027 30e42c4e Guido Trotter
  def FinalizeMigration(self, instance, info, success):
1028 30e42c4e Guido Trotter
    """Finalize an instance migration.
1029 30e42c4e Guido Trotter

1030 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
1031 30e42c4e Guido Trotter

1032 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1033 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
1034 30e42c4e Guido Trotter

1035 30e42c4e Guido Trotter
    """
1036 30e42c4e Guido Trotter
    if success:
1037 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1038 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
1039 5d9bfd87 Apollon Oikonomopoulos
1040 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
1041 cc8a8ed7 Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1042 cc8a8ed7 Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
1043 cc8a8ed7 Apollon Oikonomopoulos
          continue
1044 5d9bfd87 Apollon Oikonomopoulos
        try:
1045 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
1046 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
1047 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
1048 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
1049 5d9bfd87 Apollon Oikonomopoulos
          continue
1050 5d9bfd87 Apollon Oikonomopoulos
        try:
1051 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
1052 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
1053 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
1054 5d9bfd87 Apollon Oikonomopoulos
1055 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
1056 30e42c4e Guido Trotter
    else:
1057 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
1058 30e42c4e Guido Trotter
1059 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
1060 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
1061 30e42c4e Guido Trotter

1062 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
1063 30e42c4e Guido Trotter
    currently running.
1064 30e42c4e Guido Trotter

1065 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
1066 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
1067 30e42c4e Guido Trotter
    @type target: string
1068 30e42c4e Guido Trotter
    @param target: ip address of the target node
1069 30e42c4e Guido Trotter
    @type live: boolean
1070 30e42c4e Guido Trotter
    @param live: perform a live migration
1071 30e42c4e Guido Trotter

1072 30e42c4e Guido Trotter
    """
1073 58d38b02 Iustin Pop
    instance_name = instance.name
1074 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
1075 30e42c4e Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1076 30e42c4e Guido Trotter
    if not alive:
1077 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
1078 30e42c4e Guido Trotter
1079 30e42c4e Guido Trotter
    if not live:
1080 30e42c4e Guido Trotter
      self._CallMonitorCommand(instance_name, 'stop')
1081 30e42c4e Guido Trotter
1082 e43d4f9f Apollon Oikonomopoulos
    migrate_command = ('migrate_set_speed %dm' %
1083 e43d4f9f Apollon Oikonomopoulos
        instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1084 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
1085 e43d4f9f Apollon Oikonomopoulos
1086 e43d4f9f Apollon Oikonomopoulos
    migrate_command = ('migrate_set_downtime %dms' %
1087 e43d4f9f Apollon Oikonomopoulos
        instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
1088 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
1089 e43d4f9f Apollon Oikonomopoulos
1090 641ae041 Iustin Pop
    migrate_command = 'migrate -d tcp:%s:%s' % (target, port)
1091 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
1092 30e42c4e Guido Trotter
1093 30e42c4e Guido Trotter
    info_command = 'info migrate'
1094 30e42c4e Guido Trotter
    done = False
1095 c4e388a5 Guido Trotter
    broken_answers = 0
1096 30e42c4e Guido Trotter
    while not done:
1097 30e42c4e Guido Trotter
      result = self._CallMonitorCommand(instance_name, info_command)
1098 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
1099 30e42c4e Guido Trotter
      if not match:
1100 c4e388a5 Guido Trotter
        broken_answers += 1
1101 c4e388a5 Guido Trotter
        if not result.stdout:
1102 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
1103 c4e388a5 Guido Trotter
        else:
1104 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
1105 c4e388a5 Guido Trotter
                          result.stdout)
1106 c4e388a5 Guido Trotter
        time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1107 30e42c4e Guido Trotter
      else:
1108 30e42c4e Guido Trotter
        status = match.group(1)
1109 30e42c4e Guido Trotter
        if status == 'completed':
1110 30e42c4e Guido Trotter
          done = True
1111 30e42c4e Guido Trotter
        elif status == 'active':
1112 c4e388a5 Guido Trotter
          # reset the broken answers count
1113 c4e388a5 Guido Trotter
          broken_answers = 0
1114 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1115 c087266c Guido Trotter
        elif status == 'failed' or status == 'cancelled':
1116 c087266c Guido Trotter
          if not live:
1117 c087266c Guido Trotter
            self._CallMonitorCommand(instance_name, 'cont')
1118 c087266c Guido Trotter
          raise errors.HypervisorError("Migration %s at the kvm level" %
1119 c087266c Guido Trotter
                                       status)
1120 30e42c4e Guido Trotter
        else:
1121 c4e388a5 Guido Trotter
          logging.warning("KVM: unknown migration status '%s'", status)
1122 c4e388a5 Guido Trotter
          broken_answers += 1
1123 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1124 c4e388a5 Guido Trotter
      if broken_answers >= self._MIGRATION_INFO_MAX_BAD_ANSWERS:
1125 c4e388a5 Guido Trotter
        raise errors.HypervisorError("Too many 'info migrate' broken answers")
1126 30e42c4e Guido Trotter
1127 30e42c4e Guido Trotter
    utils.KillProcess(pid)
1128 7b381438 Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1129 30e42c4e Guido Trotter
1130 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
1131 eb58f9b1 Guido Trotter
    """Return information about the node.
1132 eb58f9b1 Guido Trotter

1133 572e52bf Iustin Pop
    This is just a wrapper over the base GetLinuxNodeInfo method.
1134 572e52bf Iustin Pop

1135 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
1136 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
1137 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
1138 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
1139 eb58f9b1 Guido Trotter

1140 eb58f9b1 Guido Trotter
    """
1141 572e52bf Iustin Pop
    return self.GetLinuxNodeInfo()
1142 eb58f9b1 Guido Trotter
1143 637ce7f9 Guido Trotter
  @classmethod
1144 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
1145 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
1146 eb58f9b1 Guido Trotter

1147 eb58f9b1 Guido Trotter
    """
1148 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
1149 2f4c951e Stephen Shirley
      cmd = [constants.KVM_CONSOLE_WRAPPER,
1150 2f4c951e Stephen Shirley
             constants.SOCAT_PATH, utils.ShellQuote(instance.name),
1151 2f4c951e Stephen Shirley
             utils.ShellQuote(cls._InstanceMonitor(instance.name)),
1152 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
1153 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
1154 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
1155 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
1156 55cc0a44 Michael Hanselmann
                                     host=instance.primary_node,
1157 55cc0a44 Michael Hanselmann
                                     user=constants.GANETI_RUNAS,
1158 55cc0a44 Michael Hanselmann
                                     command=cmd)
1159 3be34f57 Guido Trotter
1160 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
1161 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
1162 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
1163 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
1164 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
1165 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
1166 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
1167 55cc0a44 Michael Hanselmann
                                     display=display)
1168 55cc0a44 Michael Hanselmann
1169 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
1170 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
1171 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
1172 55cc0a44 Michael Hanselmann
                                            instance.name))
1173 eb58f9b1 Guido Trotter
1174 eb58f9b1 Guido Trotter
  def Verify(self):
1175 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
1176 eb58f9b1 Guido Trotter

1177 eb58f9b1 Guido Trotter
    Check that the binary exists.
1178 eb58f9b1 Guido Trotter

1179 eb58f9b1 Guido Trotter
    """
1180 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
1181 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
1182 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
1183 14aa53cb Guido Trotter
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
1184 14aa53cb Guido Trotter
1185 6b5605e8 Iustin Pop
  @classmethod
1186 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
1187 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
1188 6b5605e8 Iustin Pop

1189 6b5605e8 Iustin Pop
    @type hvparams:  dict
1190 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
1191 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
1192 6b5605e8 Iustin Pop

1193 6b5605e8 Iustin Pop
    """
1194 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
1195 6b5605e8 Iustin Pop
1196 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
1197 df5ab9f0 Guido Trotter
    if kernel_path:
1198 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
1199 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
1200 205ab586 Iustin Pop
                                     " if a kernel is defined")
1201 6b5605e8 Iustin Pop
1202 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
1203 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
1204 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
1205 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
1206 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
1207 66d5dbef Guido Trotter
1208 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
1209 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
1210 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
1211 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
1212 835528af Iustin Pop
                                   " ISO path")
1213 f5118ade Iustin Pop
1214 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
1215 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
1216 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
1217 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
1218 d19d94db Guido Trotter
                                     " must be specified")
1219 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
1220 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
1221 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
1222 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
1223 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
1224 d19d94db Guido Trotter
1225 d19d94db Guido Trotter
  @classmethod
1226 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
1227 d19d94db Guido Trotter
    """Check the given parameters for validity.
1228 d19d94db Guido Trotter

1229 d19d94db Guido Trotter
    @type hvparams:  dict
1230 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
1231 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
1232 d19d94db Guido Trotter

1233 d19d94db Guido Trotter
    """
1234 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
1235 d19d94db Guido Trotter
1236 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
1237 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
1238 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
1239 d19d94db Guido Trotter
      try:
1240 1feb39ec Guido Trotter
        pwd.getpwnam(username)
1241 d19d94db Guido Trotter
      except KeyError:
1242 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
1243 d19d94db Guido Trotter
                                     % username)
1244 d19d94db Guido Trotter
1245 f5118ade Iustin Pop
  @classmethod
1246 f5118ade Iustin Pop
  def PowercycleNode(cls):
1247 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
1248 f5118ade Iustin Pop

1249 f5118ade Iustin Pop
    """
1250 f5118ade Iustin Pop
    cls.LinuxPowercycle()