Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 1f8194b3

History | View | Annotate | Download (43.9 kB)

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

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

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

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

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

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

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

134 43fcf0d3 Apollon Oikonomopoulos
  """
135 43fcf0d3 Apollon Oikonomopoulos
  req = urllib2.Request(url)
136 43fcf0d3 Apollon Oikonomopoulos
137 43fcf0d3 Apollon Oikonomopoulos
  # XXX: ugly but true
138 43fcf0d3 Apollon Oikonomopoulos
  req.get_method = lambda: "HEAD"
139 43fcf0d3 Apollon Oikonomopoulos
140 43fcf0d3 Apollon Oikonomopoulos
  try:
141 43fcf0d3 Apollon Oikonomopoulos
    resp = urllib2.urlopen(req)
142 43fcf0d3 Apollon Oikonomopoulos
  except urllib2.URLError:
143 43fcf0d3 Apollon Oikonomopoulos
    return False
144 43fcf0d3 Apollon Oikonomopoulos
145 43fcf0d3 Apollon Oikonomopoulos
  del resp
146 43fcf0d3 Apollon Oikonomopoulos
  return True
147 43fcf0d3 Apollon Oikonomopoulos
148 43fcf0d3 Apollon Oikonomopoulos
149 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
150 c4469f75 Guido Trotter
  """KVM hypervisor interface"""
151 d271c6fd Iustin Pop
  CAN_MIGRATE = True
152 eb58f9b1 Guido Trotter
153 eb58f9b1 Guido Trotter
  _ROOT_DIR = constants.RUN_GANETI_DIR + "/kvm-hypervisor"
154 a1d79fc6 Guido Trotter
  _PIDS_DIR = _ROOT_DIR + "/pid" # contains live instances pids
155 7548396c Guido Trotter
  _UIDS_DIR = _ROOT_DIR + "/uid" # contains instances reserved uids
156 a1d79fc6 Guido Trotter
  _CTRL_DIR = _ROOT_DIR + "/ctrl" # contains instances control sockets
157 a1d79fc6 Guido Trotter
  _CONF_DIR = _ROOT_DIR + "/conf" # contains instances startup data
158 5d9bfd87 Apollon Oikonomopoulos
  _NICS_DIR = _ROOT_DIR + "/nic" # contains instances nic <-> tap associations
159 547a63b7 Balazs Lecz
  # KVM instances with chroot enabled are started in empty chroot directories.
160 547a63b7 Balazs Lecz
  _CHROOT_DIR = _ROOT_DIR + "/chroot" # for empty chroot directories
161 547a63b7 Balazs Lecz
  # After an instance is stopped, its chroot directory is removed.
162 547a63b7 Balazs Lecz
  # If the chroot directory is not empty, it can't be removed.
163 547a63b7 Balazs Lecz
  # A non-empty chroot directory indicates a possible security incident.
164 547a63b7 Balazs Lecz
  # To support forensics, the non-empty chroot directory is quarantined in
165 547a63b7 Balazs Lecz
  # a separate directory, called 'chroot-quarantine'.
166 547a63b7 Balazs Lecz
  _CHROOT_QUARANTINE_DIR = _ROOT_DIR + "/chroot-quarantine"
167 5d9bfd87 Apollon Oikonomopoulos
  _DIRS = [_ROOT_DIR, _PIDS_DIR, _UIDS_DIR, _CTRL_DIR, _CONF_DIR, _NICS_DIR,
168 547a63b7 Balazs Lecz
           _CHROOT_DIR, _CHROOT_QUARANTINE_DIR]
169 eb58f9b1 Guido Trotter
170 205ab586 Iustin Pop
  PARAMETERS = {
171 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK,
172 205ab586 Iustin Pop
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
173 205ab586 Iustin Pop
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
174 205ab586 Iustin Pop
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
175 205ab586 Iustin Pop
    constants.HV_ACPI: hv_base.NO_CHECK,
176 205ab586 Iustin Pop
    constants.HV_SERIAL_CONSOLE: hv_base.NO_CHECK,
177 d73ef63f Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS:
178 8b312c1d Manuel Franceschini
      (False, lambda x: (netutils.IP4Address.IsValid(x) or
179 8b312c1d Manuel Franceschini
                         utils.IsNormAbsPath(x)),
180 d73ef63f Michael Hanselmann
       "the VNC bind address must be either a valid IP address or an absolute"
181 d73ef63f Michael Hanselmann
       " pathname", None, None),
182 205ab586 Iustin Pop
    constants.HV_VNC_TLS: hv_base.NO_CHECK,
183 205ab586 Iustin Pop
    constants.HV_VNC_X509: hv_base.OPT_DIR_CHECK,
184 205ab586 Iustin Pop
    constants.HV_VNC_X509_VERIFY: hv_base.NO_CHECK,
185 6e6bb8d5 Guido Trotter
    constants.HV_VNC_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
186 fba7f911 Marco Casavecchia
    constants.HV_KVM_FLOPPY_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
187 c1dc897b Apollon Oikonomopoulos
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_OR_URL_CHECK,
188 fba7f911 Marco Casavecchia
    constants.HV_KVM_CDROM2_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
189 d73ef63f Michael Hanselmann
    constants.HV_BOOT_ORDER:
190 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
191 d73ef63f Michael Hanselmann
    constants.HV_NIC_TYPE:
192 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
193 d73ef63f Michael Hanselmann
    constants.HV_DISK_TYPE:
194 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
195 fba7f911 Marco Casavecchia
    constants.HV_KVM_CDROM_DISK_TYPE:
196 fba7f911 Marco Casavecchia
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_DISK_TYPES),
197 d73ef63f Michael Hanselmann
    constants.HV_USB_MOUSE:
198 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
199 78411c60 Iustin Pop
    constants.HV_MIGRATION_PORT: hv_base.NET_PORT_CHECK,
200 e43d4f9f Apollon Oikonomopoulos
    constants.HV_MIGRATION_BANDWIDTH: hv_base.NO_CHECK,
201 e43d4f9f Apollon Oikonomopoulos
    constants.HV_MIGRATION_DOWNTIME: hv_base.NO_CHECK,
202 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
203 6b970cef Jun Futagawa
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
204 19572932 Iustin Pop
    constants.HV_DISK_CACHE:
205 19572932 Iustin Pop
      hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
206 d19d94db Guido Trotter
    constants.HV_SECURITY_MODEL:
207 d19d94db Guido Trotter
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_SM_TYPES),
208 d19d94db Guido Trotter
    constants.HV_SECURITY_DOMAIN: hv_base.NO_CHECK,
209 7ba594c0 Guido Trotter
    constants.HV_KVM_FLAG:
210 7ba594c0 Guido Trotter
      hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES),
211 fbe27e2b Guido Trotter
    constants.HV_VHOST_NET: hv_base.NO_CHECK,
212 547a63b7 Balazs Lecz
    constants.HV_KVM_USE_CHROOT: hv_base.NO_CHECK,
213 4f958b0b Miguel Di Ciurcio Filho
    constants.HV_MEM_PATH: hv_base.OPT_DIR_CHECK,
214 205ab586 Iustin Pop
    }
215 6b5605e8 Iustin Pop
216 30e42c4e Guido Trotter
  _MIGRATION_STATUS_RE = re.compile('Migration\s+status:\s+(\w+)',
217 30e42c4e Guido Trotter
                                    re.M | re.I)
218 c4e388a5 Guido Trotter
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
219 f7d61653 Apollon Oikonomopoulos
  _MIGRATION_INFO_RETRY_DELAY = 1
220 30e42c4e Guido Trotter
221 b52d85c1 Guido Trotter
  _VERSION_RE = re.compile(r"\b(\d+)\.(\d+)\.(\d+)\b")
222 b52d85c1 Guido Trotter
223 64bfbc08 Guido Trotter
  ANCILLARY_FILES = [
224 64bfbc08 Guido Trotter
    _KVM_NETWORK_SCRIPT,
225 64bfbc08 Guido Trotter
    ]
226 64bfbc08 Guido Trotter
227 eb58f9b1 Guido Trotter
  def __init__(self):
228 eb58f9b1 Guido Trotter
    hv_base.BaseHypervisor.__init__(self)
229 eb58f9b1 Guido Trotter
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
230 eb58f9b1 Guido Trotter
    # in a tmpfs filesystem or has been otherwise wiped out.
231 29921401 Iustin Pop
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
232 9afb67fe Guido Trotter
    utils.EnsureDirs(dirs)
233 eb58f9b1 Guido Trotter
234 30786fc9 Iustin Pop
  @classmethod
235 30786fc9 Iustin Pop
  def _InstancePidFile(cls, instance_name):
236 98ec75d6 Iustin Pop
    """Returns the instance pidfile.
237 98ec75d6 Iustin Pop

238 98ec75d6 Iustin Pop
    """
239 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
240 98ec75d6 Iustin Pop
241 263b8de6 Guido Trotter
  @classmethod
242 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
243 7548396c Guido Trotter
    """Returns the instance uidfile.
244 7548396c Guido Trotter

245 7548396c Guido Trotter
    """
246 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
247 7548396c Guido Trotter
248 7548396c Guido Trotter
  @classmethod
249 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
250 263b8de6 Guido Trotter
    """Check pid file for instance information.
251 263b8de6 Guido Trotter

252 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
253 263b8de6 Guido Trotter
    information from its command line.
254 263b8de6 Guido Trotter

255 263b8de6 Guido Trotter
    @type pid: string or int
256 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
257 263b8de6 Guido Trotter
    @rtype: tuple
258 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
259 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
260 263b8de6 Guido Trotter

261 263b8de6 Guido Trotter
    """
262 263b8de6 Guido Trotter
    alive = utils.IsProcessAlive(pid)
263 263b8de6 Guido Trotter
    if not alive:
264 263b8de6 Guido Trotter
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
265 263b8de6 Guido Trotter
266 263b8de6 Guido Trotter
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
267 263b8de6 Guido Trotter
    try:
268 263b8de6 Guido Trotter
      cmdline = utils.ReadFile(cmdline_file)
269 263b8de6 Guido Trotter
    except EnvironmentError, err:
270 263b8de6 Guido Trotter
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
271 263b8de6 Guido Trotter
                                   (pid, err))
272 263b8de6 Guido Trotter
273 263b8de6 Guido Trotter
    instance = None
274 263b8de6 Guido Trotter
    memory = 0
275 263b8de6 Guido Trotter
    vcpus = 0
276 263b8de6 Guido Trotter
277 263b8de6 Guido Trotter
    arg_list = cmdline.split('\x00')
278 263b8de6 Guido Trotter
    while arg_list:
279 263b8de6 Guido Trotter
      arg =  arg_list.pop(0)
280 263b8de6 Guido Trotter
      if arg == "-name":
281 263b8de6 Guido Trotter
        instance = arg_list.pop(0)
282 263b8de6 Guido Trotter
      elif arg == "-m":
283 263b8de6 Guido Trotter
        memory = int(arg_list.pop(0))
284 263b8de6 Guido Trotter
      elif arg == "-smp":
285 263b8de6 Guido Trotter
        vcpus = int(arg_list.pop(0))
286 263b8de6 Guido Trotter
287 263b8de6 Guido Trotter
    if instance is None:
288 263b8de6 Guido Trotter
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
289 263b8de6 Guido Trotter
                                   " instance" % pid)
290 263b8de6 Guido Trotter
291 263b8de6 Guido Trotter
    return (instance, memory, vcpus)
292 263b8de6 Guido Trotter
293 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
294 263b8de6 Guido Trotter
    """Returns the instance pidfile, pid, and liveness.
295 263b8de6 Guido Trotter

296 263b8de6 Guido Trotter
    @type instance_name: string
297 263b8de6 Guido Trotter
    @param instance_name: instance name
298 263b8de6 Guido Trotter
    @rtype: tuple
299 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
300 1f8b3a27 Guido Trotter

301 1f8b3a27 Guido Trotter
    """
302 98ec75d6 Iustin Pop
    pidfile = self._InstancePidFile(instance_name)
303 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
304 263b8de6 Guido Trotter
305 263b8de6 Guido Trotter
    alive = False
306 263b8de6 Guido Trotter
    try:
307 263b8de6 Guido Trotter
      cmd_instance = self._InstancePidInfo(pid)[0]
308 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
309 263b8de6 Guido Trotter
    except errors.HypervisorError:
310 263b8de6 Guido Trotter
      pass
311 1f8b3a27 Guido Trotter
312 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
313 1f8b3a27 Guido Trotter
314 5905901c Iustin Pop
  def _CheckDown(self, instance_name):
315 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
316 5905901c Iustin Pop

317 5905901c Iustin Pop
    """
318 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
319 5905901c Iustin Pop
    if alive:
320 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
321 5905901c Iustin Pop
                                   (instance_name, "already running"))
322 5905901c Iustin Pop
323 0df4d98a Guido Trotter
  @classmethod
324 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
325 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
326 c4fbefc8 Guido Trotter

327 c4fbefc8 Guido Trotter
    """
328 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
329 c4fbefc8 Guido Trotter
330 0df4d98a Guido Trotter
  @classmethod
331 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
332 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
333 c4fbefc8 Guido Trotter

334 c4fbefc8 Guido Trotter
    """
335 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
336 c4fbefc8 Guido Trotter
337 86d6bc2a Guido Trotter
  @staticmethod
338 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
339 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
340 86d6bc2a Guido Trotter

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

343 86d6bc2a Guido Trotter
    """
344 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
345 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
346 86d6bc2a Guido Trotter
    else:
347 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
348 86d6bc2a Guido Trotter
349 0df4d98a Guido Trotter
  @classmethod
350 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
351 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
352 38e250ba Guido Trotter

353 38e250ba Guido Trotter
    """
354 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
355 38e250ba Guido Trotter
356 7e66c35b Guido Trotter
  @classmethod
357 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
358 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
359 547a63b7 Balazs Lecz

360 547a63b7 Balazs Lecz
    """
361 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
362 547a63b7 Balazs Lecz
363 547a63b7 Balazs Lecz
  @classmethod
364 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICDir(cls, instance_name):
365 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the directory holding the tap device files for a
366 5d9bfd87 Apollon Oikonomopoulos
    given instance.
367 5d9bfd87 Apollon Oikonomopoulos

368 5d9bfd87 Apollon Oikonomopoulos
    """
369 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._NICS_DIR, instance_name)
370 5d9bfd87 Apollon Oikonomopoulos
371 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
372 5d9bfd87 Apollon Oikonomopoulos
  def _InstanceNICFile(cls, instance_name, seq):
373 5d9bfd87 Apollon Oikonomopoulos
    """Returns the name of the file containing the tap device for a given NIC
374 5d9bfd87 Apollon Oikonomopoulos

375 5d9bfd87 Apollon Oikonomopoulos
    """
376 5d9bfd87 Apollon Oikonomopoulos
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
377 5d9bfd87 Apollon Oikonomopoulos
378 5d9bfd87 Apollon Oikonomopoulos
  @classmethod
379 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
380 7548396c Guido Trotter
    """Try to read a uid file
381 7548396c Guido Trotter

382 7548396c Guido Trotter
    """
383 7548396c Guido Trotter
    if os.path.exists(uid_file):
384 7548396c Guido Trotter
      try:
385 682f7601 Guido Trotter
        uid = int(utils.ReadOneLineFile(uid_file))
386 aa0b600b Guido Trotter
        return uid
387 7548396c Guido Trotter
      except EnvironmentError:
388 7548396c Guido Trotter
        logging.warning("Can't read uid file", exc_info=True)
389 7548396c Guido Trotter
      except (TypeError, ValueError):
390 7548396c Guido Trotter
        logging.warning("Can't parse uid file contents", exc_info=True)
391 aa0b600b Guido Trotter
    return None
392 7548396c Guido Trotter
393 7548396c Guido Trotter
  @classmethod
394 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
395 547a63b7 Balazs Lecz
    """Removes an instance's rutime sockets/files/dirs.
396 7e66c35b Guido Trotter

397 7e66c35b Guido Trotter
    """
398 7e66c35b Guido Trotter
    utils.RemoveFile(pidfile)
399 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
400 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceSerial(instance_name))
401 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
402 7548396c Guido Trotter
    uid_file = cls._InstanceUidFile(instance_name)
403 7548396c Guido Trotter
    uid = cls._TryReadUidFile(uid_file)
404 7548396c Guido Trotter
    utils.RemoveFile(uid_file)
405 7548396c Guido Trotter
    if uid is not None:
406 7548396c Guido Trotter
      uidpool.ReleaseUid(uid)
407 7be85163 Guido Trotter
    try:
408 7be85163 Guido Trotter
      shutil.rmtree(cls._InstanceNICDir(instance_name))
409 7be85163 Guido Trotter
    except OSError, err:
410 7be85163 Guido Trotter
      if err.errno != errno.ENOENT:
411 7be85163 Guido Trotter
        raise
412 547a63b7 Balazs Lecz
    try:
413 547a63b7 Balazs Lecz
      chroot_dir = cls._InstanceChrootDir(instance_name)
414 547a63b7 Balazs Lecz
      utils.RemoveDir(chroot_dir)
415 547a63b7 Balazs Lecz
    except OSError, err:
416 547a63b7 Balazs Lecz
      if err.errno == errno.ENOTEMPTY:
417 547a63b7 Balazs Lecz
        # The chroot directory is expected to be empty, but it isn't.
418 547a63b7 Balazs Lecz
        new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
419 547a63b7 Balazs Lecz
                                          prefix="%s-%s-" %
420 547a63b7 Balazs Lecz
                                          (instance_name,
421 547a63b7 Balazs Lecz
                                           utils.TimestampForFilename()))
422 547a63b7 Balazs Lecz
        logging.warning("The chroot directory of instance %s can not be"
423 547a63b7 Balazs Lecz
                        " removed as it is not empty. Moving it to the"
424 547a63b7 Balazs Lecz
                        " quarantine instead. Please investigate the"
425 547a63b7 Balazs Lecz
                        " contents (%s) and clean up manually",
426 547a63b7 Balazs Lecz
                        instance_name, new_chroot_dir)
427 547a63b7 Balazs Lecz
        utils.RenameFile(chroot_dir, new_chroot_dir)
428 547a63b7 Balazs Lecz
      else:
429 547a63b7 Balazs Lecz
        raise
430 7e66c35b Guido Trotter
431 748e4b5a Michael Hanselmann
  @staticmethod
432 5d9bfd87 Apollon Oikonomopoulos
  def _ConfigureNIC(instance, seq, nic, tap):
433 5d9bfd87 Apollon Oikonomopoulos
    """Run the network configuration script for a specified NIC
434 eb58f9b1 Guido Trotter

435 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
436 eb58f9b1 Guido Trotter
    @type instance: instance object
437 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
438 eb58f9b1 Guido Trotter
    @type seq: int
439 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
440 eb58f9b1 Guido Trotter
    @type nic: nic object
441 5d9bfd87 Apollon Oikonomopoulos
    @param tap: the host's tap interface this NIC corresponds to
442 5d9bfd87 Apollon Oikonomopoulos
    @type tap: str
443 eb58f9b1 Guido Trotter

444 eb58f9b1 Guido Trotter
    """
445 748e4b5a Michael Hanselmann
446 5d9bfd87 Apollon Oikonomopoulos
    if instance.tags:
447 5d9bfd87 Apollon Oikonomopoulos
      tags = " ".join(instance.tags)
448 5d9bfd87 Apollon Oikonomopoulos
    else:
449 5d9bfd87 Apollon Oikonomopoulos
      tags = ""
450 5d9bfd87 Apollon Oikonomopoulos
451 5d9bfd87 Apollon Oikonomopoulos
    env = {
452 5d9bfd87 Apollon Oikonomopoulos
      "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
453 5d9bfd87 Apollon Oikonomopoulos
      "INSTANCE": instance.name,
454 5d9bfd87 Apollon Oikonomopoulos
      "MAC": nic.mac,
455 5d9bfd87 Apollon Oikonomopoulos
      "MODE": nic.nicparams[constants.NIC_MODE],
456 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE": tap,
457 5d9bfd87 Apollon Oikonomopoulos
      "INTERFACE_INDEX": str(seq),
458 5d9bfd87 Apollon Oikonomopoulos
      "TAGS": tags,
459 5d9bfd87 Apollon Oikonomopoulos
    }
460 5d9bfd87 Apollon Oikonomopoulos
461 5d9bfd87 Apollon Oikonomopoulos
    if nic.ip:
462 5d9bfd87 Apollon Oikonomopoulos
      env["IP"] = nic.ip
463 5d9bfd87 Apollon Oikonomopoulos
464 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_LINK]:
465 5d9bfd87 Apollon Oikonomopoulos
      env["LINK"] = nic.nicparams[constants.NIC_LINK]
466 5d9bfd87 Apollon Oikonomopoulos
467 5d9bfd87 Apollon Oikonomopoulos
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
468 5d9bfd87 Apollon Oikonomopoulos
      env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
469 5d9bfd87 Apollon Oikonomopoulos
470 5d9bfd87 Apollon Oikonomopoulos
    result = utils.RunCmd([constants.KVM_IFUP, tap], env=env)
471 5d9bfd87 Apollon Oikonomopoulos
    if result.failed:
472 5d9bfd87 Apollon Oikonomopoulos
      raise errors.HypervisorError("Failed to configure interface %s: %s."
473 5d9bfd87 Apollon Oikonomopoulos
                                   " Network configuration script output: %s" %
474 5d9bfd87 Apollon Oikonomopoulos
                                   (tap, result.fail_reason, result.output))
475 eb58f9b1 Guido Trotter
476 eb58f9b1 Guido Trotter
  def ListInstances(self):
477 eb58f9b1 Guido Trotter
    """Get the list of running instances.
478 eb58f9b1 Guido Trotter

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

482 eb58f9b1 Guido Trotter
    """
483 eb58f9b1 Guido Trotter
    result = []
484 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
485 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
486 eb58f9b1 Guido Trotter
        result.append(name)
487 eb58f9b1 Guido Trotter
    return result
488 eb58f9b1 Guido Trotter
489 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
490 eb58f9b1 Guido Trotter
    """Get instance properties.
491 eb58f9b1 Guido Trotter

492 4fbb3c60 Guido Trotter
    @type instance_name: string
493 c41eea6e Iustin Pop
    @param instance_name: the instance name
494 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
495 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
496 eb58f9b1 Guido Trotter

497 eb58f9b1 Guido Trotter
    """
498 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
499 1f8b3a27 Guido Trotter
    if not alive:
500 eb58f9b1 Guido Trotter
      return None
501 eb58f9b1 Guido Trotter
502 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
503 eb58f9b1 Guido Trotter
    stat = "---b-"
504 eb58f9b1 Guido Trotter
    times = "0"
505 eb58f9b1 Guido Trotter
506 eb58f9b1 Guido Trotter
    return (instance_name, pid, memory, vcpus, stat, times)
507 eb58f9b1 Guido Trotter
508 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
509 eb58f9b1 Guido Trotter
    """Get properties of all instances.
510 eb58f9b1 Guido Trotter

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

513 eb58f9b1 Guido Trotter
    """
514 eb58f9b1 Guido Trotter
    data = []
515 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
516 263b8de6 Guido Trotter
      try:
517 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
518 263b8de6 Guido Trotter
      except errors.HypervisorError:
519 263b8de6 Guido Trotter
        continue
520 263b8de6 Guido Trotter
      if info:
521 263b8de6 Guido Trotter
        data.append(info)
522 eb58f9b1 Guido Trotter
    return data
523 eb58f9b1 Guido Trotter
524 07813a9e Iustin Pop
  def _GenerateKVMRuntime(self, instance, block_devices):
525 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
526 eb58f9b1 Guido Trotter

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

733 38e250ba Guido Trotter
    """
734 38e250ba Guido Trotter
    try:
735 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
736 38e250ba Guido Trotter
                      data=data)
737 90c024f6 Guido Trotter
    except EnvironmentError, err:
738 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
739 38e250ba Guido Trotter
740 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
741 38e250ba Guido Trotter
    """Read an instance's KVM runtime
742 38e250ba Guido Trotter

743 38e250ba Guido Trotter
    """
744 38e250ba Guido Trotter
    try:
745 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
746 90c024f6 Guido Trotter
    except EnvironmentError, err:
747 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
748 38e250ba Guido Trotter
    return file_content
749 38e250ba Guido Trotter
750 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
751 38e250ba Guido Trotter
    """Save an instance's KVM runtime
752 38e250ba Guido Trotter

753 38e250ba Guido Trotter
    """
754 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
755 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
756 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
757 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
758 38e250ba Guido Trotter
759 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
760 38e250ba Guido Trotter
    """Load an instance's KVM runtime
761 38e250ba Guido Trotter

762 38e250ba Guido Trotter
    """
763 30e42c4e Guido Trotter
    if not serialized_runtime:
764 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
765 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
766 c2672466 Guido Trotter
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
767 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
768 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
769 38e250ba Guido Trotter
770 5d9bfd87 Apollon Oikonomopoulos
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
771 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
772 76431533 Guido Trotter

773 76431533 Guido Trotter
    @type name: string
774 76431533 Guido Trotter
    @param name: instance name
775 76431533 Guido Trotter
    @type kvm_cmd: list of strings
776 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
777 5d9bfd87 Apollon Oikonomopoulos
    @type tap_fds: list of int
778 5d9bfd87 Apollon Oikonomopoulos
    @param tap_fds: fds of tap devices opened by Ganeti
779 76431533 Guido Trotter

780 76431533 Guido Trotter
    """
781 5d9bfd87 Apollon Oikonomopoulos
    try:
782 5d9bfd87 Apollon Oikonomopoulos
      result = utils.RunCmd(kvm_cmd, noclose_fds=tap_fds)
783 5d9bfd87 Apollon Oikonomopoulos
    finally:
784 5d9bfd87 Apollon Oikonomopoulos
      for fd in tap_fds:
785 5d9bfd87 Apollon Oikonomopoulos
        utils_wrapper.CloseFdNoError(fd)
786 5d9bfd87 Apollon Oikonomopoulos
787 76431533 Guido Trotter
    if result.failed:
788 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
789 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
790 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
791 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
792 76431533 Guido Trotter
793 30e42c4e Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
794 ee5f20b0 Guido Trotter
    """Execute a KVM cmd, after completing it with some last minute data
795 ee5f20b0 Guido Trotter

796 30e42c4e Guido Trotter
    @type incoming: tuple of strings
797 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
798 30e42c4e Guido Trotter

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

934 ee5f20b0 Guido Trotter
    """
935 5905901c Iustin Pop
    self._CheckDown(instance.name)
936 07813a9e Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices)
937 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
938 ee5f20b0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
939 ee5f20b0 Guido Trotter
940 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
941 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
942 6567aff3 Guido Trotter

943 6567aff3 Guido Trotter
    """
944 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
945 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
946 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
947 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
948 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
949 6567aff3 Guido Trotter
    if result.failed:
950 6567aff3 Guido Trotter
      msg = ("Failed to send command '%s' to instance %s."
951 6567aff3 Guido Trotter
             " output: %s, error: %s, fail_reason: %s" %
952 9798fcae Guido Trotter
             (command, instance_name,
953 9798fcae Guido Trotter
              result.stdout, result.stderr, result.fail_reason))
954 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
955 6567aff3 Guido Trotter
956 6567aff3 Guido Trotter
    return result
957 6567aff3 Guido Trotter
958 b52d85c1 Guido Trotter
  @classmethod
959 b52d85c1 Guido Trotter
  def _GetKVMVersion(cls):
960 b52d85c1 Guido Trotter
    """Return the installed KVM version
961 b52d85c1 Guido Trotter

962 b52d85c1 Guido Trotter
    @return: (version, v_maj, v_min, v_rev), or None
963 b52d85c1 Guido Trotter

964 b52d85c1 Guido Trotter
    """
965 b52d85c1 Guido Trotter
    result = utils.RunCmd([constants.KVM_PATH, "--help"])
966 b52d85c1 Guido Trotter
    if result.failed:
967 b52d85c1 Guido Trotter
      return None
968 b52d85c1 Guido Trotter
    match = cls._VERSION_RE.search(result.output.splitlines()[0])
969 b52d85c1 Guido Trotter
    if not match:
970 b52d85c1 Guido Trotter
      return None
971 3f2eba25 Miguel Di Ciurcio Filho
972 3f2eba25 Miguel Di Ciurcio Filho
    return (match.group(0), int(match.group(1)), int(match.group(2)),
973 3f2eba25 Miguel Di Ciurcio Filho
            int(match.group(3)))
974 b52d85c1 Guido Trotter
975 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
976 eb58f9b1 Guido Trotter
    """Stop an instance.
977 eb58f9b1 Guido Trotter

978 eb58f9b1 Guido Trotter
    """
979 bbcf7ad0 Iustin Pop
    if name is not None and not force:
980 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
981 bbcf7ad0 Iustin Pop
    if name is None:
982 bbcf7ad0 Iustin Pop
      name = instance.name
983 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
984 bbcf7ad0 Iustin Pop
    else:
985 bbcf7ad0 Iustin Pop
      acpi = False
986 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
987 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
988 bbcf7ad0 Iustin Pop
      if force or not acpi:
989 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
990 eb58f9b1 Guido Trotter
      else:
991 bbcf7ad0 Iustin Pop
        self._CallMonitorCommand(name, 'system_powerdown')
992 eb58f9b1 Guido Trotter
993 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
994 8904b35c Guido Trotter
    """Cleanup after a stopped instance
995 8904b35c Guido Trotter

996 8904b35c Guido Trotter
    """
997 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
998 8904b35c Guido Trotter
    if pid > 0 and alive:
999 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
1000 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1001 eb58f9b1 Guido Trotter
1002 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
1003 eb58f9b1 Guido Trotter
    """Reboot an instance.
1004 eb58f9b1 Guido Trotter

1005 eb58f9b1 Guido Trotter
    """
1006 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
1007 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
1008 eb58f9b1 Guido Trotter
    # to shutdown and restart.
1009 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
1010 1f8b3a27 Guido Trotter
    if not alive:
1011 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
1012 78411c60 Iustin Pop
                                   " not running" % instance.name)
1013 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
1014 f02881e0 Guido Trotter
    # ...first load it...
1015 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
1016 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
1017 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
1018 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
1019 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
1020 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
1021 f02881e0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
1022 eb58f9b1 Guido Trotter
1023 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
1024 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
1025 30e42c4e Guido Trotter

1026 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1027 30e42c4e Guido Trotter
    @param instance: instance to be migrated
1028 30e42c4e Guido Trotter
    @rtype: string
1029 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
1030 30e42c4e Guido Trotter

1031 30e42c4e Guido Trotter
    """
1032 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
1033 30e42c4e Guido Trotter
1034 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
1035 30e42c4e Guido Trotter
    """Prepare to accept an instance.
1036 30e42c4e Guido Trotter

1037 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1038 30e42c4e Guido Trotter
    @param instance: instance to be accepted
1039 30e42c4e Guido Trotter
    @type info: string
1040 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
1041 30e42c4e Guido Trotter
    @type target: string
1042 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
1043 30e42c4e Guido Trotter

1044 30e42c4e Guido Trotter
    """
1045 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1046 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
1047 30e42c4e Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
1048 30e42c4e Guido Trotter
1049 30e42c4e Guido Trotter
  def FinalizeMigration(self, instance, info, success):
1050 30e42c4e Guido Trotter
    """Finalize an instance migration.
1051 30e42c4e Guido Trotter

1052 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
1053 30e42c4e Guido Trotter

1054 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
1055 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
1056 30e42c4e Guido Trotter

1057 30e42c4e Guido Trotter
    """
1058 30e42c4e Guido Trotter
    if success:
1059 5d9bfd87 Apollon Oikonomopoulos
      kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
1060 5d9bfd87 Apollon Oikonomopoulos
      kvm_nics = kvm_runtime[1]
1061 5d9bfd87 Apollon Oikonomopoulos
1062 5d9bfd87 Apollon Oikonomopoulos
      for nic_seq, nic in enumerate(kvm_nics):
1063 034c116d Apollon Oikonomopoulos
        if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1064 034c116d Apollon Oikonomopoulos
          # Bridged interfaces have already been configured
1065 034c116d Apollon Oikonomopoulos
          continue
1066 5d9bfd87 Apollon Oikonomopoulos
        try:
1067 5d9bfd87 Apollon Oikonomopoulos
          tap = utils.ReadFile(self._InstanceNICFile(instance.name, nic_seq))
1068 5d9bfd87 Apollon Oikonomopoulos
        except EnvironmentError, err:
1069 5d9bfd87 Apollon Oikonomopoulos
          logging.warning("Failed to find host interface for %s NIC #%d: %s",
1070 5d9bfd87 Apollon Oikonomopoulos
                          instance.name, nic_seq, str(err))
1071 5d9bfd87 Apollon Oikonomopoulos
          continue
1072 5d9bfd87 Apollon Oikonomopoulos
        try:
1073 5d9bfd87 Apollon Oikonomopoulos
          self._ConfigureNIC(instance, nic_seq, nic, tap)
1074 5d9bfd87 Apollon Oikonomopoulos
        except errors.HypervisorError, err:
1075 5d9bfd87 Apollon Oikonomopoulos
          logging.warning(str(err))
1076 5d9bfd87 Apollon Oikonomopoulos
1077 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
1078 30e42c4e Guido Trotter
    else:
1079 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
1080 30e42c4e Guido Trotter
1081 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
1082 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
1083 30e42c4e Guido Trotter

1084 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
1085 30e42c4e Guido Trotter
    currently running.
1086 30e42c4e Guido Trotter

1087 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
1088 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
1089 30e42c4e Guido Trotter
    @type target: string
1090 30e42c4e Guido Trotter
    @param target: ip address of the target node
1091 30e42c4e Guido Trotter
    @type live: boolean
1092 30e42c4e Guido Trotter
    @param live: perform a live migration
1093 30e42c4e Guido Trotter

1094 30e42c4e Guido Trotter
    """
1095 58d38b02 Iustin Pop
    instance_name = instance.name
1096 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
1097 30e42c4e Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
1098 30e42c4e Guido Trotter
    if not alive:
1099 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
1100 30e42c4e Guido Trotter
1101 30e42c4e Guido Trotter
    if not live:
1102 30e42c4e Guido Trotter
      self._CallMonitorCommand(instance_name, 'stop')
1103 30e42c4e Guido Trotter
1104 e43d4f9f Apollon Oikonomopoulos
    migrate_command = ('migrate_set_speed %dm' %
1105 e43d4f9f Apollon Oikonomopoulos
        instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
1106 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
1107 e43d4f9f Apollon Oikonomopoulos
1108 e43d4f9f Apollon Oikonomopoulos
    migrate_command = ('migrate_set_downtime %dms' %
1109 e43d4f9f Apollon Oikonomopoulos
        instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
1110 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
1111 e43d4f9f Apollon Oikonomopoulos
1112 641ae041 Iustin Pop
    migrate_command = 'migrate -d tcp:%s:%s' % (target, port)
1113 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
1114 30e42c4e Guido Trotter
1115 30e42c4e Guido Trotter
    info_command = 'info migrate'
1116 30e42c4e Guido Trotter
    done = False
1117 c4e388a5 Guido Trotter
    broken_answers = 0
1118 30e42c4e Guido Trotter
    while not done:
1119 30e42c4e Guido Trotter
      result = self._CallMonitorCommand(instance_name, info_command)
1120 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
1121 30e42c4e Guido Trotter
      if not match:
1122 c4e388a5 Guido Trotter
        broken_answers += 1
1123 c4e388a5 Guido Trotter
        if not result.stdout:
1124 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
1125 c4e388a5 Guido Trotter
        else:
1126 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
1127 c4e388a5 Guido Trotter
                          result.stdout)
1128 c4e388a5 Guido Trotter
        time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1129 30e42c4e Guido Trotter
      else:
1130 30e42c4e Guido Trotter
        status = match.group(1)
1131 30e42c4e Guido Trotter
        if status == 'completed':
1132 30e42c4e Guido Trotter
          done = True
1133 30e42c4e Guido Trotter
        elif status == 'active':
1134 c4e388a5 Guido Trotter
          # reset the broken answers count
1135 c4e388a5 Guido Trotter
          broken_answers = 0
1136 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1137 c087266c Guido Trotter
        elif status == 'failed' or status == 'cancelled':
1138 c087266c Guido Trotter
          if not live:
1139 c087266c Guido Trotter
            self._CallMonitorCommand(instance_name, 'cont')
1140 c087266c Guido Trotter
          raise errors.HypervisorError("Migration %s at the kvm level" %
1141 c087266c Guido Trotter
                                       status)
1142 30e42c4e Guido Trotter
        else:
1143 c4e388a5 Guido Trotter
          logging.warning("KVM: unknown migration status '%s'", status)
1144 c4e388a5 Guido Trotter
          broken_answers += 1
1145 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1146 c4e388a5 Guido Trotter
      if broken_answers >= self._MIGRATION_INFO_MAX_BAD_ANSWERS:
1147 c4e388a5 Guido Trotter
        raise errors.HypervisorError("Too many 'info migrate' broken answers")
1148 30e42c4e Guido Trotter
1149 30e42c4e Guido Trotter
    utils.KillProcess(pid)
1150 7b381438 Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1151 30e42c4e Guido Trotter
1152 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
1153 eb58f9b1 Guido Trotter
    """Return information about the node.
1154 eb58f9b1 Guido Trotter

1155 572e52bf Iustin Pop
    This is just a wrapper over the base GetLinuxNodeInfo method.
1156 572e52bf Iustin Pop

1157 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
1158 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
1159 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
1160 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
1161 eb58f9b1 Guido Trotter

1162 eb58f9b1 Guido Trotter
    """
1163 572e52bf Iustin Pop
    return self.GetLinuxNodeInfo()
1164 eb58f9b1 Guido Trotter
1165 637ce7f9 Guido Trotter
  @classmethod
1166 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
1167 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
1168 eb58f9b1 Guido Trotter

1169 eb58f9b1 Guido Trotter
    """
1170 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
1171 55cc0a44 Michael Hanselmann
      cmd = [constants.SOCAT_PATH,
1172 55cc0a44 Michael Hanselmann
             "STDIO,%s" % cls._SocatUnixConsoleParams(),
1173 55cc0a44 Michael Hanselmann
             "UNIX-CONNECT:%s" % cls._InstanceSerial(instance.name)]
1174 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
1175 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_SSH,
1176 55cc0a44 Michael Hanselmann
                                     host=instance.primary_node,
1177 55cc0a44 Michael Hanselmann
                                     user=constants.GANETI_RUNAS,
1178 55cc0a44 Michael Hanselmann
                                     command=cmd)
1179 3be34f57 Guido Trotter
1180 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
1181 55cc0a44 Michael Hanselmann
    if vnc_bind_address and instance.network_port > constants.VNC_BASE_PORT:
1182 55cc0a44 Michael Hanselmann
      display = instance.network_port - constants.VNC_BASE_PORT
1183 55cc0a44 Michael Hanselmann
      return objects.InstanceConsole(instance=instance.name,
1184 55cc0a44 Michael Hanselmann
                                     kind=constants.CONS_VNC,
1185 55cc0a44 Michael Hanselmann
                                     host=vnc_bind_address,
1186 55cc0a44 Michael Hanselmann
                                     port=instance.network_port,
1187 55cc0a44 Michael Hanselmann
                                     display=display)
1188 55cc0a44 Michael Hanselmann
1189 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
1190 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
1191 55cc0a44 Michael Hanselmann
                                   message=("No serial shell for instance %s" %
1192 55cc0a44 Michael Hanselmann
                                            instance.name))
1193 eb58f9b1 Guido Trotter
1194 eb58f9b1 Guido Trotter
  def Verify(self):
1195 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
1196 eb58f9b1 Guido Trotter

1197 eb58f9b1 Guido Trotter
    Check that the binary exists.
1198 eb58f9b1 Guido Trotter

1199 eb58f9b1 Guido Trotter
    """
1200 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
1201 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
1202 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
1203 14aa53cb Guido Trotter
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
1204 14aa53cb Guido Trotter
1205 6b5605e8 Iustin Pop
  @classmethod
1206 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
1207 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
1208 6b5605e8 Iustin Pop

1209 6b5605e8 Iustin Pop
    @type hvparams:  dict
1210 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
1211 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
1212 6b5605e8 Iustin Pop

1213 6b5605e8 Iustin Pop
    """
1214 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
1215 6b5605e8 Iustin Pop
1216 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
1217 df5ab9f0 Guido Trotter
    if kernel_path:
1218 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
1219 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
1220 205ab586 Iustin Pop
                                     " if a kernel is defined")
1221 6b5605e8 Iustin Pop
1222 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
1223 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
1224 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
1225 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
1226 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
1227 66d5dbef Guido Trotter
1228 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
1229 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
1230 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
1231 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
1232 835528af Iustin Pop
                                   " ISO path")
1233 f5118ade Iustin Pop
1234 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
1235 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
1236 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
1237 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
1238 d19d94db Guido Trotter
                                     " must be specified")
1239 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
1240 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
1241 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
1242 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
1243 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
1244 d19d94db Guido Trotter
1245 d19d94db Guido Trotter
  @classmethod
1246 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
1247 d19d94db Guido Trotter
    """Check the given parameters for validity.
1248 d19d94db Guido Trotter

1249 d19d94db Guido Trotter
    @type hvparams:  dict
1250 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
1251 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
1252 d19d94db Guido Trotter

1253 d19d94db Guido Trotter
    """
1254 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
1255 d19d94db Guido Trotter
1256 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
1257 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
1258 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
1259 d19d94db Guido Trotter
      try:
1260 1feb39ec Guido Trotter
        pwd.getpwnam(username)
1261 d19d94db Guido Trotter
      except KeyError:
1262 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
1263 d19d94db Guido Trotter
                                     % username)
1264 d19d94db Guido Trotter
1265 f5118ade Iustin Pop
  @classmethod
1266 f5118ade Iustin Pop
  def PowercycleNode(cls):
1267 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
1268 f5118ade Iustin Pop

1269 f5118ade Iustin Pop
    """
1270 f5118ade Iustin Pop
    cls.LinuxPowercycle()