Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ e4dd2299

History | View | Annotate | Download (27.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 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 98ec75d6 Iustin Pop
  def _InstancePidFile(self, instance_name):
100 98ec75d6 Iustin Pop
    """Returns the instance pidfile.
101 98ec75d6 Iustin Pop

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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