Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 7ba594c0

History | View | Annotate | Download (30.9 kB)

1 eb58f9b1 Guido Trotter
#
2 eb58f9b1 Guido Trotter
#
3 eb58f9b1 Guido Trotter
4 eb58f9b1 Guido Trotter
# Copyright (C) 2008 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 eb58f9b1 Guido Trotter
import os
27 eb58f9b1 Guido Trotter
import os.path
28 eb58f9b1 Guido Trotter
import re
29 eb58f9b1 Guido Trotter
import tempfile
30 6567aff3 Guido Trotter
import time
31 30e42c4e Guido Trotter
import logging
32 d19d94db Guido Trotter
import pwd
33 eb58f9b1 Guido Trotter
from cStringIO import StringIO
34 eb58f9b1 Guido Trotter
35 eb58f9b1 Guido Trotter
from ganeti import utils
36 eb58f9b1 Guido Trotter
from ganeti import constants
37 eb58f9b1 Guido Trotter
from ganeti import errors
38 38e250ba Guido Trotter
from ganeti import serializer
39 38e250ba Guido Trotter
from ganeti import objects
40 eb58f9b1 Guido Trotter
from ganeti.hypervisor import hv_base
41 eb58f9b1 Guido Trotter
42 eb58f9b1 Guido Trotter
43 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
44 c4469f75 Guido Trotter
  """KVM hypervisor interface"""
45 eb58f9b1 Guido Trotter
46 eb58f9b1 Guido Trotter
  _ROOT_DIR = constants.RUN_GANETI_DIR + "/kvm-hypervisor"
47 a1d79fc6 Guido Trotter
  _PIDS_DIR = _ROOT_DIR + "/pid" # contains live instances pids
48 a1d79fc6 Guido Trotter
  _CTRL_DIR = _ROOT_DIR + "/ctrl" # contains instances control sockets
49 a1d79fc6 Guido Trotter
  _CONF_DIR = _ROOT_DIR + "/conf" # contains instances startup data
50 a1d79fc6 Guido Trotter
  _DIRS = [_ROOT_DIR, _PIDS_DIR, _CTRL_DIR, _CONF_DIR]
51 eb58f9b1 Guido Trotter
52 205ab586 Iustin Pop
  PARAMETERS = {
53 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK,
54 205ab586 Iustin Pop
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
55 205ab586 Iustin Pop
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
56 205ab586 Iustin Pop
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
57 205ab586 Iustin Pop
    constants.HV_ACPI: hv_base.NO_CHECK,
58 205ab586 Iustin Pop
    constants.HV_SERIAL_CONSOLE: hv_base.NO_CHECK,
59 d73ef63f Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS:
60 d73ef63f Michael Hanselmann
      (False, lambda x: (utils.IsValidIP(x) or utils.IsNormAbsPath(x)),
61 d73ef63f Michael Hanselmann
       "the VNC bind address must be either a valid IP address or an absolute"
62 d73ef63f Michael Hanselmann
       " pathname", None, None),
63 205ab586 Iustin Pop
    constants.HV_VNC_TLS: hv_base.NO_CHECK,
64 205ab586 Iustin Pop
    constants.HV_VNC_X509: hv_base.OPT_DIR_CHECK,
65 205ab586 Iustin Pop
    constants.HV_VNC_X509_VERIFY: hv_base.NO_CHECK,
66 6e6bb8d5 Guido Trotter
    constants.HV_VNC_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
67 205ab586 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
68 d73ef63f Michael Hanselmann
    constants.HV_BOOT_ORDER:
69 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
70 d73ef63f Michael Hanselmann
    constants.HV_NIC_TYPE:
71 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
72 d73ef63f Michael Hanselmann
    constants.HV_DISK_TYPE:
73 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
74 d73ef63f Michael Hanselmann
    constants.HV_USB_MOUSE:
75 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
76 78411c60 Iustin Pop
    constants.HV_MIGRATION_PORT: hv_base.NET_PORT_CHECK,
77 6b970cef Jun Futagawa
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
78 19572932 Iustin Pop
    constants.HV_DISK_CACHE:
79 19572932 Iustin Pop
      hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
80 d19d94db Guido Trotter
    constants.HV_SECURITY_MODEL:
81 d19d94db Guido Trotter
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_SM_TYPES),
82 d19d94db Guido Trotter
    constants.HV_SECURITY_DOMAIN: hv_base.NO_CHECK,
83 7ba594c0 Guido Trotter
    constants.HV_KVM_FLAG:
84 7ba594c0 Guido Trotter
      hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES),
85 205ab586 Iustin Pop
    }
86 6b5605e8 Iustin Pop
87 30e42c4e Guido Trotter
  _MIGRATION_STATUS_RE = re.compile('Migration\s+status:\s+(\w+)',
88 30e42c4e Guido Trotter
                                    re.M | re.I)
89 c4e388a5 Guido Trotter
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
90 c4e388a5 Guido Trotter
  _MIGRATION_INFO_RETRY_DELAY = 2
91 30e42c4e Guido Trotter
92 5420ffc9 Guido Trotter
  _KVM_NETWORK_SCRIPT = constants.SYSCONFDIR + "/ganeti/kvm-vif-bridge"
93 5420ffc9 Guido Trotter
94 64bfbc08 Guido Trotter
  ANCILLARY_FILES = [
95 64bfbc08 Guido Trotter
    _KVM_NETWORK_SCRIPT,
96 64bfbc08 Guido Trotter
    ]
97 64bfbc08 Guido Trotter
98 eb58f9b1 Guido Trotter
  def __init__(self):
99 eb58f9b1 Guido Trotter
    hv_base.BaseHypervisor.__init__(self)
100 eb58f9b1 Guido Trotter
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
101 eb58f9b1 Guido Trotter
    # in a tmpfs filesystem or has been otherwise wiped out.
102 29921401 Iustin Pop
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
103 9afb67fe Guido Trotter
    utils.EnsureDirs(dirs)
104 eb58f9b1 Guido Trotter
105 30786fc9 Iustin Pop
  @classmethod
106 30786fc9 Iustin Pop
  def _InstancePidFile(cls, instance_name):
107 98ec75d6 Iustin Pop
    """Returns the instance pidfile.
108 98ec75d6 Iustin Pop

109 98ec75d6 Iustin Pop
    """
110 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
111 98ec75d6 Iustin Pop
112 263b8de6 Guido Trotter
  @classmethod
113 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
114 263b8de6 Guido Trotter
    """Check pid file for instance information.
115 263b8de6 Guido Trotter

116 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
117 263b8de6 Guido Trotter
    information from its command line.
118 263b8de6 Guido Trotter

119 263b8de6 Guido Trotter
    @type pid: string or int
120 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
121 263b8de6 Guido Trotter
    @rtype: tuple
122 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
123 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
124 263b8de6 Guido Trotter

125 263b8de6 Guido Trotter
    """
126 263b8de6 Guido Trotter
    alive = utils.IsProcessAlive(pid)
127 263b8de6 Guido Trotter
    if not alive:
128 263b8de6 Guido Trotter
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
129 263b8de6 Guido Trotter
130 263b8de6 Guido Trotter
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
131 263b8de6 Guido Trotter
    try:
132 263b8de6 Guido Trotter
      cmdline = utils.ReadFile(cmdline_file)
133 263b8de6 Guido Trotter
    except EnvironmentError, err:
134 263b8de6 Guido Trotter
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
135 263b8de6 Guido Trotter
                                   (pid, err))
136 263b8de6 Guido Trotter
137 263b8de6 Guido Trotter
    instance = None
138 263b8de6 Guido Trotter
    memory = 0
139 263b8de6 Guido Trotter
    vcpus = 0
140 263b8de6 Guido Trotter
141 263b8de6 Guido Trotter
    arg_list = cmdline.split('\x00')
142 263b8de6 Guido Trotter
    while arg_list:
143 263b8de6 Guido Trotter
      arg =  arg_list.pop(0)
144 263b8de6 Guido Trotter
      if arg == "-name":
145 263b8de6 Guido Trotter
        instance = arg_list.pop(0)
146 263b8de6 Guido Trotter
      elif arg == "-m":
147 263b8de6 Guido Trotter
        memory = int(arg_list.pop(0))
148 263b8de6 Guido Trotter
      elif arg == "-smp":
149 263b8de6 Guido Trotter
        vcpus = int(arg_list.pop(0))
150 263b8de6 Guido Trotter
151 263b8de6 Guido Trotter
    if instance is None:
152 263b8de6 Guido Trotter
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
153 263b8de6 Guido Trotter
                                   " instance" % pid)
154 263b8de6 Guido Trotter
155 263b8de6 Guido Trotter
    return (instance, memory, vcpus)
156 263b8de6 Guido Trotter
157 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
158 263b8de6 Guido Trotter
    """Returns the instance pidfile, pid, and liveness.
159 263b8de6 Guido Trotter

160 263b8de6 Guido Trotter
    @type instance_name: string
161 263b8de6 Guido Trotter
    @param instance_name: instance name
162 263b8de6 Guido Trotter
    @rtype: tuple
163 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
164 1f8b3a27 Guido Trotter

165 1f8b3a27 Guido Trotter
    """
166 98ec75d6 Iustin Pop
    pidfile = self._InstancePidFile(instance_name)
167 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
168 263b8de6 Guido Trotter
169 263b8de6 Guido Trotter
    alive = False
170 263b8de6 Guido Trotter
    try:
171 263b8de6 Guido Trotter
      cmd_instance = self._InstancePidInfo(pid)[0]
172 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
173 263b8de6 Guido Trotter
    except errors.HypervisorError:
174 263b8de6 Guido Trotter
      pass
175 1f8b3a27 Guido Trotter
176 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
177 1f8b3a27 Guido Trotter
178 5905901c Iustin Pop
  def _CheckDown(self, instance_name):
179 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
180 5905901c Iustin Pop

181 5905901c Iustin Pop
    """
182 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
183 5905901c Iustin Pop
    if alive:
184 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
185 5905901c Iustin Pop
                                   (instance_name, "already running"))
186 5905901c Iustin Pop
187 0df4d98a Guido Trotter
  @classmethod
188 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
189 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
190 c4fbefc8 Guido Trotter

191 c4fbefc8 Guido Trotter
    """
192 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
193 c4fbefc8 Guido Trotter
194 0df4d98a Guido Trotter
  @classmethod
195 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
196 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
197 c4fbefc8 Guido Trotter

198 c4fbefc8 Guido Trotter
    """
199 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
200 c4fbefc8 Guido Trotter
201 86d6bc2a Guido Trotter
  @staticmethod
202 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
203 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
204 86d6bc2a Guido Trotter

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

207 86d6bc2a Guido Trotter
    """
208 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
209 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
210 86d6bc2a Guido Trotter
    else:
211 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
212 86d6bc2a Guido Trotter
213 0df4d98a Guido Trotter
  @classmethod
214 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
215 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
216 38e250ba Guido Trotter

217 38e250ba Guido Trotter
    """
218 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
219 38e250ba Guido Trotter
220 7e66c35b Guido Trotter
  @classmethod
221 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
222 7e66c35b Guido Trotter
    """Removes an instance's rutime sockets/files.
223 7e66c35b Guido Trotter

224 7e66c35b Guido Trotter
    """
225 7e66c35b Guido Trotter
    utils.RemoveFile(pidfile)
226 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
227 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceSerial(instance_name))
228 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
229 7e66c35b Guido Trotter
230 eb58f9b1 Guido Trotter
  def _WriteNetScript(self, instance, seq, nic):
231 eb58f9b1 Guido Trotter
    """Write a script to connect a net interface to the proper bridge.
232 eb58f9b1 Guido Trotter

233 eb58f9b1 Guido Trotter
    This can be used by any qemu-type hypervisor.
234 eb58f9b1 Guido Trotter

235 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
236 eb58f9b1 Guido Trotter
    @type instance: instance object
237 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
238 eb58f9b1 Guido Trotter
    @type seq: int
239 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
240 eb58f9b1 Guido Trotter
    @type nic: nic object
241 eb58f9b1 Guido Trotter
    @return: netscript file name
242 eb58f9b1 Guido Trotter
    @rtype: string
243 eb58f9b1 Guido Trotter

244 eb58f9b1 Guido Trotter
    """
245 eb58f9b1 Guido Trotter
    script = StringIO()
246 eb58f9b1 Guido Trotter
    script.write("#!/bin/sh\n")
247 eb58f9b1 Guido Trotter
    script.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
248 e8022bef Vitaly Kuznetsov
    script.write("PATH=$PATH:/sbin:/usr/sbin\n")
249 eb58f9b1 Guido Trotter
    script.write("export INSTANCE=%s\n" % instance.name)
250 eb58f9b1 Guido Trotter
    script.write("export MAC=%s\n" % nic.mac)
251 bef9c750 Guido Trotter
    if nic.ip:
252 bef9c750 Guido Trotter
      script.write("export IP=%s\n" % nic.ip)
253 bef9c750 Guido Trotter
    script.write("export MODE=%s\n" % nic.nicparams[constants.NIC_MODE])
254 bef9c750 Guido Trotter
    if nic.nicparams[constants.NIC_LINK]:
255 bef9c750 Guido Trotter
      script.write("export LINK=%s\n" % nic.nicparams[constants.NIC_LINK])
256 bef9c750 Guido Trotter
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
257 bef9c750 Guido Trotter
      script.write("export BRIDGE=%s\n" % nic.nicparams[constants.NIC_LINK])
258 eb58f9b1 Guido Trotter
    script.write("export INTERFACE=$1\n")
259 eb58f9b1 Guido Trotter
    # TODO: make this configurable at ./configure time
260 5420ffc9 Guido Trotter
    script.write("if [ -x '%s' ]; then\n" % self._KVM_NETWORK_SCRIPT)
261 eb58f9b1 Guido Trotter
    script.write("  # Execute the user-specific vif file\n")
262 5420ffc9 Guido Trotter
    script.write("  %s\n" % self._KVM_NETWORK_SCRIPT)
263 eb58f9b1 Guido Trotter
    script.write("else\n")
264 e8022bef Vitaly Kuznetsov
    script.write("  ifconfig $INTERFACE 0.0.0.0 up\n")
265 bef9c750 Guido Trotter
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
266 bef9c750 Guido Trotter
      script.write("  # Connect the interface to the bridge\n")
267 e8022bef Vitaly Kuznetsov
      script.write("  brctl addif $BRIDGE $INTERFACE\n")
268 bef9c750 Guido Trotter
    elif nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_ROUTED:
269 94c2ed34 Guido Trotter
      if not nic.ip:
270 94c2ed34 Guido Trotter
        raise errors.HypervisorError("nic/%d is routed, but has no ip." % seq)
271 bef9c750 Guido Trotter
      script.write("  # Route traffic targeted at the IP to the interface\n")
272 7c60f7a2 Guido Trotter
      if nic.nicparams[constants.NIC_LINK]:
273 e8022bef Vitaly Kuznetsov
        script.write("  while ip rule del dev $INTERFACE; do :; done\n")
274 e8022bef Vitaly Kuznetsov
        script.write("  ip rule add dev $INTERFACE table $LINK\n")
275 e8022bef Vitaly Kuznetsov
        script.write("  ip route replace $IP table $LINK proto static"
276 d63218ce Guido Trotter
                     " dev $INTERFACE\n")
277 7c60f7a2 Guido Trotter
      else:
278 e8022bef Vitaly Kuznetsov
        script.write("  ip route replace $IP proto static"
279 8866ec86 Guido Trotter
                     " dev $INTERFACE\n")
280 e014f1d0 Guido Trotter
      interface_v4_conf = "/proc/sys/net/ipv4/conf/$INTERFACE"
281 e014f1d0 Guido Trotter
      interface_v6_conf = "/proc/sys/net/ipv6/conf/$INTERFACE"
282 e014f1d0 Guido Trotter
      script.write("  if [ -d %s ]; then\n" % interface_v4_conf)
283 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/proxy_arp\n" % interface_v4_conf)
284 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/forwarding\n" % interface_v4_conf)
285 e014f1d0 Guido Trotter
      script.write("  fi\n")
286 e014f1d0 Guido Trotter
      script.write("  if [ -d %s ]; then\n" % interface_v6_conf)
287 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/proxy_ndp\n" % interface_v6_conf)
288 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/forwarding\n" % interface_v6_conf)
289 e014f1d0 Guido Trotter
      script.write("  fi\n")
290 eb58f9b1 Guido Trotter
    script.write("fi\n\n")
291 eb58f9b1 Guido Trotter
    # As much as we'd like to put this in our _ROOT_DIR, that will happen to be
292 eb58f9b1 Guido Trotter
    # mounted noexec sometimes, so we'll have to find another place.
293 eb58f9b1 Guido Trotter
    (tmpfd, tmpfile_name) = tempfile.mkstemp()
294 eb58f9b1 Guido Trotter
    tmpfile = os.fdopen(tmpfd, 'w')
295 d73ef63f Michael Hanselmann
    try:
296 d73ef63f Michael Hanselmann
      tmpfile.write(script.getvalue())
297 d73ef63f Michael Hanselmann
    finally:
298 d73ef63f Michael Hanselmann
      tmpfile.close()
299 eb58f9b1 Guido Trotter
    os.chmod(tmpfile_name, 0755)
300 eb58f9b1 Guido Trotter
    return tmpfile_name
301 eb58f9b1 Guido Trotter
302 eb58f9b1 Guido Trotter
  def ListInstances(self):
303 eb58f9b1 Guido Trotter
    """Get the list of running instances.
304 eb58f9b1 Guido Trotter

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

308 eb58f9b1 Guido Trotter
    """
309 eb58f9b1 Guido Trotter
    result = []
310 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
311 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
312 eb58f9b1 Guido Trotter
        result.append(name)
313 eb58f9b1 Guido Trotter
    return result
314 eb58f9b1 Guido Trotter
315 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
316 eb58f9b1 Guido Trotter
    """Get instance properties.
317 eb58f9b1 Guido Trotter

318 4fbb3c60 Guido Trotter
    @type instance_name: string
319 c41eea6e Iustin Pop
    @param instance_name: the instance name
320 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
321 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
322 eb58f9b1 Guido Trotter

323 eb58f9b1 Guido Trotter
    """
324 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
325 1f8b3a27 Guido Trotter
    if not alive:
326 eb58f9b1 Guido Trotter
      return None
327 eb58f9b1 Guido Trotter
328 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
329 eb58f9b1 Guido Trotter
    stat = "---b-"
330 eb58f9b1 Guido Trotter
    times = "0"
331 eb58f9b1 Guido Trotter
332 eb58f9b1 Guido Trotter
    return (instance_name, pid, memory, vcpus, stat, times)
333 eb58f9b1 Guido Trotter
334 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
335 eb58f9b1 Guido Trotter
    """Get properties of all instances.
336 eb58f9b1 Guido Trotter

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

339 eb58f9b1 Guido Trotter
    """
340 eb58f9b1 Guido Trotter
    data = []
341 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
342 263b8de6 Guido Trotter
      try:
343 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
344 263b8de6 Guido Trotter
      except errors.HypervisorError:
345 263b8de6 Guido Trotter
        continue
346 263b8de6 Guido Trotter
      if info:
347 263b8de6 Guido Trotter
        data.append(info)
348 eb58f9b1 Guido Trotter
    return data
349 eb58f9b1 Guido Trotter
350 07813a9e Iustin Pop
  def _GenerateKVMRuntime(self, instance, block_devices):
351 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
352 eb58f9b1 Guido Trotter

353 eb58f9b1 Guido Trotter
    """
354 98ec75d6 Iustin Pop
    pidfile  = self._InstancePidFile(instance.name)
355 eb58f9b1 Guido Trotter
    kvm = constants.KVM_PATH
356 eb58f9b1 Guido Trotter
    kvm_cmd = [kvm]
357 c6a39fc2 Guido Trotter
    # used just by the vnc server, if enabled
358 c6a39fc2 Guido Trotter
    kvm_cmd.extend(['-name', instance.name])
359 8b3fd458 Iustin Pop
    kvm_cmd.extend(['-m', instance.beparams[constants.BE_MEMORY]])
360 8b3fd458 Iustin Pop
    kvm_cmd.extend(['-smp', instance.beparams[constants.BE_VCPUS]])
361 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-pidfile', pidfile])
362 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-daemonize'])
363 6b5605e8 Iustin Pop
    if not instance.hvparams[constants.HV_ACPI]:
364 eb58f9b1 Guido Trotter
      kvm_cmd.extend(['-no-acpi'])
365 eb58f9b1 Guido Trotter
366 a985b417 Iustin Pop
    hvp = instance.hvparams
367 835528af Iustin Pop
    boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
368 835528af Iustin Pop
    boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
369 835528af Iustin Pop
    boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
370 8745c3d7 Guido Trotter
371 7ba594c0 Guido Trotter
    if hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED:
372 7ba594c0 Guido Trotter
      kvm_cmd.extend(["-enable-kvm"])
373 7ba594c0 Guido Trotter
    elif hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED:
374 7ba594c0 Guido Trotter
      kvm_cmd.extend(["-disable-kvm"])
375 7ba594c0 Guido Trotter
376 8745c3d7 Guido Trotter
    if boot_network:
377 8745c3d7 Guido Trotter
      kvm_cmd.extend(['-boot', 'n'])
378 1213604d Guido Trotter
379 a985b417 Iustin Pop
    disk_type = hvp[constants.HV_DISK_TYPE]
380 1213604d Guido Trotter
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
381 1213604d Guido Trotter
      if_val = ',if=virtio'
382 1213604d Guido Trotter
    else:
383 1213604d Guido Trotter
      if_val = ',if=%s' % disk_type
384 19572932 Iustin Pop
    # Cache mode
385 19572932 Iustin Pop
    disk_cache = hvp[constants.HV_DISK_CACHE]
386 19572932 Iustin Pop
    if disk_cache != constants.HT_CACHE_DEFAULT:
387 19572932 Iustin Pop
      cache_val = ",cache=%s" % disk_cache
388 19572932 Iustin Pop
    else:
389 19572932 Iustin Pop
      cache_val = ""
390 069cfbf1 Iustin Pop
    for cfdev, dev_path in block_devices:
391 d34b16d7 Iustin Pop
      if cfdev.mode != constants.DISK_RDWR:
392 d34b16d7 Iustin Pop
        raise errors.HypervisorError("Instance has read-only disks which"
393 d34b16d7 Iustin Pop
                                     " are not supported by KVM")
394 eb58f9b1 Guido Trotter
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
395 66d5dbef Guido Trotter
      if boot_disk:
396 9dd363eb Guido Trotter
        kvm_cmd.extend(['-boot', 'c'])
397 eb58f9b1 Guido Trotter
        boot_val = ',boot=on'
398 8745c3d7 Guido Trotter
        # We only boot from the first disk
399 66d5dbef Guido Trotter
        boot_disk = False
400 eb58f9b1 Guido Trotter
      else:
401 eb58f9b1 Guido Trotter
        boot_val = ''
402 eb58f9b1 Guido Trotter
403 19572932 Iustin Pop
      drive_val = 'file=%s,format=raw%s%s%s' % (dev_path, if_val, boot_val,
404 19572932 Iustin Pop
                                                cache_val)
405 eb58f9b1 Guido Trotter
      kvm_cmd.extend(['-drive', drive_val])
406 eb58f9b1 Guido Trotter
407 a985b417 Iustin Pop
    iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
408 66d5dbef Guido Trotter
    if iso_image:
409 9dd363eb Guido Trotter
      options = ',format=raw,media=cdrom'
410 66d5dbef Guido Trotter
      if boot_cdrom:
411 9dd363eb Guido Trotter
        kvm_cmd.extend(['-boot', 'd'])
412 66d5dbef Guido Trotter
        options = '%s,boot=on' % options
413 9dd363eb Guido Trotter
      else:
414 9dd363eb Guido Trotter
        options = '%s,if=virtio' % options
415 66d5dbef Guido Trotter
      drive_val = 'file=%s%s' % (iso_image, options)
416 66d5dbef Guido Trotter
      kvm_cmd.extend(['-drive', drive_val])
417 66d5dbef Guido Trotter
418 a985b417 Iustin Pop
    kernel_path = hvp[constants.HV_KERNEL_PATH]
419 df5ab9f0 Guido Trotter
    if kernel_path:
420 df5ab9f0 Guido Trotter
      kvm_cmd.extend(['-kernel', kernel_path])
421 a985b417 Iustin Pop
      initrd_path = hvp[constants.HV_INITRD_PATH]
422 df5ab9f0 Guido Trotter
      if initrd_path:
423 df5ab9f0 Guido Trotter
        kvm_cmd.extend(['-initrd', initrd_path])
424 07813a9e Iustin Pop
      root_append = ['root=%s' % hvp[constants.HV_ROOT_PATH],
425 07813a9e Iustin Pop
                     hvp[constants.HV_KERNEL_ARGS]]
426 07813a9e Iustin Pop
      if hvp[constants.HV_SERIAL_CONSOLE]:
427 07813a9e Iustin Pop
        root_append.append('console=ttyS0,38400')
428 07813a9e Iustin Pop
      kvm_cmd.extend(['-append', ' '.join(root_append)])
429 eb58f9b1 Guido Trotter
430 a985b417 Iustin Pop
    mouse_type = hvp[constants.HV_USB_MOUSE]
431 11344a50 Guido Trotter
    if mouse_type:
432 11344a50 Guido Trotter
      kvm_cmd.extend(['-usb'])
433 11344a50 Guido Trotter
      kvm_cmd.extend(['-usbdevice', mouse_type])
434 11344a50 Guido Trotter
435 a985b417 Iustin Pop
    vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
436 8470c8db Guido Trotter
    if vnc_bind_address:
437 8447f52b Guido Trotter
      if utils.IsValidIP(vnc_bind_address):
438 377d74c9 Guido Trotter
        if instance.network_port > constants.VNC_BASE_PORT:
439 377d74c9 Guido Trotter
          display = instance.network_port - constants.VNC_BASE_PORT
440 8447f52b Guido Trotter
          if vnc_bind_address == '0.0.0.0':
441 8447f52b Guido Trotter
            vnc_arg = ':%d' % (display)
442 8447f52b Guido Trotter
          else:
443 19498d6c Guido Trotter
            vnc_arg = '%s:%d' % (vnc_bind_address, display)
444 8470c8db Guido Trotter
        else:
445 8447f52b Guido Trotter
          logging.error("Network port is not a valid VNC display (%d < %d)."
446 07b8a2b5 Iustin Pop
                        " Not starting VNC", instance.network_port,
447 07b8a2b5 Iustin Pop
                        constants.VNC_BASE_PORT)
448 8447f52b Guido Trotter
          vnc_arg = 'none'
449 8b2d1013 Guido Trotter
450 8b2d1013 Guido Trotter
        # Only allow tls and other option when not binding to a file, for now.
451 8b2d1013 Guido Trotter
        # kvm/qemu gets confused otherwise about the filename to use.
452 8b2d1013 Guido Trotter
        vnc_append = ''
453 a985b417 Iustin Pop
        if hvp[constants.HV_VNC_TLS]:
454 8b2d1013 Guido Trotter
          vnc_append = '%s,tls' % vnc_append
455 a985b417 Iustin Pop
          if hvp[constants.HV_VNC_X509_VERIFY]:
456 8b2d1013 Guido Trotter
            vnc_append = '%s,x509verify=%s' % (vnc_append,
457 a985b417 Iustin Pop
                                               hvp[constants.HV_VNC_X509])
458 a985b417 Iustin Pop
          elif hvp[constants.HV_VNC_X509]:
459 8b2d1013 Guido Trotter
            vnc_append = '%s,x509=%s' % (vnc_append,
460 a985b417 Iustin Pop
                                         hvp[constants.HV_VNC_X509])
461 6e6bb8d5 Guido Trotter
        if hvp[constants.HV_VNC_PASSWORD_FILE]:
462 6e6bb8d5 Guido Trotter
          vnc_append = '%s,password' % vnc_append
463 6e6bb8d5 Guido Trotter
464 8b2d1013 Guido Trotter
        vnc_arg = '%s%s' % (vnc_arg, vnc_append)
465 8b2d1013 Guido Trotter
466 8470c8db Guido Trotter
      else:
467 8b2d1013 Guido Trotter
        vnc_arg = 'unix:%s/%s.vnc' % (vnc_bind_address, instance.name)
468 8b2d1013 Guido Trotter
469 8447f52b Guido Trotter
      kvm_cmd.extend(['-vnc', vnc_arg])
470 8470c8db Guido Trotter
    else:
471 8470c8db Guido Trotter
      kvm_cmd.extend(['-nographic'])
472 8470c8db Guido Trotter
473 69b99987 Michael Hanselmann
    monitor_dev = ("unix:%s,server,nowait" %
474 69b99987 Michael Hanselmann
                   self._InstanceMonitor(instance.name))
475 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-monitor', monitor_dev])
476 a985b417 Iustin Pop
    if hvp[constants.HV_SERIAL_CONSOLE]:
477 a985b417 Iustin Pop
      serial_dev = ('unix:%s,server,nowait' %
478 a985b417 Iustin Pop
                    self._InstanceSerial(instance.name))
479 a2faf9ee Guido Trotter
      kvm_cmd.extend(['-serial', serial_dev])
480 a2faf9ee Guido Trotter
    else:
481 a2faf9ee Guido Trotter
      kvm_cmd.extend(['-serial', 'none'])
482 eb58f9b1 Guido Trotter
483 6b970cef Jun Futagawa
    if hvp[constants.HV_USE_LOCALTIME]:
484 6b970cef Jun Futagawa
      kvm_cmd.extend(['-localtime'])
485 6b970cef Jun Futagawa
486 ee5f20b0 Guido Trotter
    # Save the current instance nics, but defer their expansion as parameters,
487 ee5f20b0 Guido Trotter
    # as we'll need to generate executable temp files for them.
488 ee5f20b0 Guido Trotter
    kvm_nics = instance.nics
489 a985b417 Iustin Pop
    hvparams = hvp
490 ee5f20b0 Guido Trotter
491 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
492 ee5f20b0 Guido Trotter
493 38e250ba Guido Trotter
  def _WriteKVMRuntime(self, instance_name, data):
494 38e250ba Guido Trotter
    """Write an instance's KVM runtime
495 38e250ba Guido Trotter

496 38e250ba Guido Trotter
    """
497 38e250ba Guido Trotter
    try:
498 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
499 38e250ba Guido Trotter
                      data=data)
500 90c024f6 Guido Trotter
    except EnvironmentError, err:
501 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
502 38e250ba Guido Trotter
503 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
504 38e250ba Guido Trotter
    """Read an instance's KVM runtime
505 38e250ba Guido Trotter

506 38e250ba Guido Trotter
    """
507 38e250ba Guido Trotter
    try:
508 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
509 90c024f6 Guido Trotter
    except EnvironmentError, err:
510 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
511 38e250ba Guido Trotter
    return file_content
512 38e250ba Guido Trotter
513 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
514 38e250ba Guido Trotter
    """Save an instance's KVM runtime
515 38e250ba Guido Trotter

516 38e250ba Guido Trotter
    """
517 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
518 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
519 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
520 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
521 38e250ba Guido Trotter
522 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
523 38e250ba Guido Trotter
    """Load an instance's KVM runtime
524 38e250ba Guido Trotter

525 38e250ba Guido Trotter
    """
526 30e42c4e Guido Trotter
    if not serialized_runtime:
527 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
528 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
529 c2672466 Guido Trotter
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
530 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
531 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
532 38e250ba Guido Trotter
533 30e42c4e Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
534 ee5f20b0 Guido Trotter
    """Execute a KVM cmd, after completing it with some last minute data
535 ee5f20b0 Guido Trotter

536 30e42c4e Guido Trotter
    @type incoming: tuple of strings
537 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
538 30e42c4e Guido Trotter

539 ee5f20b0 Guido Trotter
    """
540 6e6bb8d5 Guido Trotter
    hvp = instance.hvparams
541 5905901c Iustin Pop
    name = instance.name
542 5905901c Iustin Pop
    self._CheckDown(name)
543 ee5f20b0 Guido Trotter
544 ee5f20b0 Guido Trotter
    temp_files = []
545 ee5f20b0 Guido Trotter
546 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
547 ee5f20b0 Guido Trotter
548 cef34868 Guido Trotter
    security_model = hvp[constants.HV_SECURITY_MODEL]
549 cef34868 Guido Trotter
    if security_model == constants.HT_SM_USER:
550 cef34868 Guido Trotter
      kvm_cmd.extend(["-runas", hvp[constants.HV_SECURITY_DOMAIN]])
551 cef34868 Guido Trotter
552 ee5f20b0 Guido Trotter
    if not kvm_nics:
553 ee5f20b0 Guido Trotter
      kvm_cmd.extend(['-net', 'none'])
554 ee5f20b0 Guido Trotter
    else:
555 37f88dc6 Guido Trotter
      nic_type = hvparams[constants.HV_NIC_TYPE]
556 37f88dc6 Guido Trotter
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
557 37f88dc6 Guido Trotter
        nic_model = "model=virtio"
558 37f88dc6 Guido Trotter
      else:
559 37f88dc6 Guido Trotter
        nic_model = "model=%s" % nic_type
560 37f88dc6 Guido Trotter
561 ee5f20b0 Guido Trotter
      for nic_seq, nic in enumerate(kvm_nics):
562 760570a8 Timothy Kuhlman
        nic_val = "nic,vlan=%s,macaddr=%s,%s" % (nic_seq, nic.mac, nic_model)
563 ee5f20b0 Guido Trotter
        script = self._WriteNetScript(instance, nic_seq, nic)
564 ee5f20b0 Guido Trotter
        kvm_cmd.extend(['-net', nic_val])
565 760570a8 Timothy Kuhlman
        kvm_cmd.extend(['-net', 'tap,vlan=%s,script=%s' % (nic_seq, script)])
566 ee5f20b0 Guido Trotter
        temp_files.append(script)
567 ee5f20b0 Guido Trotter
568 30e42c4e Guido Trotter
    if incoming:
569 30e42c4e Guido Trotter
      target, port = incoming
570 30e42c4e Guido Trotter
      kvm_cmd.extend(['-incoming', 'tcp:%s:%s' % (target, port)])
571 30e42c4e Guido Trotter
572 6e6bb8d5 Guido Trotter
    vnc_pwd_file = hvp[constants.HV_VNC_PASSWORD_FILE]
573 6e6bb8d5 Guido Trotter
    vnc_pwd = None
574 6e6bb8d5 Guido Trotter
    if vnc_pwd_file:
575 6e6bb8d5 Guido Trotter
      try:
576 6e6bb8d5 Guido Trotter
        vnc_pwd = utils.ReadFile(vnc_pwd_file)
577 6e6bb8d5 Guido Trotter
      except EnvironmentError, err:
578 6e6bb8d5 Guido Trotter
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
579 6e6bb8d5 Guido Trotter
                                     % (vnc_pwd_file, err))
580 6e6bb8d5 Guido Trotter
581 eb58f9b1 Guido Trotter
    result = utils.RunCmd(kvm_cmd)
582 eb58f9b1 Guido Trotter
    if result.failed:
583 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
584 5905901c Iustin Pop
                                   (name, result.fail_reason, result.output))
585 eb58f9b1 Guido Trotter
586 5905901c Iustin Pop
    if not self._InstancePidAlive(name)[2]:
587 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s" % name)
588 eb58f9b1 Guido Trotter
589 6e6bb8d5 Guido Trotter
    if vnc_pwd:
590 6e6bb8d5 Guido Trotter
      change_cmd = 'change vnc password %s' % vnc_pwd
591 6e6bb8d5 Guido Trotter
      self._CallMonitorCommand(instance.name, change_cmd)
592 6e6bb8d5 Guido Trotter
593 08137f9e Iustin Pop
    for filename in temp_files:
594 08137f9e Iustin Pop
      utils.RemoveFile(filename)
595 eb58f9b1 Guido Trotter
596 07813a9e Iustin Pop
  def StartInstance(self, instance, block_devices):
597 ee5f20b0 Guido Trotter
    """Start an instance.
598 ee5f20b0 Guido Trotter

599 ee5f20b0 Guido Trotter
    """
600 5905901c Iustin Pop
    self._CheckDown(instance.name)
601 07813a9e Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices)
602 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
603 ee5f20b0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
604 ee5f20b0 Guido Trotter
605 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
606 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
607 6567aff3 Guido Trotter

608 6567aff3 Guido Trotter
    """
609 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
610 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
611 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
612 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
613 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
614 6567aff3 Guido Trotter
    if result.failed:
615 6567aff3 Guido Trotter
      msg = ("Failed to send command '%s' to instance %s."
616 6567aff3 Guido Trotter
             " output: %s, error: %s, fail_reason: %s" %
617 9798fcae Guido Trotter
             (command, instance_name,
618 9798fcae Guido Trotter
              result.stdout, result.stderr, result.fail_reason))
619 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
620 6567aff3 Guido Trotter
621 6567aff3 Guido Trotter
    return result
622 6567aff3 Guido Trotter
623 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
624 eb58f9b1 Guido Trotter
    """Stop an instance.
625 eb58f9b1 Guido Trotter

626 eb58f9b1 Guido Trotter
    """
627 bbcf7ad0 Iustin Pop
    if name is not None and not force:
628 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
629 bbcf7ad0 Iustin Pop
    if name is None:
630 bbcf7ad0 Iustin Pop
      name = instance.name
631 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
632 bbcf7ad0 Iustin Pop
    else:
633 bbcf7ad0 Iustin Pop
      acpi = False
634 bbcf7ad0 Iustin Pop
    pidfile, pid, alive = self._InstancePidAlive(name)
635 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
636 bbcf7ad0 Iustin Pop
      if force or not acpi:
637 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
638 eb58f9b1 Guido Trotter
      else:
639 bbcf7ad0 Iustin Pop
        self._CallMonitorCommand(name, 'system_powerdown')
640 eb58f9b1 Guido Trotter
641 bbcf7ad0 Iustin Pop
    if not self._InstancePidAlive(name)[2]:
642 bbcf7ad0 Iustin Pop
      self._RemoveInstanceRuntimeFiles(pidfile, name)
643 6567aff3 Guido Trotter
      return True
644 6567aff3 Guido Trotter
    else:
645 6567aff3 Guido Trotter
      return False
646 eb58f9b1 Guido Trotter
647 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
648 eb58f9b1 Guido Trotter
    """Reboot an instance.
649 eb58f9b1 Guido Trotter

650 eb58f9b1 Guido Trotter
    """
651 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
652 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
653 eb58f9b1 Guido Trotter
    # to shutdown and restart.
654 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
655 1f8b3a27 Guido Trotter
    if not alive:
656 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
657 78411c60 Iustin Pop
                                   " not running" % instance.name)
658 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
659 f02881e0 Guido Trotter
    # ...first load it...
660 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
661 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
662 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
663 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
664 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
665 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
666 f02881e0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
667 eb58f9b1 Guido Trotter
668 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
669 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
670 30e42c4e Guido Trotter

671 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
672 30e42c4e Guido Trotter
    @param instance: instance to be migrated
673 30e42c4e Guido Trotter
    @rtype: string
674 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
675 30e42c4e Guido Trotter

676 30e42c4e Guido Trotter
    """
677 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
678 30e42c4e Guido Trotter
679 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
680 30e42c4e Guido Trotter
    """Prepare to accept an instance.
681 30e42c4e Guido Trotter

682 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
683 30e42c4e Guido Trotter
    @param instance: instance to be accepted
684 30e42c4e Guido Trotter
    @type info: string
685 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
686 30e42c4e Guido Trotter
    @type target: string
687 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
688 30e42c4e Guido Trotter

689 30e42c4e Guido Trotter
    """
690 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
691 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
692 30e42c4e Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
693 30e42c4e Guido Trotter
694 30e42c4e Guido Trotter
  def FinalizeMigration(self, instance, info, success):
695 30e42c4e Guido Trotter
    """Finalize an instance migration.
696 30e42c4e Guido Trotter

697 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
698 30e42c4e Guido Trotter

699 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
700 30e42c4e Guido Trotter
    @param instance: instance whose migration is being aborted
701 30e42c4e Guido Trotter

702 30e42c4e Guido Trotter
    """
703 30e42c4e Guido Trotter
    if success:
704 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
705 30e42c4e Guido Trotter
    else:
706 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
707 30e42c4e Guido Trotter
708 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
709 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
710 30e42c4e Guido Trotter

711 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
712 30e42c4e Guido Trotter
    currently running.
713 30e42c4e Guido Trotter

714 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
715 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
716 30e42c4e Guido Trotter
    @type target: string
717 30e42c4e Guido Trotter
    @param target: ip address of the target node
718 30e42c4e Guido Trotter
    @type live: boolean
719 30e42c4e Guido Trotter
    @param live: perform a live migration
720 30e42c4e Guido Trotter

721 30e42c4e Guido Trotter
    """
722 58d38b02 Iustin Pop
    instance_name = instance.name
723 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
724 30e42c4e Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
725 30e42c4e Guido Trotter
    if not alive:
726 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
727 30e42c4e Guido Trotter
728 50716be0 Iustin Pop
    if not utils.TcpPing(target, port, live_port_needed=True):
729 50716be0 Iustin Pop
      raise errors.HypervisorError("Remote host %s not listening on port"
730 50716be0 Iustin Pop
                                   " %s, cannot migrate" % (target, port))
731 50716be0 Iustin Pop
732 30e42c4e Guido Trotter
    if not live:
733 30e42c4e Guido Trotter
      self._CallMonitorCommand(instance_name, 'stop')
734 30e42c4e Guido Trotter
735 641ae041 Iustin Pop
    migrate_command = 'migrate -d tcp:%s:%s' % (target, port)
736 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
737 30e42c4e Guido Trotter
738 30e42c4e Guido Trotter
    info_command = 'info migrate'
739 30e42c4e Guido Trotter
    done = False
740 c4e388a5 Guido Trotter
    broken_answers = 0
741 30e42c4e Guido Trotter
    while not done:
742 30e42c4e Guido Trotter
      result = self._CallMonitorCommand(instance_name, info_command)
743 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
744 30e42c4e Guido Trotter
      if not match:
745 c4e388a5 Guido Trotter
        broken_answers += 1
746 c4e388a5 Guido Trotter
        if not result.stdout:
747 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
748 c4e388a5 Guido Trotter
        else:
749 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
750 c4e388a5 Guido Trotter
                          result.stdout)
751 c4e388a5 Guido Trotter
        time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
752 30e42c4e Guido Trotter
      else:
753 30e42c4e Guido Trotter
        status = match.group(1)
754 30e42c4e Guido Trotter
        if status == 'completed':
755 30e42c4e Guido Trotter
          done = True
756 30e42c4e Guido Trotter
        elif status == 'active':
757 c4e388a5 Guido Trotter
          # reset the broken answers count
758 c4e388a5 Guido Trotter
          broken_answers = 0
759 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
760 c087266c Guido Trotter
        elif status == 'failed' or status == 'cancelled':
761 c087266c Guido Trotter
          if not live:
762 c087266c Guido Trotter
            self._CallMonitorCommand(instance_name, 'cont')
763 c087266c Guido Trotter
          raise errors.HypervisorError("Migration %s at the kvm level" %
764 c087266c Guido Trotter
                                       status)
765 30e42c4e Guido Trotter
        else:
766 c4e388a5 Guido Trotter
          logging.warning("KVM: unknown migration status '%s'", status)
767 c4e388a5 Guido Trotter
          broken_answers += 1
768 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
769 c4e388a5 Guido Trotter
      if broken_answers >= self._MIGRATION_INFO_MAX_BAD_ANSWERS:
770 c4e388a5 Guido Trotter
        raise errors.HypervisorError("Too many 'info migrate' broken answers")
771 30e42c4e Guido Trotter
772 30e42c4e Guido Trotter
    utils.KillProcess(pid)
773 7b381438 Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
774 30e42c4e Guido Trotter
775 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
776 eb58f9b1 Guido Trotter
    """Return information about the node.
777 eb58f9b1 Guido Trotter

778 572e52bf Iustin Pop
    This is just a wrapper over the base GetLinuxNodeInfo method.
779 572e52bf Iustin Pop

780 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
781 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
782 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
783 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
784 eb58f9b1 Guido Trotter

785 eb58f9b1 Guido Trotter
    """
786 572e52bf Iustin Pop
    return self.GetLinuxNodeInfo()
787 eb58f9b1 Guido Trotter
788 637ce7f9 Guido Trotter
  @classmethod
789 5431b2e4 Guido Trotter
  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
790 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
791 eb58f9b1 Guido Trotter

792 eb58f9b1 Guido Trotter
    """
793 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
794 86d6bc2a Guido Trotter
      shell_command = ("%s STDIO,%s UNIX-CONNECT:%s" %
795 86d6bc2a Guido Trotter
                       (constants.SOCAT_PATH, cls._SocatUnixConsoleParams(),
796 a2faf9ee Guido Trotter
                        utils.ShellQuote(cls._InstanceSerial(instance.name))))
797 a2faf9ee Guido Trotter
    else:
798 a2faf9ee Guido Trotter
      shell_command = "echo 'No serial shell for instance %s'" % instance.name
799 3be34f57 Guido Trotter
800 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
801 3be34f57 Guido Trotter
    if vnc_bind_address:
802 377d74c9 Guido Trotter
      if instance.network_port > constants.VNC_BASE_PORT:
803 377d74c9 Guido Trotter
        display = instance.network_port - constants.VNC_BASE_PORT
804 3be34f57 Guido Trotter
        vnc_command = ("echo 'Instance has VNC listening on %s:%d"
805 3be34f57 Guido Trotter
                       " (display: %d)'" % (vnc_bind_address,
806 3be34f57 Guido Trotter
                                            instance.network_port,
807 3be34f57 Guido Trotter
                                            display))
808 3be34f57 Guido Trotter
        shell_command = "%s; %s" % (vnc_command, shell_command)
809 3be34f57 Guido Trotter
810 a2faf9ee Guido Trotter
    return shell_command
811 eb58f9b1 Guido Trotter
812 eb58f9b1 Guido Trotter
  def Verify(self):
813 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
814 eb58f9b1 Guido Trotter

815 eb58f9b1 Guido Trotter
    Check that the binary exists.
816 eb58f9b1 Guido Trotter

817 eb58f9b1 Guido Trotter
    """
818 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
819 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
820 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
821 14aa53cb Guido Trotter
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
822 14aa53cb Guido Trotter
823 6b5605e8 Iustin Pop
824 6b5605e8 Iustin Pop
  @classmethod
825 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
826 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
827 6b5605e8 Iustin Pop

828 6b5605e8 Iustin Pop
    @type hvparams:  dict
829 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
830 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
831 6b5605e8 Iustin Pop

832 6b5605e8 Iustin Pop
    """
833 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
834 6b5605e8 Iustin Pop
835 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
836 df5ab9f0 Guido Trotter
    if kernel_path:
837 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
838 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
839 205ab586 Iustin Pop
                                     " if a kernel is defined")
840 6b5605e8 Iustin Pop
841 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
842 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
843 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
844 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
845 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
846 66d5dbef Guido Trotter
847 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
848 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
849 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
850 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
851 835528af Iustin Pop
                                   " ISO path")
852 f5118ade Iustin Pop
853 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
854 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
855 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
856 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
857 d19d94db Guido Trotter
                                     " must be specified")
858 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
859 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
860 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
861 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
862 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
863 d19d94db Guido Trotter
    if security_model == constants.HT_SM_POOL:
864 d19d94db Guido Trotter
      raise errors.HypervisorError("Security model pool is not supported yet")
865 d19d94db Guido Trotter
866 d19d94db Guido Trotter
  @classmethod
867 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
868 d19d94db Guido Trotter
    """Check the given parameters for validity.
869 d19d94db Guido Trotter

870 d19d94db Guido Trotter
    @type hvparams:  dict
871 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
872 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
873 d19d94db Guido Trotter

874 d19d94db Guido Trotter
    """
875 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
876 d19d94db Guido Trotter
877 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
878 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
879 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
880 d19d94db Guido Trotter
      try:
881 1feb39ec Guido Trotter
        pwd.getpwnam(username)
882 d19d94db Guido Trotter
      except KeyError:
883 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
884 d19d94db Guido Trotter
                                     % username)
885 d19d94db Guido Trotter
886 f5118ade Iustin Pop
  @classmethod
887 f5118ade Iustin Pop
  def PowercycleNode(cls):
888 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
889 f5118ade Iustin Pop

890 f5118ade Iustin Pop
    """
891 f5118ade Iustin Pop
    cls.LinuxPowercycle()