Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ b4478d34

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

103 98ec75d6 Iustin Pop
    """
104 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
105 98ec75d6 Iustin Pop
106 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
107 1f8b3a27 Guido Trotter
    """Returns the instance pid and pidfile
108 1f8b3a27 Guido Trotter

109 1f8b3a27 Guido Trotter
    """
110 98ec75d6 Iustin Pop
    pidfile = self._InstancePidFile(instance_name)
111 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
112 1f8b3a27 Guido Trotter
    alive = utils.IsProcessAlive(pid)
113 1f8b3a27 Guido Trotter
114 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
115 1f8b3a27 Guido Trotter
116 5905901c Iustin Pop
  def _CheckDown(self, instance_name):
117 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
118 5905901c Iustin Pop

119 5905901c Iustin Pop
    """
120 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
121 5905901c Iustin Pop
    if alive:
122 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
123 5905901c Iustin Pop
                                   (instance_name, "already running"))
124 5905901c Iustin Pop
125 0df4d98a Guido Trotter
  @classmethod
126 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
127 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
128 c4fbefc8 Guido Trotter

129 c4fbefc8 Guido Trotter
    """
130 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
131 c4fbefc8 Guido Trotter
132 0df4d98a Guido Trotter
  @classmethod
133 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
134 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
135 c4fbefc8 Guido Trotter

136 c4fbefc8 Guido Trotter
    """
137 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
138 c4fbefc8 Guido Trotter
139 86d6bc2a Guido Trotter
  @staticmethod
140 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
141 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
142 86d6bc2a Guido Trotter

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

145 86d6bc2a Guido Trotter
    """
146 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
147 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
148 86d6bc2a Guido Trotter
    else:
149 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
150 86d6bc2a Guido Trotter
151 0df4d98a Guido Trotter
  @classmethod
152 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
153 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
154 38e250ba Guido Trotter

155 38e250ba Guido Trotter
    """
156 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
157 38e250ba Guido Trotter
158 7e66c35b Guido Trotter
  @classmethod
159 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
160 7e66c35b Guido Trotter
    """Removes an instance's rutime sockets/files.
161 7e66c35b Guido Trotter

162 7e66c35b Guido Trotter
    """
163 7e66c35b Guido Trotter
    utils.RemoveFile(pidfile)
164 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
165 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceSerial(instance_name))
166 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
167 7e66c35b Guido Trotter
168 eb58f9b1 Guido Trotter
  def _WriteNetScript(self, instance, seq, nic):
169 eb58f9b1 Guido Trotter
    """Write a script to connect a net interface to the proper bridge.
170 eb58f9b1 Guido Trotter

171 eb58f9b1 Guido Trotter
    This can be used by any qemu-type hypervisor.
172 eb58f9b1 Guido Trotter

173 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
174 eb58f9b1 Guido Trotter
    @type instance: instance object
175 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
176 eb58f9b1 Guido Trotter
    @type seq: int
177 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
178 eb58f9b1 Guido Trotter
    @type nic: nic object
179 eb58f9b1 Guido Trotter
    @return: netscript file name
180 eb58f9b1 Guido Trotter
    @rtype: string
181 eb58f9b1 Guido Trotter

182 eb58f9b1 Guido Trotter
    """
183 eb58f9b1 Guido Trotter
    script = StringIO()
184 eb58f9b1 Guido Trotter
    script.write("#!/bin/sh\n")
185 eb58f9b1 Guido Trotter
    script.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
186 e8022bef Vitaly Kuznetsov
    script.write("PATH=$PATH:/sbin:/usr/sbin\n")
187 eb58f9b1 Guido Trotter
    script.write("export INSTANCE=%s\n" % instance.name)
188 eb58f9b1 Guido Trotter
    script.write("export MAC=%s\n" % nic.mac)
189 bef9c750 Guido Trotter
    if nic.ip:
190 bef9c750 Guido Trotter
      script.write("export IP=%s\n" % nic.ip)
191 bef9c750 Guido Trotter
    script.write("export MODE=%s\n" % nic.nicparams[constants.NIC_MODE])
192 bef9c750 Guido Trotter
    if nic.nicparams[constants.NIC_LINK]:
193 bef9c750 Guido Trotter
      script.write("export LINK=%s\n" % nic.nicparams[constants.NIC_LINK])
194 bef9c750 Guido Trotter
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
195 bef9c750 Guido Trotter
      script.write("export BRIDGE=%s\n" % nic.nicparams[constants.NIC_LINK])
196 eb58f9b1 Guido Trotter
    script.write("export INTERFACE=$1\n")
197 eb58f9b1 Guido Trotter
    # TODO: make this configurable at ./configure time
198 5420ffc9 Guido Trotter
    script.write("if [ -x '%s' ]; then\n" % self._KVM_NETWORK_SCRIPT)
199 eb58f9b1 Guido Trotter
    script.write("  # Execute the user-specific vif file\n")
200 5420ffc9 Guido Trotter
    script.write("  %s\n" % self._KVM_NETWORK_SCRIPT)
201 eb58f9b1 Guido Trotter
    script.write("else\n")
202 e8022bef Vitaly Kuznetsov
    script.write("  ifconfig $INTERFACE 0.0.0.0 up\n")
203 bef9c750 Guido Trotter
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
204 bef9c750 Guido Trotter
      script.write("  # Connect the interface to the bridge\n")
205 e8022bef Vitaly Kuznetsov
      script.write("  brctl addif $BRIDGE $INTERFACE\n")
206 bef9c750 Guido Trotter
    elif nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_ROUTED:
207 94c2ed34 Guido Trotter
      if not nic.ip:
208 94c2ed34 Guido Trotter
        raise errors.HypervisorError("nic/%d is routed, but has no ip." % seq)
209 bef9c750 Guido Trotter
      script.write("  # Route traffic targeted at the IP to the interface\n")
210 7c60f7a2 Guido Trotter
      if nic.nicparams[constants.NIC_LINK]:
211 e8022bef Vitaly Kuznetsov
        script.write("  while ip rule del dev $INTERFACE; do :; done\n")
212 e8022bef Vitaly Kuznetsov
        script.write("  ip rule add dev $INTERFACE table $LINK\n")
213 e8022bef Vitaly Kuznetsov
        script.write("  ip route replace $IP table $LINK proto static"
214 d63218ce Guido Trotter
                     " dev $INTERFACE\n")
215 7c60f7a2 Guido Trotter
      else:
216 e8022bef Vitaly Kuznetsov
        script.write("  ip route replace $IP proto static"
217 8866ec86 Guido Trotter
                     " dev $INTERFACE\n")
218 e014f1d0 Guido Trotter
      interface_v4_conf = "/proc/sys/net/ipv4/conf/$INTERFACE"
219 e014f1d0 Guido Trotter
      interface_v6_conf = "/proc/sys/net/ipv6/conf/$INTERFACE"
220 e014f1d0 Guido Trotter
      script.write("  if [ -d %s ]; then\n" % interface_v4_conf)
221 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/proxy_arp\n" % interface_v4_conf)
222 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/forwarding\n" % interface_v4_conf)
223 e014f1d0 Guido Trotter
      script.write("  fi\n")
224 e014f1d0 Guido Trotter
      script.write("  if [ -d %s ]; then\n" % interface_v6_conf)
225 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/proxy_ndp\n" % interface_v6_conf)
226 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/forwarding\n" % interface_v6_conf)
227 e014f1d0 Guido Trotter
      script.write("  fi\n")
228 eb58f9b1 Guido Trotter
    script.write("fi\n\n")
229 eb58f9b1 Guido Trotter
    # As much as we'd like to put this in our _ROOT_DIR, that will happen to be
230 eb58f9b1 Guido Trotter
    # mounted noexec sometimes, so we'll have to find another place.
231 eb58f9b1 Guido Trotter
    (tmpfd, tmpfile_name) = tempfile.mkstemp()
232 eb58f9b1 Guido Trotter
    tmpfile = os.fdopen(tmpfd, 'w')
233 d73ef63f Michael Hanselmann
    try:
234 d73ef63f Michael Hanselmann
      tmpfile.write(script.getvalue())
235 d73ef63f Michael Hanselmann
    finally:
236 d73ef63f Michael Hanselmann
      tmpfile.close()
237 eb58f9b1 Guido Trotter
    os.chmod(tmpfile_name, 0755)
238 eb58f9b1 Guido Trotter
    return tmpfile_name
239 eb58f9b1 Guido Trotter
240 eb58f9b1 Guido Trotter
  def ListInstances(self):
241 eb58f9b1 Guido Trotter
    """Get the list of running instances.
242 eb58f9b1 Guido Trotter

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

246 eb58f9b1 Guido Trotter
    """
247 eb58f9b1 Guido Trotter
    result = []
248 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
249 30786fc9 Iustin Pop
      filename = utils.PathJoin(self._PIDS_DIR, name)
250 08137f9e Iustin Pop
      if utils.IsProcessAlive(utils.ReadPidFile(filename)):
251 eb58f9b1 Guido Trotter
        result.append(name)
252 eb58f9b1 Guido Trotter
    return result
253 eb58f9b1 Guido Trotter
254 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
255 eb58f9b1 Guido Trotter
    """Get instance properties.
256 eb58f9b1 Guido Trotter

257 c41eea6e Iustin Pop
    @param instance_name: the instance name
258 c41eea6e Iustin Pop

259 c41eea6e Iustin Pop
    @return: tuple (name, id, memory, vcpus, stat, times)
260 eb58f9b1 Guido Trotter

261 eb58f9b1 Guido Trotter
    """
262 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
263 1f8b3a27 Guido Trotter
    if not alive:
264 eb58f9b1 Guido Trotter
      return None
265 eb58f9b1 Guido Trotter
266 30786fc9 Iustin Pop
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
267 eb58f9b1 Guido Trotter
    try:
268 1e37ad45 Michael Hanselmann
      cmdline = utils.ReadFile(cmdline_file)
269 90c024f6 Guido Trotter
    except EnvironmentError, err:
270 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to list instance %s: %s" %
271 eb58f9b1 Guido Trotter
                                   (instance_name, err))
272 eb58f9b1 Guido Trotter
273 eb58f9b1 Guido Trotter
    memory = 0
274 eb58f9b1 Guido Trotter
    vcpus = 0
275 eb58f9b1 Guido Trotter
    stat = "---b-"
276 eb58f9b1 Guido Trotter
    times = "0"
277 eb58f9b1 Guido Trotter
278 eb58f9b1 Guido Trotter
    arg_list = cmdline.split('\x00')
279 eb58f9b1 Guido Trotter
    while arg_list:
280 eb58f9b1 Guido Trotter
      arg =  arg_list.pop(0)
281 eb58f9b1 Guido Trotter
      if arg == '-m':
282 2a7e887b Guido Trotter
        memory = int(arg_list.pop(0))
283 eb58f9b1 Guido Trotter
      elif arg == '-smp':
284 2a7e887b Guido Trotter
        vcpus = int(arg_list.pop(0))
285 eb58f9b1 Guido Trotter
286 eb58f9b1 Guido Trotter
    return (instance_name, pid, memory, vcpus, stat, times)
287 eb58f9b1 Guido Trotter
288 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
289 eb58f9b1 Guido Trotter
    """Get properties of all instances.
290 eb58f9b1 Guido Trotter

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

293 eb58f9b1 Guido Trotter
    """
294 eb58f9b1 Guido Trotter
    data = []
295 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
296 30786fc9 Iustin Pop
      filename = utils.PathJoin(self._PIDS_DIR, name)
297 08137f9e Iustin Pop
      if utils.IsProcessAlive(utils.ReadPidFile(filename)):
298 00ad5362 Guido Trotter
        try:
299 00ad5362 Guido Trotter
          info = self.GetInstanceInfo(name)
300 1122eb25 Iustin Pop
        except errors.HypervisorError:
301 00ad5362 Guido Trotter
          continue
302 00ad5362 Guido Trotter
        if info:
303 00ad5362 Guido Trotter
          data.append(info)
304 eb58f9b1 Guido Trotter
305 eb58f9b1 Guido Trotter
    return data
306 eb58f9b1 Guido Trotter
307 07813a9e Iustin Pop
  def _GenerateKVMRuntime(self, instance, block_devices):
308 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
309 eb58f9b1 Guido Trotter

310 eb58f9b1 Guido Trotter
    """
311 98ec75d6 Iustin Pop
    pidfile  = self._InstancePidFile(instance.name)
312 eb58f9b1 Guido Trotter
    kvm = constants.KVM_PATH
313 eb58f9b1 Guido Trotter
    kvm_cmd = [kvm]
314 8b3fd458 Iustin Pop
    kvm_cmd.extend(['-m', instance.beparams[constants.BE_MEMORY]])
315 8b3fd458 Iustin Pop
    kvm_cmd.extend(['-smp', instance.beparams[constants.BE_VCPUS]])
316 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-pidfile', pidfile])
317 eb58f9b1 Guido Trotter
    # used just by the vnc server, if enabled
318 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-name', instance.name])
319 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-daemonize'])
320 6b5605e8 Iustin Pop
    if not instance.hvparams[constants.HV_ACPI]:
321 eb58f9b1 Guido Trotter
      kvm_cmd.extend(['-no-acpi'])
322 eb58f9b1 Guido Trotter
323 a985b417 Iustin Pop
    hvp = instance.hvparams
324 835528af Iustin Pop
    boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
325 835528af Iustin Pop
    boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
326 835528af Iustin Pop
    boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
327 8745c3d7 Guido Trotter
328 8745c3d7 Guido Trotter
    if boot_network:
329 8745c3d7 Guido Trotter
      kvm_cmd.extend(['-boot', 'n'])
330 1213604d Guido Trotter
331 a985b417 Iustin Pop
    disk_type = hvp[constants.HV_DISK_TYPE]
332 1213604d Guido Trotter
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
333 1213604d Guido Trotter
      if_val = ',if=virtio'
334 1213604d Guido Trotter
    else:
335 1213604d Guido Trotter
      if_val = ',if=%s' % disk_type
336 19572932 Iustin Pop
    # Cache mode
337 19572932 Iustin Pop
    disk_cache = hvp[constants.HV_DISK_CACHE]
338 19572932 Iustin Pop
    if disk_cache != constants.HT_CACHE_DEFAULT:
339 19572932 Iustin Pop
      cache_val = ",cache=%s" % disk_cache
340 19572932 Iustin Pop
    else:
341 19572932 Iustin Pop
      cache_val = ""
342 069cfbf1 Iustin Pop
    for cfdev, dev_path in block_devices:
343 d34b16d7 Iustin Pop
      if cfdev.mode != constants.DISK_RDWR:
344 d34b16d7 Iustin Pop
        raise errors.HypervisorError("Instance has read-only disks which"
345 d34b16d7 Iustin Pop
                                     " are not supported by KVM")
346 eb58f9b1 Guido Trotter
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
347 66d5dbef Guido Trotter
      if boot_disk:
348 9dd363eb Guido Trotter
        kvm_cmd.extend(['-boot', 'c'])
349 eb58f9b1 Guido Trotter
        boot_val = ',boot=on'
350 8745c3d7 Guido Trotter
        # We only boot from the first disk
351 66d5dbef Guido Trotter
        boot_disk = False
352 eb58f9b1 Guido Trotter
      else:
353 eb58f9b1 Guido Trotter
        boot_val = ''
354 eb58f9b1 Guido Trotter
355 19572932 Iustin Pop
      drive_val = 'file=%s,format=raw%s%s%s' % (dev_path, if_val, boot_val,
356 19572932 Iustin Pop
                                                cache_val)
357 eb58f9b1 Guido Trotter
      kvm_cmd.extend(['-drive', drive_val])
358 eb58f9b1 Guido Trotter
359 a985b417 Iustin Pop
    iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
360 66d5dbef Guido Trotter
    if iso_image:
361 9dd363eb Guido Trotter
      options = ',format=raw,media=cdrom'
362 66d5dbef Guido Trotter
      if boot_cdrom:
363 9dd363eb Guido Trotter
        kvm_cmd.extend(['-boot', 'd'])
364 66d5dbef Guido Trotter
        options = '%s,boot=on' % options
365 9dd363eb Guido Trotter
      else:
366 9dd363eb Guido Trotter
        options = '%s,if=virtio' % options
367 66d5dbef Guido Trotter
      drive_val = 'file=%s%s' % (iso_image, options)
368 66d5dbef Guido Trotter
      kvm_cmd.extend(['-drive', drive_val])
369 66d5dbef Guido Trotter
370 a985b417 Iustin Pop
    kernel_path = hvp[constants.HV_KERNEL_PATH]
371 df5ab9f0 Guido Trotter
    if kernel_path:
372 df5ab9f0 Guido Trotter
      kvm_cmd.extend(['-kernel', kernel_path])
373 a985b417 Iustin Pop
      initrd_path = hvp[constants.HV_INITRD_PATH]
374 df5ab9f0 Guido Trotter
      if initrd_path:
375 df5ab9f0 Guido Trotter
        kvm_cmd.extend(['-initrd', initrd_path])
376 07813a9e Iustin Pop
      root_append = ['root=%s' % hvp[constants.HV_ROOT_PATH],
377 07813a9e Iustin Pop
                     hvp[constants.HV_KERNEL_ARGS]]
378 07813a9e Iustin Pop
      if hvp[constants.HV_SERIAL_CONSOLE]:
379 07813a9e Iustin Pop
        root_append.append('console=ttyS0,38400')
380 07813a9e Iustin Pop
      kvm_cmd.extend(['-append', ' '.join(root_append)])
381 eb58f9b1 Guido Trotter
382 a985b417 Iustin Pop
    mouse_type = hvp[constants.HV_USB_MOUSE]
383 11344a50 Guido Trotter
    if mouse_type:
384 11344a50 Guido Trotter
      kvm_cmd.extend(['-usb'])
385 11344a50 Guido Trotter
      kvm_cmd.extend(['-usbdevice', mouse_type])
386 11344a50 Guido Trotter
387 a985b417 Iustin Pop
    vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
388 8470c8db Guido Trotter
    if vnc_bind_address:
389 8447f52b Guido Trotter
      if utils.IsValidIP(vnc_bind_address):
390 377d74c9 Guido Trotter
        if instance.network_port > constants.VNC_BASE_PORT:
391 377d74c9 Guido Trotter
          display = instance.network_port - constants.VNC_BASE_PORT
392 8447f52b Guido Trotter
          if vnc_bind_address == '0.0.0.0':
393 8447f52b Guido Trotter
            vnc_arg = ':%d' % (display)
394 8447f52b Guido Trotter
          else:
395 19498d6c Guido Trotter
            vnc_arg = '%s:%d' % (vnc_bind_address, display)
396 8470c8db Guido Trotter
        else:
397 8447f52b Guido Trotter
          logging.error("Network port is not a valid VNC display (%d < %d)."
398 07b8a2b5 Iustin Pop
                        " Not starting VNC", instance.network_port,
399 07b8a2b5 Iustin Pop
                        constants.VNC_BASE_PORT)
400 8447f52b Guido Trotter
          vnc_arg = 'none'
401 8b2d1013 Guido Trotter
402 8b2d1013 Guido Trotter
        # Only allow tls and other option when not binding to a file, for now.
403 8b2d1013 Guido Trotter
        # kvm/qemu gets confused otherwise about the filename to use.
404 8b2d1013 Guido Trotter
        vnc_append = ''
405 a985b417 Iustin Pop
        if hvp[constants.HV_VNC_TLS]:
406 8b2d1013 Guido Trotter
          vnc_append = '%s,tls' % vnc_append
407 a985b417 Iustin Pop
          if hvp[constants.HV_VNC_X509_VERIFY]:
408 8b2d1013 Guido Trotter
            vnc_append = '%s,x509verify=%s' % (vnc_append,
409 a985b417 Iustin Pop
                                               hvp[constants.HV_VNC_X509])
410 a985b417 Iustin Pop
          elif hvp[constants.HV_VNC_X509]:
411 8b2d1013 Guido Trotter
            vnc_append = '%s,x509=%s' % (vnc_append,
412 a985b417 Iustin Pop
                                         hvp[constants.HV_VNC_X509])
413 6e6bb8d5 Guido Trotter
        if hvp[constants.HV_VNC_PASSWORD_FILE]:
414 6e6bb8d5 Guido Trotter
          vnc_append = '%s,password' % vnc_append
415 6e6bb8d5 Guido Trotter
416 8b2d1013 Guido Trotter
        vnc_arg = '%s%s' % (vnc_arg, vnc_append)
417 8b2d1013 Guido Trotter
418 8470c8db Guido Trotter
      else:
419 8b2d1013 Guido Trotter
        vnc_arg = 'unix:%s/%s.vnc' % (vnc_bind_address, instance.name)
420 8b2d1013 Guido Trotter
421 8447f52b Guido Trotter
      kvm_cmd.extend(['-vnc', vnc_arg])
422 8470c8db Guido Trotter
    else:
423 8470c8db Guido Trotter
      kvm_cmd.extend(['-nographic'])
424 8470c8db Guido Trotter
425 69b99987 Michael Hanselmann
    monitor_dev = ("unix:%s,server,nowait" %
426 69b99987 Michael Hanselmann
                   self._InstanceMonitor(instance.name))
427 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-monitor', monitor_dev])
428 a985b417 Iustin Pop
    if hvp[constants.HV_SERIAL_CONSOLE]:
429 a985b417 Iustin Pop
      serial_dev = ('unix:%s,server,nowait' %
430 a985b417 Iustin Pop
                    self._InstanceSerial(instance.name))
431 a2faf9ee Guido Trotter
      kvm_cmd.extend(['-serial', serial_dev])
432 a2faf9ee Guido Trotter
    else:
433 a2faf9ee Guido Trotter
      kvm_cmd.extend(['-serial', 'none'])
434 eb58f9b1 Guido Trotter
435 6b970cef Jun Futagawa
    if hvp[constants.HV_USE_LOCALTIME]:
436 6b970cef Jun Futagawa
      kvm_cmd.extend(['-localtime'])
437 6b970cef Jun Futagawa
438 ee5f20b0 Guido Trotter
    # Save the current instance nics, but defer their expansion as parameters,
439 ee5f20b0 Guido Trotter
    # as we'll need to generate executable temp files for them.
440 ee5f20b0 Guido Trotter
    kvm_nics = instance.nics
441 a985b417 Iustin Pop
    hvparams = hvp
442 ee5f20b0 Guido Trotter
443 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
444 ee5f20b0 Guido Trotter
445 38e250ba Guido Trotter
  def _WriteKVMRuntime(self, instance_name, data):
446 38e250ba Guido Trotter
    """Write an instance's KVM runtime
447 38e250ba Guido Trotter

448 38e250ba Guido Trotter
    """
449 38e250ba Guido Trotter
    try:
450 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
451 38e250ba Guido Trotter
                      data=data)
452 90c024f6 Guido Trotter
    except EnvironmentError, err:
453 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
454 38e250ba Guido Trotter
455 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
456 38e250ba Guido Trotter
    """Read an instance's KVM runtime
457 38e250ba Guido Trotter

458 38e250ba Guido Trotter
    """
459 38e250ba Guido Trotter
    try:
460 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
461 90c024f6 Guido Trotter
    except EnvironmentError, err:
462 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
463 38e250ba Guido Trotter
    return file_content
464 38e250ba Guido Trotter
465 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
466 38e250ba Guido Trotter
    """Save an instance's KVM runtime
467 38e250ba Guido Trotter

468 38e250ba Guido Trotter
    """
469 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
470 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
471 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
472 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
473 38e250ba Guido Trotter
474 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
475 38e250ba Guido Trotter
    """Load an instance's KVM runtime
476 38e250ba Guido Trotter

477 38e250ba Guido Trotter
    """
478 30e42c4e Guido Trotter
    if not serialized_runtime:
479 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
480 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
481 c2672466 Guido Trotter
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
482 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
483 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
484 38e250ba Guido Trotter
485 30e42c4e Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
486 ee5f20b0 Guido Trotter
    """Execute a KVM cmd, after completing it with some last minute data
487 ee5f20b0 Guido Trotter

488 30e42c4e Guido Trotter
    @type incoming: tuple of strings
489 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
490 30e42c4e Guido Trotter

491 ee5f20b0 Guido Trotter
    """
492 6e6bb8d5 Guido Trotter
    hvp = instance.hvparams
493 5905901c Iustin Pop
    name = instance.name
494 5905901c Iustin Pop
    self._CheckDown(name)
495 ee5f20b0 Guido Trotter
496 ee5f20b0 Guido Trotter
    temp_files = []
497 ee5f20b0 Guido Trotter
498 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
499 ee5f20b0 Guido Trotter
500 ee5f20b0 Guido Trotter
    if not kvm_nics:
501 ee5f20b0 Guido Trotter
      kvm_cmd.extend(['-net', 'none'])
502 ee5f20b0 Guido Trotter
    else:
503 37f88dc6 Guido Trotter
      nic_type = hvparams[constants.HV_NIC_TYPE]
504 37f88dc6 Guido Trotter
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
505 37f88dc6 Guido Trotter
        nic_model = "model=virtio"
506 37f88dc6 Guido Trotter
      else:
507 37f88dc6 Guido Trotter
        nic_model = "model=%s" % nic_type
508 37f88dc6 Guido Trotter
509 ee5f20b0 Guido Trotter
      for nic_seq, nic in enumerate(kvm_nics):
510 37f88dc6 Guido Trotter
        nic_val = "nic,macaddr=%s,%s" % (nic.mac, nic_model)
511 ee5f20b0 Guido Trotter
        script = self._WriteNetScript(instance, nic_seq, nic)
512 ee5f20b0 Guido Trotter
        kvm_cmd.extend(['-net', nic_val])
513 ee5f20b0 Guido Trotter
        kvm_cmd.extend(['-net', 'tap,script=%s' % script])
514 ee5f20b0 Guido Trotter
        temp_files.append(script)
515 ee5f20b0 Guido Trotter
516 30e42c4e Guido Trotter
    if incoming:
517 30e42c4e Guido Trotter
      target, port = incoming
518 30e42c4e Guido Trotter
      kvm_cmd.extend(['-incoming', 'tcp:%s:%s' % (target, port)])
519 30e42c4e Guido Trotter
520 6e6bb8d5 Guido Trotter
    vnc_pwd_file = hvp[constants.HV_VNC_PASSWORD_FILE]
521 6e6bb8d5 Guido Trotter
    vnc_pwd = None
522 6e6bb8d5 Guido Trotter
    if vnc_pwd_file:
523 6e6bb8d5 Guido Trotter
      try:
524 6e6bb8d5 Guido Trotter
        vnc_pwd = utils.ReadFile(vnc_pwd_file)
525 6e6bb8d5 Guido Trotter
      except EnvironmentError, err:
526 6e6bb8d5 Guido Trotter
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
527 6e6bb8d5 Guido Trotter
                                     % (vnc_pwd_file, err))
528 6e6bb8d5 Guido Trotter
529 eb58f9b1 Guido Trotter
    result = utils.RunCmd(kvm_cmd)
530 eb58f9b1 Guido Trotter
    if result.failed:
531 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
532 5905901c Iustin Pop
                                   (name, result.fail_reason, result.output))
533 eb58f9b1 Guido Trotter
534 5905901c Iustin Pop
    if not self._InstancePidAlive(name)[2]:
535 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s" % name)
536 eb58f9b1 Guido Trotter
537 6e6bb8d5 Guido Trotter
    if vnc_pwd:
538 6e6bb8d5 Guido Trotter
      change_cmd = 'change vnc password %s' % vnc_pwd
539 6e6bb8d5 Guido Trotter
      self._CallMonitorCommand(instance.name, change_cmd)
540 6e6bb8d5 Guido Trotter
541 08137f9e Iustin Pop
    for filename in temp_files:
542 08137f9e Iustin Pop
      utils.RemoveFile(filename)
543 eb58f9b1 Guido Trotter
544 07813a9e Iustin Pop
  def StartInstance(self, instance, block_devices):
545 ee5f20b0 Guido Trotter
    """Start an instance.
546 ee5f20b0 Guido Trotter

547 ee5f20b0 Guido Trotter
    """
548 5905901c Iustin Pop
    self._CheckDown(instance.name)
549 07813a9e Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices)
550 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
551 ee5f20b0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
552 ee5f20b0 Guido Trotter
553 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
554 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
555 6567aff3 Guido Trotter

556 6567aff3 Guido Trotter
    """
557 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
558 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
559 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
560 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
561 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
562 6567aff3 Guido Trotter
    if result.failed:
563 6567aff3 Guido Trotter
      msg = ("Failed to send command '%s' to instance %s."
564 6567aff3 Guido Trotter
             " output: %s, error: %s, fail_reason: %s" %
565 9798fcae Guido Trotter
             (command, instance_name,
566 9798fcae Guido Trotter
              result.stdout, result.stderr, result.fail_reason))
567 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
568 6567aff3 Guido Trotter
569 6567aff3 Guido Trotter
    return result
570 6567aff3 Guido Trotter
571 07b49e41 Guido Trotter
  def StopInstance(self, instance, force=False, retry=False):
572 eb58f9b1 Guido Trotter
    """Stop an instance.
573 eb58f9b1 Guido Trotter

574 eb58f9b1 Guido Trotter
    """
575 1f8b3a27 Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance.name)
576 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
577 6b5605e8 Iustin Pop
      if force or not instance.hvparams[constants.HV_ACPI]:
578 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
579 eb58f9b1 Guido Trotter
      else:
580 4ad45119 Guido Trotter
        self._CallMonitorCommand(instance.name, 'system_powerdown')
581 eb58f9b1 Guido Trotter
582 eb58f9b1 Guido Trotter
    if not utils.IsProcessAlive(pid):
583 7e66c35b Guido Trotter
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
584 6567aff3 Guido Trotter
      return True
585 6567aff3 Guido Trotter
    else:
586 6567aff3 Guido Trotter
      return False
587 eb58f9b1 Guido Trotter
588 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
589 eb58f9b1 Guido Trotter
    """Reboot an instance.
590 eb58f9b1 Guido Trotter

591 eb58f9b1 Guido Trotter
    """
592 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
593 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
594 eb58f9b1 Guido Trotter
    # to shutdown and restart.
595 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
596 1f8b3a27 Guido Trotter
    if not alive:
597 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
598 78411c60 Iustin Pop
                                   " not running" % instance.name)
599 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
600 f02881e0 Guido Trotter
    # ...first load it...
601 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
602 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
603 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
604 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
605 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
606 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
607 f02881e0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
608 eb58f9b1 Guido Trotter
609 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
610 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
611 30e42c4e Guido Trotter

612 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
613 30e42c4e Guido Trotter
    @param instance: instance to be migrated
614 30e42c4e Guido Trotter
    @rtype: string
615 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
616 30e42c4e Guido Trotter

617 30e42c4e Guido Trotter
    """
618 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
619 30e42c4e Guido Trotter
620 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
621 30e42c4e Guido Trotter
    """Prepare to accept an instance.
622 30e42c4e Guido Trotter

623 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
624 30e42c4e Guido Trotter
    @param instance: instance to be accepted
625 30e42c4e Guido Trotter
    @type info: string
626 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
627 30e42c4e Guido Trotter
    @type target: string
628 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
629 30e42c4e Guido Trotter

630 30e42c4e Guido Trotter
    """
631 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
632 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
633 30e42c4e Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
634 30e42c4e Guido Trotter
635 30e42c4e Guido Trotter
  def FinalizeMigration(self, instance, info, success):
636 30e42c4e Guido Trotter
    """Finalize an instance migration.
637 30e42c4e Guido Trotter

638 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
639 30e42c4e Guido Trotter

640 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
641 30e42c4e Guido Trotter
    @param instance: instance whose migration is being aborted
642 30e42c4e Guido Trotter

643 30e42c4e Guido Trotter
    """
644 30e42c4e Guido Trotter
    if success:
645 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
646 30e42c4e Guido Trotter
    else:
647 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
648 30e42c4e Guido Trotter
649 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
650 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
651 30e42c4e Guido Trotter

652 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
653 30e42c4e Guido Trotter
    currently running.
654 30e42c4e Guido Trotter

655 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
656 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
657 30e42c4e Guido Trotter
    @type target: string
658 30e42c4e Guido Trotter
    @param target: ip address of the target node
659 30e42c4e Guido Trotter
    @type live: boolean
660 30e42c4e Guido Trotter
    @param live: perform a live migration
661 30e42c4e Guido Trotter

662 30e42c4e Guido Trotter
    """
663 58d38b02 Iustin Pop
    instance_name = instance.name
664 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
665 30e42c4e Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
666 30e42c4e Guido Trotter
    if not alive:
667 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
668 30e42c4e Guido Trotter
669 50716be0 Iustin Pop
    if not utils.TcpPing(target, port, live_port_needed=True):
670 50716be0 Iustin Pop
      raise errors.HypervisorError("Remote host %s not listening on port"
671 50716be0 Iustin Pop
                                   " %s, cannot migrate" % (target, port))
672 50716be0 Iustin Pop
673 30e42c4e Guido Trotter
    if not live:
674 30e42c4e Guido Trotter
      self._CallMonitorCommand(instance_name, 'stop')
675 30e42c4e Guido Trotter
676 641ae041 Iustin Pop
    migrate_command = 'migrate -d tcp:%s:%s' % (target, port)
677 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
678 30e42c4e Guido Trotter
679 30e42c4e Guido Trotter
    info_command = 'info migrate'
680 30e42c4e Guido Trotter
    done = False
681 c4e388a5 Guido Trotter
    broken_answers = 0
682 30e42c4e Guido Trotter
    while not done:
683 30e42c4e Guido Trotter
      result = self._CallMonitorCommand(instance_name, info_command)
684 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
685 30e42c4e Guido Trotter
      if not match:
686 c4e388a5 Guido Trotter
        broken_answers += 1
687 c4e388a5 Guido Trotter
        if not result.stdout:
688 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
689 c4e388a5 Guido Trotter
        else:
690 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
691 c4e388a5 Guido Trotter
                          result.stdout)
692 c4e388a5 Guido Trotter
        time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
693 30e42c4e Guido Trotter
      else:
694 30e42c4e Guido Trotter
        status = match.group(1)
695 30e42c4e Guido Trotter
        if status == 'completed':
696 30e42c4e Guido Trotter
          done = True
697 30e42c4e Guido Trotter
        elif status == 'active':
698 c4e388a5 Guido Trotter
          # reset the broken answers count
699 c4e388a5 Guido Trotter
          broken_answers = 0
700 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
701 c087266c Guido Trotter
        elif status == 'failed' or status == 'cancelled':
702 c087266c Guido Trotter
          if not live:
703 c087266c Guido Trotter
            self._CallMonitorCommand(instance_name, 'cont')
704 c087266c Guido Trotter
          raise errors.HypervisorError("Migration %s at the kvm level" %
705 c087266c Guido Trotter
                                       status)
706 30e42c4e Guido Trotter
        else:
707 c4e388a5 Guido Trotter
          logging.warning("KVM: unknown migration status '%s'", status)
708 c4e388a5 Guido Trotter
          broken_answers += 1
709 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
710 c4e388a5 Guido Trotter
      if broken_answers >= self._MIGRATION_INFO_MAX_BAD_ANSWERS:
711 c4e388a5 Guido Trotter
        raise errors.HypervisorError("Too many 'info migrate' broken answers")
712 30e42c4e Guido Trotter
713 30e42c4e Guido Trotter
    utils.KillProcess(pid)
714 7b381438 Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
715 30e42c4e Guido Trotter
716 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
717 eb58f9b1 Guido Trotter
    """Return information about the node.
718 eb58f9b1 Guido Trotter

719 572e52bf Iustin Pop
    This is just a wrapper over the base GetLinuxNodeInfo method.
720 572e52bf Iustin Pop

721 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
722 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
723 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
724 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
725 eb58f9b1 Guido Trotter

726 eb58f9b1 Guido Trotter
    """
727 572e52bf Iustin Pop
    return self.GetLinuxNodeInfo()
728 eb58f9b1 Guido Trotter
729 637ce7f9 Guido Trotter
  @classmethod
730 5431b2e4 Guido Trotter
  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
731 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
732 eb58f9b1 Guido Trotter

733 eb58f9b1 Guido Trotter
    """
734 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
735 86d6bc2a Guido Trotter
      shell_command = ("%s STDIO,%s UNIX-CONNECT:%s" %
736 86d6bc2a Guido Trotter
                       (constants.SOCAT_PATH, cls._SocatUnixConsoleParams(),
737 a2faf9ee Guido Trotter
                        utils.ShellQuote(cls._InstanceSerial(instance.name))))
738 a2faf9ee Guido Trotter
    else:
739 a2faf9ee Guido Trotter
      shell_command = "echo 'No serial shell for instance %s'" % instance.name
740 3be34f57 Guido Trotter
741 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
742 3be34f57 Guido Trotter
    if vnc_bind_address:
743 377d74c9 Guido Trotter
      if instance.network_port > constants.VNC_BASE_PORT:
744 377d74c9 Guido Trotter
        display = instance.network_port - constants.VNC_BASE_PORT
745 3be34f57 Guido Trotter
        vnc_command = ("echo 'Instance has VNC listening on %s:%d"
746 3be34f57 Guido Trotter
                       " (display: %d)'" % (vnc_bind_address,
747 3be34f57 Guido Trotter
                                            instance.network_port,
748 3be34f57 Guido Trotter
                                            display))
749 3be34f57 Guido Trotter
        shell_command = "%s; %s" % (vnc_command, shell_command)
750 3be34f57 Guido Trotter
751 a2faf9ee Guido Trotter
    return shell_command
752 eb58f9b1 Guido Trotter
753 eb58f9b1 Guido Trotter
  def Verify(self):
754 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
755 eb58f9b1 Guido Trotter

756 eb58f9b1 Guido Trotter
    Check that the binary exists.
757 eb58f9b1 Guido Trotter

758 eb58f9b1 Guido Trotter
    """
759 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
760 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
761 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
762 14aa53cb Guido Trotter
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
763 14aa53cb Guido Trotter
764 6b5605e8 Iustin Pop
765 6b5605e8 Iustin Pop
  @classmethod
766 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
767 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
768 6b5605e8 Iustin Pop

769 6b5605e8 Iustin Pop
    @type hvparams:  dict
770 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
771 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
772 6b5605e8 Iustin Pop

773 6b5605e8 Iustin Pop
    """
774 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
775 6b5605e8 Iustin Pop
776 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
777 df5ab9f0 Guido Trotter
    if kernel_path:
778 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
779 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
780 205ab586 Iustin Pop
                                     " if a kernel is defined")
781 6b5605e8 Iustin Pop
782 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
783 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
784 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
785 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
786 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
787 66d5dbef Guido Trotter
788 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
789 66d5dbef Guido Trotter
790 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
791 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
792 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
793 835528af Iustin Pop
                                   " ISO path")
794 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_NETWORK and
795 205ab586 Iustin Pop
        hvparams[constants.HV_NIC_TYPE] == constants.HT_NIC_PARAVIRTUAL):
796 8745c3d7 Guido Trotter
      raise errors.HypervisorError("Cannot boot from a paravirtual NIC. Please"
797 835528af Iustin Pop
                                   " change the NIC type.")
798 f5118ade Iustin Pop
799 f5118ade Iustin Pop
  @classmethod
800 f5118ade Iustin Pop
  def PowercycleNode(cls):
801 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
802 f5118ade Iustin Pop

803 f5118ade Iustin Pop
    """
804 f5118ade Iustin Pop
    cls.LinuxPowercycle()