Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 4b784cf8

History | View | Annotate | Download (39 kB)

1 eb58f9b1 Guido Trotter
#
2 eb58f9b1 Guido Trotter
#
3 eb58f9b1 Guido Trotter
4 783a6c0b Iustin Pop
# Copyright (C) 2008, 2009, 2010 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 eb58f9b1 Guido Trotter
from cStringIO import StringIO
35 eb58f9b1 Guido Trotter
36 eb58f9b1 Guido Trotter
from ganeti import utils
37 eb58f9b1 Guido Trotter
from ganeti import constants
38 eb58f9b1 Guido Trotter
from ganeti import errors
39 38e250ba Guido Trotter
from ganeti import serializer
40 38e250ba Guido Trotter
from ganeti import objects
41 76431533 Guido Trotter
from ganeti import uidpool
42 76431533 Guido Trotter
from ganeti import ssconf
43 eb58f9b1 Guido Trotter
from ganeti.hypervisor import hv_base
44 a744b676 Manuel Franceschini
from ganeti import netutils
45 eb58f9b1 Guido Trotter
46 eb58f9b1 Guido Trotter
47 748e4b5a Michael Hanselmann
_KVM_NETWORK_SCRIPT = constants.SYSCONFDIR + "/ganeti/kvm-vif-bridge"
48 748e4b5a Michael Hanselmann
49 748e4b5a Michael Hanselmann
50 748e4b5a Michael Hanselmann
def _WriteNetScript(instance, nic, index):
51 748e4b5a Michael Hanselmann
  """Write a script to connect a net interface to the proper bridge.
52 748e4b5a Michael Hanselmann

53 748e4b5a Michael Hanselmann
  This can be used by any qemu-type hypervisor.
54 748e4b5a Michael Hanselmann

55 748e4b5a Michael Hanselmann
  @type instance: L{objects.Instance}
56 748e4b5a Michael Hanselmann
  @param instance: Instance object
57 748e4b5a Michael Hanselmann
  @type nic: L{objects.NIC}
58 748e4b5a Michael Hanselmann
  @param nic: NIC object
59 748e4b5a Michael Hanselmann
  @type index: int
60 748e4b5a Michael Hanselmann
  @param index: NIC index
61 748e4b5a Michael Hanselmann
  @return: Script
62 748e4b5a Michael Hanselmann
  @rtype: string
63 748e4b5a Michael Hanselmann

64 748e4b5a Michael Hanselmann
  """
65 748e4b5a Michael Hanselmann
  if instance.tags:
66 748e4b5a Michael Hanselmann
    tags = " ".join(instance.tags)
67 748e4b5a Michael Hanselmann
  else:
68 748e4b5a Michael Hanselmann
    tags = ""
69 748e4b5a Michael Hanselmann
70 748e4b5a Michael Hanselmann
  buf = StringIO()
71 748e4b5a Michael Hanselmann
  sw = utils.ShellWriter(buf)
72 748e4b5a Michael Hanselmann
  sw.Write("#!/bin/sh")
73 748e4b5a Michael Hanselmann
  sw.Write("# this is autogenerated by Ganeti, please do not edit")
74 748e4b5a Michael Hanselmann
  sw.Write("export PATH=$PATH:/sbin:/usr/sbin")
75 748e4b5a Michael Hanselmann
  sw.Write("export INSTANCE=%s", utils.ShellQuote(instance.name))
76 748e4b5a Michael Hanselmann
  sw.Write("export MAC=%s", utils.ShellQuote(nic.mac))
77 748e4b5a Michael Hanselmann
  sw.Write("export MODE=%s",
78 748e4b5a Michael Hanselmann
           utils.ShellQuote(nic.nicparams[constants.NIC_MODE]))
79 748e4b5a Michael Hanselmann
  sw.Write("export INTERFACE=\"$1\"")
80 748e4b5a Michael Hanselmann
  sw.Write("export TAGS=%s", utils.ShellQuote(tags))
81 748e4b5a Michael Hanselmann
82 748e4b5a Michael Hanselmann
  if nic.ip:
83 748e4b5a Michael Hanselmann
    sw.Write("export IP=%s", utils.ShellQuote(nic.ip))
84 748e4b5a Michael Hanselmann
85 748e4b5a Michael Hanselmann
  if nic.nicparams[constants.NIC_LINK]:
86 748e4b5a Michael Hanselmann
    sw.Write("export LINK=%s",
87 748e4b5a Michael Hanselmann
             utils.ShellQuote(nic.nicparams[constants.NIC_LINK]))
88 748e4b5a Michael Hanselmann
89 748e4b5a Michael Hanselmann
  if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
90 748e4b5a Michael Hanselmann
    sw.Write("export BRIDGE=%s",
91 748e4b5a Michael Hanselmann
             utils.ShellQuote(nic.nicparams[constants.NIC_LINK]))
92 748e4b5a Michael Hanselmann
93 748e4b5a Michael Hanselmann
  # TODO: make this configurable at ./configure time
94 748e4b5a Michael Hanselmann
  sw.Write("if [ -x %s ]; then", utils.ShellQuote(_KVM_NETWORK_SCRIPT))
95 748e4b5a Michael Hanselmann
  sw.IncIndent()
96 748e4b5a Michael Hanselmann
  try:
97 748e4b5a Michael Hanselmann
    sw.Write("# Execute the user-specific vif file")
98 748e4b5a Michael Hanselmann
    sw.Write(_KVM_NETWORK_SCRIPT)
99 748e4b5a Michael Hanselmann
  finally:
100 748e4b5a Michael Hanselmann
    sw.DecIndent()
101 748e4b5a Michael Hanselmann
  sw.Write("else")
102 748e4b5a Michael Hanselmann
  sw.IncIndent()
103 748e4b5a Michael Hanselmann
  try:
104 748e4b5a Michael Hanselmann
    sw.Write("ifconfig $INTERFACE 0.0.0.0 up")
105 748e4b5a Michael Hanselmann
106 748e4b5a Michael Hanselmann
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
107 748e4b5a Michael Hanselmann
      sw.Write("# Connect the interface to the bridge")
108 748e4b5a Michael Hanselmann
      sw.Write("brctl addif $BRIDGE $INTERFACE")
109 748e4b5a Michael Hanselmann
110 748e4b5a Michael Hanselmann
    elif nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_ROUTED:
111 748e4b5a Michael Hanselmann
      if not nic.ip:
112 748e4b5a Michael Hanselmann
        raise errors.HypervisorError("nic/%d is routed, but has no IP"
113 748e4b5a Michael Hanselmann
                                     " address" % index)
114 748e4b5a Michael Hanselmann
115 748e4b5a Michael Hanselmann
      sw.Write("# Route traffic targeted at the IP to the interface")
116 748e4b5a Michael Hanselmann
      if nic.nicparams[constants.NIC_LINK]:
117 748e4b5a Michael Hanselmann
        sw.Write("while ip rule del dev $INTERFACE; do :; done")
118 748e4b5a Michael Hanselmann
        sw.Write("ip rule add dev $INTERFACE table $LINK")
119 748e4b5a Michael Hanselmann
        sw.Write("ip route replace $IP table $LINK proto static"
120 748e4b5a Michael Hanselmann
                 " dev $INTERFACE")
121 748e4b5a Michael Hanselmann
      else:
122 748e4b5a Michael Hanselmann
        sw.Write("ip route replace $IP proto static dev $INTERFACE")
123 748e4b5a Michael Hanselmann
124 748e4b5a Michael Hanselmann
      interface_v4_conf = "/proc/sys/net/ipv4/conf/$INTERFACE"
125 748e4b5a Michael Hanselmann
      sw.Write(" if [ -d %s ]; then", interface_v4_conf)
126 748e4b5a Michael Hanselmann
      sw.IncIndent()
127 748e4b5a Michael Hanselmann
      try:
128 748e4b5a Michael Hanselmann
        sw.Write("echo 1 > %s/proxy_arp", interface_v4_conf)
129 748e4b5a Michael Hanselmann
        sw.Write("echo 1 > %s/forwarding", interface_v4_conf)
130 748e4b5a Michael Hanselmann
      finally:
131 748e4b5a Michael Hanselmann
        sw.DecIndent()
132 748e4b5a Michael Hanselmann
      sw.Write("fi")
133 748e4b5a Michael Hanselmann
134 748e4b5a Michael Hanselmann
      interface_v6_conf = "/proc/sys/net/ipv6/conf/$INTERFACE"
135 748e4b5a Michael Hanselmann
      sw.Write("if [ -d %s ]; then", interface_v6_conf)
136 748e4b5a Michael Hanselmann
      sw.IncIndent()
137 748e4b5a Michael Hanselmann
      try:
138 748e4b5a Michael Hanselmann
        sw.Write("echo 1 > %s/proxy_ndp", interface_v6_conf)
139 748e4b5a Michael Hanselmann
        sw.Write("echo 1 > %s/forwarding", interface_v6_conf)
140 748e4b5a Michael Hanselmann
      finally:
141 748e4b5a Michael Hanselmann
        sw.DecIndent()
142 748e4b5a Michael Hanselmann
      sw.Write("fi")
143 748e4b5a Michael Hanselmann
  finally:
144 748e4b5a Michael Hanselmann
    sw.DecIndent()
145 748e4b5a Michael Hanselmann
  sw.Write("fi")
146 748e4b5a Michael Hanselmann
147 748e4b5a Michael Hanselmann
  return buf.getvalue()
148 748e4b5a Michael Hanselmann
149 748e4b5a Michael Hanselmann
150 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
151 c4469f75 Guido Trotter
  """KVM hypervisor interface"""
152 d271c6fd Iustin Pop
  CAN_MIGRATE = True
153 eb58f9b1 Guido Trotter
154 eb58f9b1 Guido Trotter
  _ROOT_DIR = constants.RUN_GANETI_DIR + "/kvm-hypervisor"
155 a1d79fc6 Guido Trotter
  _PIDS_DIR = _ROOT_DIR + "/pid" # contains live instances pids
156 7548396c Guido Trotter
  _UIDS_DIR = _ROOT_DIR + "/uid" # contains instances reserved uids
157 a1d79fc6 Guido Trotter
  _CTRL_DIR = _ROOT_DIR + "/ctrl" # contains instances control sockets
158 a1d79fc6 Guido Trotter
  _CONF_DIR = _ROOT_DIR + "/conf" # contains instances startup data
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 547a63b7 Balazs Lecz
  _DIRS = [_ROOT_DIR, _PIDS_DIR, _UIDS_DIR, _CTRL_DIR, _CONF_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 205ab586 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
187 d73ef63f Michael Hanselmann
    constants.HV_BOOT_ORDER:
188 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
189 d73ef63f Michael Hanselmann
    constants.HV_NIC_TYPE:
190 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
191 d73ef63f Michael Hanselmann
    constants.HV_DISK_TYPE:
192 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
193 d73ef63f Michael Hanselmann
    constants.HV_USB_MOUSE:
194 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
195 78411c60 Iustin Pop
    constants.HV_MIGRATION_PORT: hv_base.NET_PORT_CHECK,
196 e43d4f9f Apollon Oikonomopoulos
    constants.HV_MIGRATION_BANDWIDTH: hv_base.NO_CHECK,
197 e43d4f9f Apollon Oikonomopoulos
    constants.HV_MIGRATION_DOWNTIME: hv_base.NO_CHECK,
198 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
199 6b970cef Jun Futagawa
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
200 19572932 Iustin Pop
    constants.HV_DISK_CACHE:
201 19572932 Iustin Pop
      hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
202 d19d94db Guido Trotter
    constants.HV_SECURITY_MODEL:
203 d19d94db Guido Trotter
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_SM_TYPES),
204 d19d94db Guido Trotter
    constants.HV_SECURITY_DOMAIN: hv_base.NO_CHECK,
205 7ba594c0 Guido Trotter
    constants.HV_KVM_FLAG:
206 7ba594c0 Guido Trotter
      hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES),
207 fbe27e2b Guido Trotter
    constants.HV_VHOST_NET: hv_base.NO_CHECK,
208 547a63b7 Balazs Lecz
    constants.HV_KVM_USE_CHROOT: hv_base.NO_CHECK,
209 4f958b0b Miguel Di Ciurcio Filho
    constants.HV_MEM_PATH: hv_base.OPT_DIR_CHECK,
210 205ab586 Iustin Pop
    }
211 6b5605e8 Iustin Pop
212 30e42c4e Guido Trotter
  _MIGRATION_STATUS_RE = re.compile('Migration\s+status:\s+(\w+)',
213 30e42c4e Guido Trotter
                                    re.M | re.I)
214 c4e388a5 Guido Trotter
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
215 c4e388a5 Guido Trotter
  _MIGRATION_INFO_RETRY_DELAY = 2
216 30e42c4e Guido Trotter
217 b52d85c1 Guido Trotter
  _VERSION_RE = re.compile(r"\b(\d+)\.(\d+)\.(\d+)\b")
218 b52d85c1 Guido Trotter
219 64bfbc08 Guido Trotter
  ANCILLARY_FILES = [
220 64bfbc08 Guido Trotter
    _KVM_NETWORK_SCRIPT,
221 64bfbc08 Guido Trotter
    ]
222 64bfbc08 Guido Trotter
223 eb58f9b1 Guido Trotter
  def __init__(self):
224 eb58f9b1 Guido Trotter
    hv_base.BaseHypervisor.__init__(self)
225 eb58f9b1 Guido Trotter
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
226 eb58f9b1 Guido Trotter
    # in a tmpfs filesystem or has been otherwise wiped out.
227 29921401 Iustin Pop
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
228 9afb67fe Guido Trotter
    utils.EnsureDirs(dirs)
229 eb58f9b1 Guido Trotter
230 30786fc9 Iustin Pop
  @classmethod
231 30786fc9 Iustin Pop
  def _InstancePidFile(cls, instance_name):
232 98ec75d6 Iustin Pop
    """Returns the instance pidfile.
233 98ec75d6 Iustin Pop

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

241 7548396c Guido Trotter
    """
242 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
243 7548396c Guido Trotter
244 7548396c Guido Trotter
  @classmethod
245 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
246 263b8de6 Guido Trotter
    """Check pid file for instance information.
247 263b8de6 Guido Trotter

248 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
249 263b8de6 Guido Trotter
    information from its command line.
250 263b8de6 Guido Trotter

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

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

292 263b8de6 Guido Trotter
    @type instance_name: string
293 263b8de6 Guido Trotter
    @param instance_name: instance name
294 263b8de6 Guido Trotter
    @rtype: tuple
295 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
296 1f8b3a27 Guido Trotter

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

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

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

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

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

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

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

356 547a63b7 Balazs Lecz
    """
357 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
358 547a63b7 Balazs Lecz
359 547a63b7 Balazs Lecz
  @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 547a63b7 Balazs Lecz
    try:
389 547a63b7 Balazs Lecz
      chroot_dir = cls._InstanceChrootDir(instance_name)
390 547a63b7 Balazs Lecz
      utils.RemoveDir(chroot_dir)
391 547a63b7 Balazs Lecz
    except OSError, err:
392 547a63b7 Balazs Lecz
      if err.errno == errno.ENOTEMPTY:
393 547a63b7 Balazs Lecz
        # The chroot directory is expected to be empty, but it isn't.
394 547a63b7 Balazs Lecz
        new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
395 547a63b7 Balazs Lecz
                                          prefix="%s-%s-" %
396 547a63b7 Balazs Lecz
                                          (instance_name,
397 547a63b7 Balazs Lecz
                                           utils.TimestampForFilename()))
398 547a63b7 Balazs Lecz
        logging.warning("The chroot directory of instance %s can not be"
399 547a63b7 Balazs Lecz
                        " removed as it is not empty. Moving it to the"
400 547a63b7 Balazs Lecz
                        " quarantine instead. Please investigate the"
401 547a63b7 Balazs Lecz
                        " contents (%s) and clean up manually",
402 547a63b7 Balazs Lecz
                        instance_name, new_chroot_dir)
403 547a63b7 Balazs Lecz
        utils.RenameFile(chroot_dir, new_chroot_dir)
404 547a63b7 Balazs Lecz
      else:
405 547a63b7 Balazs Lecz
        raise
406 7e66c35b Guido Trotter
407 748e4b5a Michael Hanselmann
  @staticmethod
408 748e4b5a Michael Hanselmann
  def _WriteNetScriptFile(instance, seq, nic):
409 eb58f9b1 Guido Trotter
    """Write a script to connect a net interface to the proper bridge.
410 eb58f9b1 Guido Trotter

411 eb58f9b1 Guido Trotter
    This can be used by any qemu-type hypervisor.
412 eb58f9b1 Guido Trotter

413 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
414 eb58f9b1 Guido Trotter
    @type instance: instance object
415 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
416 eb58f9b1 Guido Trotter
    @type seq: int
417 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
418 eb58f9b1 Guido Trotter
    @type nic: nic object
419 eb58f9b1 Guido Trotter
    @return: netscript file name
420 eb58f9b1 Guido Trotter
    @rtype: string
421 eb58f9b1 Guido Trotter

422 eb58f9b1 Guido Trotter
    """
423 748e4b5a Michael Hanselmann
    script = _WriteNetScript(instance, nic, seq)
424 748e4b5a Michael Hanselmann
425 eb58f9b1 Guido Trotter
    # As much as we'd like to put this in our _ROOT_DIR, that will happen to be
426 eb58f9b1 Guido Trotter
    # mounted noexec sometimes, so we'll have to find another place.
427 eb58f9b1 Guido Trotter
    (tmpfd, tmpfile_name) = tempfile.mkstemp()
428 eb58f9b1 Guido Trotter
    tmpfile = os.fdopen(tmpfd, 'w')
429 d73ef63f Michael Hanselmann
    try:
430 748e4b5a Michael Hanselmann
      tmpfile.write(script)
431 d73ef63f Michael Hanselmann
    finally:
432 d73ef63f Michael Hanselmann
      tmpfile.close()
433 eb58f9b1 Guido Trotter
    os.chmod(tmpfile_name, 0755)
434 eb58f9b1 Guido Trotter
    return tmpfile_name
435 eb58f9b1 Guido Trotter
436 eb58f9b1 Guido Trotter
  def ListInstances(self):
437 eb58f9b1 Guido Trotter
    """Get the list of running instances.
438 eb58f9b1 Guido Trotter

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

442 eb58f9b1 Guido Trotter
    """
443 eb58f9b1 Guido Trotter
    result = []
444 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
445 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
446 eb58f9b1 Guido Trotter
        result.append(name)
447 eb58f9b1 Guido Trotter
    return result
448 eb58f9b1 Guido Trotter
449 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
450 eb58f9b1 Guido Trotter
    """Get instance properties.
451 eb58f9b1 Guido Trotter

452 4fbb3c60 Guido Trotter
    @type instance_name: string
453 c41eea6e Iustin Pop
    @param instance_name: the instance name
454 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
455 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
456 eb58f9b1 Guido Trotter

457 eb58f9b1 Guido Trotter
    """
458 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
459 1f8b3a27 Guido Trotter
    if not alive:
460 eb58f9b1 Guido Trotter
      return None
461 eb58f9b1 Guido Trotter
462 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
463 eb58f9b1 Guido Trotter
    stat = "---b-"
464 eb58f9b1 Guido Trotter
    times = "0"
465 eb58f9b1 Guido Trotter
466 eb58f9b1 Guido Trotter
    return (instance_name, pid, memory, vcpus, stat, times)
467 eb58f9b1 Guido Trotter
468 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
469 eb58f9b1 Guido Trotter
    """Get properties of all instances.
470 eb58f9b1 Guido Trotter

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

473 eb58f9b1 Guido Trotter
    """
474 eb58f9b1 Guido Trotter
    data = []
475 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
476 263b8de6 Guido Trotter
      try:
477 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
478 263b8de6 Guido Trotter
      except errors.HypervisorError:
479 263b8de6 Guido Trotter
        continue
480 263b8de6 Guido Trotter
      if info:
481 263b8de6 Guido Trotter
        data.append(info)
482 eb58f9b1 Guido Trotter
    return data
483 eb58f9b1 Guido Trotter
484 07813a9e Iustin Pop
  def _GenerateKVMRuntime(self, instance, block_devices):
485 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
486 eb58f9b1 Guido Trotter

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

648 38e250ba Guido Trotter
    """
649 38e250ba Guido Trotter
    try:
650 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
651 38e250ba Guido Trotter
                      data=data)
652 90c024f6 Guido Trotter
    except EnvironmentError, err:
653 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
654 38e250ba Guido Trotter
655 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
656 38e250ba Guido Trotter
    """Read an instance's KVM runtime
657 38e250ba Guido Trotter

658 38e250ba Guido Trotter
    """
659 38e250ba Guido Trotter
    try:
660 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
661 90c024f6 Guido Trotter
    except EnvironmentError, err:
662 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
663 38e250ba Guido Trotter
    return file_content
664 38e250ba Guido Trotter
665 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
666 38e250ba Guido Trotter
    """Save an instance's KVM runtime
667 38e250ba Guido Trotter

668 38e250ba Guido Trotter
    """
669 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
670 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
671 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
672 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
673 38e250ba Guido Trotter
674 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
675 38e250ba Guido Trotter
    """Load an instance's KVM runtime
676 38e250ba Guido Trotter

677 38e250ba Guido Trotter
    """
678 30e42c4e Guido Trotter
    if not serialized_runtime:
679 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
680 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
681 c2672466 Guido Trotter
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
682 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
683 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
684 38e250ba Guido Trotter
685 76431533 Guido Trotter
  def _RunKVMCmd(self, name, kvm_cmd):
686 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
687 76431533 Guido Trotter

688 76431533 Guido Trotter
    @type name: string
689 76431533 Guido Trotter
    @param name: instance name
690 76431533 Guido Trotter
    @type kvm_cmd: list of strings
691 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
692 76431533 Guido Trotter

693 76431533 Guido Trotter
    """
694 76431533 Guido Trotter
    result = utils.RunCmd(kvm_cmd)
695 76431533 Guido Trotter
    if result.failed:
696 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
697 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
698 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
699 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
700 76431533 Guido Trotter
701 30e42c4e Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
702 ee5f20b0 Guido Trotter
    """Execute a KVM cmd, after completing it with some last minute data
703 ee5f20b0 Guido Trotter

704 30e42c4e Guido Trotter
    @type incoming: tuple of strings
705 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
706 30e42c4e Guido Trotter

707 ee5f20b0 Guido Trotter
    """
708 297e6e53 Guido Trotter
    # Small _ExecuteKVMRuntime hv parameters programming howto:
709 297e6e53 Guido Trotter
    #  - conf_hvp contains the parameters as configured on ganeti. they might
710 297e6e53 Guido Trotter
    #    have changed since the instance started; only use them if the change
711 297e6e53 Guido Trotter
    #    won't affect the inside of the instance (which hasn't been rebooted).
712 297e6e53 Guido Trotter
    #  - up_hvp contains the parameters as they were when the instance was
713 297e6e53 Guido Trotter
    #    started, plus any new parameter which has been added between ganeti
714 297e6e53 Guido Trotter
    #    versions: it is paramount that those default to a value which won't
715 297e6e53 Guido Trotter
    #    affect the inside of the instance as well.
716 297e6e53 Guido Trotter
    conf_hvp = instance.hvparams
717 5905901c Iustin Pop
    name = instance.name
718 5905901c Iustin Pop
    self._CheckDown(name)
719 ee5f20b0 Guido Trotter
720 ee5f20b0 Guido Trotter
    temp_files = []
721 ee5f20b0 Guido Trotter
722 297e6e53 Guido Trotter
    kvm_cmd, kvm_nics, up_hvp = kvm_runtime
723 297e6e53 Guido Trotter
    up_hvp = objects.FillDict(conf_hvp, up_hvp)
724 ee5f20b0 Guido Trotter
725 4b784cf8 Miguel Di Ciurcio Filho
    kvm_version = self._GetKVMVersion()
726 4b784cf8 Miguel Di Ciurcio Filho
    if kvm_version:
727 4b784cf8 Miguel Di Ciurcio Filho
      _, v_major, v_min, v_rev = kvm_version
728 4b784cf8 Miguel Di Ciurcio Filho
    else:
729 4b784cf8 Miguel Di Ciurcio Filho
      raise errors.HypervisorError("Unable to get KVM version")
730 4b784cf8 Miguel Di Ciurcio Filho
731 297e6e53 Guido Trotter
    # We know it's safe to run as a different user upon migration, so we'll use
732 297e6e53 Guido Trotter
    # the latest conf, from conf_hvp.
733 297e6e53 Guido Trotter
    security_model = conf_hvp[constants.HV_SECURITY_MODEL]
734 cef34868 Guido Trotter
    if security_model == constants.HT_SM_USER:
735 297e6e53 Guido Trotter
      kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
736 cef34868 Guido Trotter
737 297e6e53 Guido Trotter
    # We have reasons to believe changing something like the nic driver/type
738 297e6e53 Guido Trotter
    # upon migration won't exactly fly with the instance kernel, so for nic
739 297e6e53 Guido Trotter
    # related parameters we'll use up_hvp
740 ee5f20b0 Guido Trotter
    if not kvm_nics:
741 fbe27e2b Guido Trotter
      kvm_cmd.extend(["-net", "none"])
742 ee5f20b0 Guido Trotter
    else:
743 fbe27e2b Guido Trotter
      tap_extra = ""
744 297e6e53 Guido Trotter
      nic_type = up_hvp[constants.HV_NIC_TYPE]
745 37f88dc6 Guido Trotter
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
746 4b784cf8 Miguel Di Ciurcio Filho
        # From version 0.12.0, kvm uses a new sintax for network configuration.
747 4b784cf8 Miguel Di Ciurcio Filho
        if (v_major, v_min) >= (0,12):
748 4b784cf8 Miguel Di Ciurcio Filho
          nic_model = "virtio-net-pci"
749 4b784cf8 Miguel Di Ciurcio Filho
        else:
750 4b784cf8 Miguel Di Ciurcio Filho
          nic_model = "virtio"
751 4b784cf8 Miguel Di Ciurcio Filho
752 297e6e53 Guido Trotter
        if up_hvp[constants.HV_VHOST_NET]:
753 4b784cf8 Miguel Di Ciurcio Filho
          # vhost_net is only available from version 0.13.0 or newer
754 4b784cf8 Miguel Di Ciurcio Filho
          if (v_major, v_min) >= (0,13):
755 4b784cf8 Miguel Di Ciurcio Filho
            tap_extra = ",vhost=on"
756 4b784cf8 Miguel Di Ciurcio Filho
          else:
757 4b784cf8 Miguel Di Ciurcio Filho
            raise errors.HypervisorError("vhost_net is configured"
758 4b784cf8 Miguel Di Ciurcio Filho
                                        " but it is not available")
759 37f88dc6 Guido Trotter
      else:
760 4b784cf8 Miguel Di Ciurcio Filho
        nic_model = nic_type
761 37f88dc6 Guido Trotter
762 ee5f20b0 Guido Trotter
      for nic_seq, nic in enumerate(kvm_nics):
763 748e4b5a Michael Hanselmann
        script = self._WriteNetScriptFile(instance, nic_seq, nic)
764 ee5f20b0 Guido Trotter
        temp_files.append(script)
765 4b784cf8 Miguel Di Ciurcio Filho
        if (v_major, v_min) >= (0,12):
766 4b784cf8 Miguel Di Ciurcio Filho
          nic_val = "%s,mac=%s,netdev=netdev%s" % (nic_model, nic.mac, nic_seq)
767 4b784cf8 Miguel Di Ciurcio Filho
          tap_val = "type=tap,id=netdev%s,script=%s%s" % (nic_seq, script, tap_extra)
768 4b784cf8 Miguel Di Ciurcio Filho
          kvm_cmd.extend(["-netdev", tap_val, "-device", nic_val])
769 4b784cf8 Miguel Di Ciurcio Filho
        else:
770 4b784cf8 Miguel Di Ciurcio Filho
          nic_val = "nic,vlan=%s,macaddr=%s,model=%s" % (nic_seq, nic.mac, nic_model)
771 4b784cf8 Miguel Di Ciurcio Filho
          tap_val = "tap,vlan=%s,script=%s" % (nic_seq, script)
772 4b784cf8 Miguel Di Ciurcio Filho
          kvm_cmd.extend(["-net", tap_val, "-net", nic_val])
773 ee5f20b0 Guido Trotter
774 30e42c4e Guido Trotter
    if incoming:
775 30e42c4e Guido Trotter
      target, port = incoming
776 30e42c4e Guido Trotter
      kvm_cmd.extend(['-incoming', 'tcp:%s:%s' % (target, port)])
777 30e42c4e Guido Trotter
778 297e6e53 Guido Trotter
    # Changing the vnc password doesn't bother the guest that much. At most it
779 297e6e53 Guido Trotter
    # will surprise people who connect to it. Whether positively or negatively
780 297e6e53 Guido Trotter
    # it's debatable.
781 297e6e53 Guido Trotter
    vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
782 6e6bb8d5 Guido Trotter
    vnc_pwd = None
783 6e6bb8d5 Guido Trotter
    if vnc_pwd_file:
784 6e6bb8d5 Guido Trotter
      try:
785 682f7601 Guido Trotter
        vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
786 6e6bb8d5 Guido Trotter
      except EnvironmentError, err:
787 6e6bb8d5 Guido Trotter
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
788 6e6bb8d5 Guido Trotter
                                     % (vnc_pwd_file, err))
789 6e6bb8d5 Guido Trotter
790 297e6e53 Guido Trotter
    if conf_hvp[constants.HV_KVM_USE_CHROOT]:
791 547a63b7 Balazs Lecz
      utils.EnsureDirs([(self._InstanceChrootDir(name),
792 547a63b7 Balazs Lecz
                         constants.SECURE_DIR_MODE)])
793 547a63b7 Balazs Lecz
794 76431533 Guido Trotter
    if security_model == constants.HT_SM_POOL:
795 76431533 Guido Trotter
      ss = ssconf.SimpleStore()
796 76431533 Guido Trotter
      uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
797 76431533 Guido Trotter
      all_uids = set(uidpool.ExpandUidPool(uid_pool))
798 76431533 Guido Trotter
      uid = uidpool.RequestUnusedUid(all_uids)
799 76431533 Guido Trotter
      try:
800 76431533 Guido Trotter
        username = pwd.getpwuid(uid.GetUid()).pw_name
801 76431533 Guido Trotter
        kvm_cmd.extend(["-runas", username])
802 76431533 Guido Trotter
        self._RunKVMCmd(name, kvm_cmd)
803 76431533 Guido Trotter
      except:
804 76431533 Guido Trotter
        uidpool.ReleaseUid(uid)
805 76431533 Guido Trotter
        raise
806 76431533 Guido Trotter
      else:
807 76431533 Guido Trotter
        uid.Unlock()
808 76431533 Guido Trotter
        utils.WriteFile(self._InstanceUidFile(name), data=str(uid))
809 76431533 Guido Trotter
    else:
810 76431533 Guido Trotter
      self._RunKVMCmd(name, kvm_cmd)
811 eb58f9b1 Guido Trotter
812 6e6bb8d5 Guido Trotter
    if vnc_pwd:
813 6e6bb8d5 Guido Trotter
      change_cmd = 'change vnc password %s' % vnc_pwd
814 6e6bb8d5 Guido Trotter
      self._CallMonitorCommand(instance.name, change_cmd)
815 6e6bb8d5 Guido Trotter
816 08137f9e Iustin Pop
    for filename in temp_files:
817 08137f9e Iustin Pop
      utils.RemoveFile(filename)
818 eb58f9b1 Guido Trotter
819 07813a9e Iustin Pop
  def StartInstance(self, instance, block_devices):
820 ee5f20b0 Guido Trotter
    """Start an instance.
821 ee5f20b0 Guido Trotter

822 ee5f20b0 Guido Trotter
    """
823 5905901c Iustin Pop
    self._CheckDown(instance.name)
824 07813a9e Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices)
825 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
826 ee5f20b0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
827 ee5f20b0 Guido Trotter
828 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
829 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
830 6567aff3 Guido Trotter

831 6567aff3 Guido Trotter
    """
832 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
833 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
834 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
835 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
836 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
837 6567aff3 Guido Trotter
    if result.failed:
838 6567aff3 Guido Trotter
      msg = ("Failed to send command '%s' to instance %s."
839 6567aff3 Guido Trotter
             " output: %s, error: %s, fail_reason: %s" %
840 9798fcae Guido Trotter
             (command, instance_name,
841 9798fcae Guido Trotter
              result.stdout, result.stderr, result.fail_reason))
842 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
843 6567aff3 Guido Trotter
844 6567aff3 Guido Trotter
    return result
845 6567aff3 Guido Trotter
846 b52d85c1 Guido Trotter
  @classmethod
847 b52d85c1 Guido Trotter
  def _GetKVMVersion(cls):
848 b52d85c1 Guido Trotter
    """Return the installed KVM version
849 b52d85c1 Guido Trotter

850 b52d85c1 Guido Trotter
    @return: (version, v_maj, v_min, v_rev), or None
851 b52d85c1 Guido Trotter

852 b52d85c1 Guido Trotter
    """
853 b52d85c1 Guido Trotter
    result = utils.RunCmd([constants.KVM_PATH, "--help"])
854 b52d85c1 Guido Trotter
    if result.failed:
855 b52d85c1 Guido Trotter
      return None
856 b52d85c1 Guido Trotter
    match = cls._VERSION_RE.search(result.output.splitlines()[0])
857 b52d85c1 Guido Trotter
    if not match:
858 b52d85c1 Guido Trotter
      return None
859 3f2eba25 Miguel Di Ciurcio Filho
860 3f2eba25 Miguel Di Ciurcio Filho
    return (match.group(0), int(match.group(1)), int(match.group(2)),
861 3f2eba25 Miguel Di Ciurcio Filho
            int(match.group(3)))
862 b52d85c1 Guido Trotter
863 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
864 eb58f9b1 Guido Trotter
    """Stop an instance.
865 eb58f9b1 Guido Trotter

866 eb58f9b1 Guido Trotter
    """
867 bbcf7ad0 Iustin Pop
    if name is not None and not force:
868 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
869 bbcf7ad0 Iustin Pop
    if name is None:
870 bbcf7ad0 Iustin Pop
      name = instance.name
871 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
872 bbcf7ad0 Iustin Pop
    else:
873 bbcf7ad0 Iustin Pop
      acpi = False
874 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
875 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
876 bbcf7ad0 Iustin Pop
      if force or not acpi:
877 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
878 eb58f9b1 Guido Trotter
      else:
879 bbcf7ad0 Iustin Pop
        self._CallMonitorCommand(name, 'system_powerdown')
880 eb58f9b1 Guido Trotter
881 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
882 8904b35c Guido Trotter
    """Cleanup after a stopped instance
883 8904b35c Guido Trotter

884 8904b35c Guido Trotter
    """
885 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
886 8904b35c Guido Trotter
    if pid > 0 and alive:
887 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
888 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
889 eb58f9b1 Guido Trotter
890 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
891 eb58f9b1 Guido Trotter
    """Reboot an instance.
892 eb58f9b1 Guido Trotter

893 eb58f9b1 Guido Trotter
    """
894 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
895 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
896 eb58f9b1 Guido Trotter
    # to shutdown and restart.
897 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
898 1f8b3a27 Guido Trotter
    if not alive:
899 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
900 78411c60 Iustin Pop
                                   " not running" % instance.name)
901 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
902 f02881e0 Guido Trotter
    # ...first load it...
903 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
904 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
905 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
906 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
907 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
908 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
909 f02881e0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
910 eb58f9b1 Guido Trotter
911 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
912 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
913 30e42c4e Guido Trotter

914 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
915 30e42c4e Guido Trotter
    @param instance: instance to be migrated
916 30e42c4e Guido Trotter
    @rtype: string
917 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
918 30e42c4e Guido Trotter

919 30e42c4e Guido Trotter
    """
920 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
921 30e42c4e Guido Trotter
922 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
923 30e42c4e Guido Trotter
    """Prepare to accept an instance.
924 30e42c4e Guido Trotter

925 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
926 30e42c4e Guido Trotter
    @param instance: instance to be accepted
927 30e42c4e Guido Trotter
    @type info: string
928 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
929 30e42c4e Guido Trotter
    @type target: string
930 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
931 30e42c4e Guido Trotter

932 30e42c4e Guido Trotter
    """
933 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
934 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
935 30e42c4e Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
936 30e42c4e Guido Trotter
937 30e42c4e Guido Trotter
  def FinalizeMigration(self, instance, info, success):
938 30e42c4e Guido Trotter
    """Finalize an instance migration.
939 30e42c4e Guido Trotter

940 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
941 30e42c4e Guido Trotter

942 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
943 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
944 30e42c4e Guido Trotter

945 30e42c4e Guido Trotter
    """
946 30e42c4e Guido Trotter
    if success:
947 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
948 30e42c4e Guido Trotter
    else:
949 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
950 30e42c4e Guido Trotter
951 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
952 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
953 30e42c4e Guido Trotter

954 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
955 30e42c4e Guido Trotter
    currently running.
956 30e42c4e Guido Trotter

957 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
958 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
959 30e42c4e Guido Trotter
    @type target: string
960 30e42c4e Guido Trotter
    @param target: ip address of the target node
961 30e42c4e Guido Trotter
    @type live: boolean
962 30e42c4e Guido Trotter
    @param live: perform a live migration
963 30e42c4e Guido Trotter

964 30e42c4e Guido Trotter
    """
965 58d38b02 Iustin Pop
    instance_name = instance.name
966 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
967 30e42c4e Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
968 30e42c4e Guido Trotter
    if not alive:
969 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
970 30e42c4e Guido Trotter
971 30e42c4e Guido Trotter
    if not live:
972 30e42c4e Guido Trotter
      self._CallMonitorCommand(instance_name, 'stop')
973 30e42c4e Guido Trotter
974 e43d4f9f Apollon Oikonomopoulos
    migrate_command = ('migrate_set_speed %dm' %
975 e43d4f9f Apollon Oikonomopoulos
        instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
976 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
977 e43d4f9f Apollon Oikonomopoulos
978 e43d4f9f Apollon Oikonomopoulos
    migrate_command = ('migrate_set_downtime %dms' %
979 e43d4f9f Apollon Oikonomopoulos
        instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
980 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
981 e43d4f9f Apollon Oikonomopoulos
982 641ae041 Iustin Pop
    migrate_command = 'migrate -d tcp:%s:%s' % (target, port)
983 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
984 30e42c4e Guido Trotter
985 30e42c4e Guido Trotter
    info_command = 'info migrate'
986 30e42c4e Guido Trotter
    done = False
987 c4e388a5 Guido Trotter
    broken_answers = 0
988 30e42c4e Guido Trotter
    while not done:
989 30e42c4e Guido Trotter
      result = self._CallMonitorCommand(instance_name, info_command)
990 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
991 30e42c4e Guido Trotter
      if not match:
992 c4e388a5 Guido Trotter
        broken_answers += 1
993 c4e388a5 Guido Trotter
        if not result.stdout:
994 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
995 c4e388a5 Guido Trotter
        else:
996 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
997 c4e388a5 Guido Trotter
                          result.stdout)
998 c4e388a5 Guido Trotter
        time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
999 30e42c4e Guido Trotter
      else:
1000 30e42c4e Guido Trotter
        status = match.group(1)
1001 30e42c4e Guido Trotter
        if status == 'completed':
1002 30e42c4e Guido Trotter
          done = True
1003 30e42c4e Guido Trotter
        elif status == 'active':
1004 c4e388a5 Guido Trotter
          # reset the broken answers count
1005 c4e388a5 Guido Trotter
          broken_answers = 0
1006 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1007 c087266c Guido Trotter
        elif status == 'failed' or status == 'cancelled':
1008 c087266c Guido Trotter
          if not live:
1009 c087266c Guido Trotter
            self._CallMonitorCommand(instance_name, 'cont')
1010 c087266c Guido Trotter
          raise errors.HypervisorError("Migration %s at the kvm level" %
1011 c087266c Guido Trotter
                                       status)
1012 30e42c4e Guido Trotter
        else:
1013 c4e388a5 Guido Trotter
          logging.warning("KVM: unknown migration status '%s'", status)
1014 c4e388a5 Guido Trotter
          broken_answers += 1
1015 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
1016 c4e388a5 Guido Trotter
      if broken_answers >= self._MIGRATION_INFO_MAX_BAD_ANSWERS:
1017 c4e388a5 Guido Trotter
        raise errors.HypervisorError("Too many 'info migrate' broken answers")
1018 30e42c4e Guido Trotter
1019 30e42c4e Guido Trotter
    utils.KillProcess(pid)
1020 7b381438 Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
1021 30e42c4e Guido Trotter
1022 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
1023 eb58f9b1 Guido Trotter
    """Return information about the node.
1024 eb58f9b1 Guido Trotter

1025 572e52bf Iustin Pop
    This is just a wrapper over the base GetLinuxNodeInfo method.
1026 572e52bf Iustin Pop

1027 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
1028 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
1029 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
1030 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
1031 eb58f9b1 Guido Trotter

1032 eb58f9b1 Guido Trotter
    """
1033 572e52bf Iustin Pop
    return self.GetLinuxNodeInfo()
1034 eb58f9b1 Guido Trotter
1035 637ce7f9 Guido Trotter
  @classmethod
1036 5431b2e4 Guido Trotter
  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
1037 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
1038 eb58f9b1 Guido Trotter

1039 eb58f9b1 Guido Trotter
    """
1040 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
1041 86d6bc2a Guido Trotter
      shell_command = ("%s STDIO,%s UNIX-CONNECT:%s" %
1042 86d6bc2a Guido Trotter
                       (constants.SOCAT_PATH, cls._SocatUnixConsoleParams(),
1043 a2faf9ee Guido Trotter
                        utils.ShellQuote(cls._InstanceSerial(instance.name))))
1044 a2faf9ee Guido Trotter
    else:
1045 a2faf9ee Guido Trotter
      shell_command = "echo 'No serial shell for instance %s'" % instance.name
1046 3be34f57 Guido Trotter
1047 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
1048 3be34f57 Guido Trotter
    if vnc_bind_address:
1049 377d74c9 Guido Trotter
      if instance.network_port > constants.VNC_BASE_PORT:
1050 377d74c9 Guido Trotter
        display = instance.network_port - constants.VNC_BASE_PORT
1051 3be34f57 Guido Trotter
        vnc_command = ("echo 'Instance has VNC listening on %s:%d"
1052 3be34f57 Guido Trotter
                       " (display: %d)'" % (vnc_bind_address,
1053 3be34f57 Guido Trotter
                                            instance.network_port,
1054 3be34f57 Guido Trotter
                                            display))
1055 3be34f57 Guido Trotter
        shell_command = "%s; %s" % (vnc_command, shell_command)
1056 3be34f57 Guido Trotter
1057 a2faf9ee Guido Trotter
    return shell_command
1058 eb58f9b1 Guido Trotter
1059 eb58f9b1 Guido Trotter
  def Verify(self):
1060 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
1061 eb58f9b1 Guido Trotter

1062 eb58f9b1 Guido Trotter
    Check that the binary exists.
1063 eb58f9b1 Guido Trotter

1064 eb58f9b1 Guido Trotter
    """
1065 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
1066 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
1067 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
1068 14aa53cb Guido Trotter
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
1069 14aa53cb Guido Trotter
1070 6b5605e8 Iustin Pop
1071 6b5605e8 Iustin Pop
  @classmethod
1072 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
1073 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
1074 6b5605e8 Iustin Pop

1075 6b5605e8 Iustin Pop
    @type hvparams:  dict
1076 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
1077 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
1078 6b5605e8 Iustin Pop

1079 6b5605e8 Iustin Pop
    """
1080 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
1081 6b5605e8 Iustin Pop
1082 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
1083 df5ab9f0 Guido Trotter
    if kernel_path:
1084 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
1085 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
1086 205ab586 Iustin Pop
                                     " if a kernel is defined")
1087 6b5605e8 Iustin Pop
1088 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
1089 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
1090 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
1091 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
1092 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
1093 66d5dbef Guido Trotter
1094 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
1095 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
1096 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
1097 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
1098 835528af Iustin Pop
                                   " ISO path")
1099 f5118ade Iustin Pop
1100 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
1101 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
1102 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
1103 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
1104 d19d94db Guido Trotter
                                     " must be specified")
1105 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
1106 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
1107 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
1108 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
1109 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
1110 d19d94db Guido Trotter
1111 d19d94db Guido Trotter
  @classmethod
1112 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
1113 d19d94db Guido Trotter
    """Check the given parameters for validity.
1114 d19d94db Guido Trotter

1115 d19d94db Guido Trotter
    @type hvparams:  dict
1116 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
1117 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
1118 d19d94db Guido Trotter

1119 d19d94db Guido Trotter
    """
1120 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
1121 d19d94db Guido Trotter
1122 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
1123 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
1124 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
1125 d19d94db Guido Trotter
      try:
1126 1feb39ec Guido Trotter
        pwd.getpwnam(username)
1127 d19d94db Guido Trotter
      except KeyError:
1128 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
1129 d19d94db Guido Trotter
                                     % username)
1130 d19d94db Guido Trotter
1131 f5118ade Iustin Pop
  @classmethod
1132 f5118ade Iustin Pop
  def PowercycleNode(cls):
1133 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
1134 f5118ade Iustin Pop

1135 f5118ade Iustin Pop
    """
1136 f5118ade Iustin Pop
    cls.LinuxPowercycle()