Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ fe5b0c42

History | View | Annotate | Download (27 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 205ab586 Iustin Pop
    }
78 6b5605e8 Iustin Pop
79 30e42c4e Guido Trotter
  _MIGRATION_STATUS_RE = re.compile('Migration\s+status:\s+(\w+)',
80 30e42c4e Guido Trotter
                                    re.M | re.I)
81 30e42c4e Guido Trotter
82 5420ffc9 Guido Trotter
  _KVM_NETWORK_SCRIPT = constants.SYSCONFDIR + "/ganeti/kvm-vif-bridge"
83 5420ffc9 Guido Trotter
84 64bfbc08 Guido Trotter
  ANCILLARY_FILES = [
85 64bfbc08 Guido Trotter
    _KVM_NETWORK_SCRIPT,
86 64bfbc08 Guido Trotter
    ]
87 64bfbc08 Guido Trotter
88 eb58f9b1 Guido Trotter
  def __init__(self):
89 eb58f9b1 Guido Trotter
    hv_base.BaseHypervisor.__init__(self)
90 eb58f9b1 Guido Trotter
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
91 eb58f9b1 Guido Trotter
    # in a tmpfs filesystem or has been otherwise wiped out.
92 29921401 Iustin Pop
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
93 9afb67fe Guido Trotter
    utils.EnsureDirs(dirs)
94 eb58f9b1 Guido Trotter
95 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
96 1f8b3a27 Guido Trotter
    """Returns the instance pid and pidfile
97 1f8b3a27 Guido Trotter

98 1f8b3a27 Guido Trotter
    """
99 1f8b3a27 Guido Trotter
    pidfile = "%s/%s" % (self._PIDS_DIR, instance_name)
100 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
101 1f8b3a27 Guido Trotter
    alive = utils.IsProcessAlive(pid)
102 1f8b3a27 Guido Trotter
103 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
104 1f8b3a27 Guido Trotter
105 0df4d98a Guido Trotter
  @classmethod
106 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
107 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
108 c4fbefc8 Guido Trotter

109 c4fbefc8 Guido Trotter
    """
110 0df4d98a Guido Trotter
    return '%s/%s.monitor' % (cls._CTRL_DIR, instance_name)
111 c4fbefc8 Guido Trotter
112 0df4d98a Guido Trotter
  @classmethod
113 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
114 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
115 c4fbefc8 Guido Trotter

116 c4fbefc8 Guido Trotter
    """
117 0df4d98a Guido Trotter
    return '%s/%s.serial' % (cls._CTRL_DIR, instance_name)
118 c4fbefc8 Guido Trotter
119 86d6bc2a Guido Trotter
  @staticmethod
120 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
121 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
122 86d6bc2a Guido Trotter

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

125 86d6bc2a Guido Trotter
    """
126 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
127 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
128 86d6bc2a Guido Trotter
    else:
129 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
130 86d6bc2a Guido Trotter
131 0df4d98a Guido Trotter
  @classmethod
132 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
133 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
134 38e250ba Guido Trotter

135 38e250ba Guido Trotter
    """
136 0df4d98a Guido Trotter
    return '%s/%s.runtime' % (cls._CONF_DIR, instance_name)
137 38e250ba Guido Trotter
138 7e66c35b Guido Trotter
  @classmethod
139 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
140 7e66c35b Guido Trotter
    """Removes an instance's rutime sockets/files.
141 7e66c35b Guido Trotter

142 7e66c35b Guido Trotter
    """
143 7e66c35b Guido Trotter
    utils.RemoveFile(pidfile)
144 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
145 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceSerial(instance_name))
146 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
147 7e66c35b Guido Trotter
148 eb58f9b1 Guido Trotter
  def _WriteNetScript(self, instance, seq, nic):
149 eb58f9b1 Guido Trotter
    """Write a script to connect a net interface to the proper bridge.
150 eb58f9b1 Guido Trotter

151 eb58f9b1 Guido Trotter
    This can be used by any qemu-type hypervisor.
152 eb58f9b1 Guido Trotter

153 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
154 eb58f9b1 Guido Trotter
    @type instance: instance object
155 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
156 eb58f9b1 Guido Trotter
    @type seq: int
157 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
158 eb58f9b1 Guido Trotter
    @type nic: nic object
159 eb58f9b1 Guido Trotter
    @return: netscript file name
160 eb58f9b1 Guido Trotter
    @rtype: string
161 eb58f9b1 Guido Trotter

162 eb58f9b1 Guido Trotter
    """
163 eb58f9b1 Guido Trotter
    script = StringIO()
164 eb58f9b1 Guido Trotter
    script.write("#!/bin/sh\n")
165 eb58f9b1 Guido Trotter
    script.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
166 eb58f9b1 Guido Trotter
    script.write("export INSTANCE=%s\n" % instance.name)
167 eb58f9b1 Guido Trotter
    script.write("export MAC=%s\n" % nic.mac)
168 bef9c750 Guido Trotter
    if nic.ip:
169 bef9c750 Guido Trotter
      script.write("export IP=%s\n" % nic.ip)
170 bef9c750 Guido Trotter
    script.write("export MODE=%s\n" % nic.nicparams[constants.NIC_MODE])
171 bef9c750 Guido Trotter
    if nic.nicparams[constants.NIC_LINK]:
172 bef9c750 Guido Trotter
      script.write("export LINK=%s\n" % nic.nicparams[constants.NIC_LINK])
173 bef9c750 Guido Trotter
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
174 bef9c750 Guido Trotter
      script.write("export BRIDGE=%s\n" % nic.nicparams[constants.NIC_LINK])
175 eb58f9b1 Guido Trotter
    script.write("export INTERFACE=$1\n")
176 eb58f9b1 Guido Trotter
    # TODO: make this configurable at ./configure time
177 5420ffc9 Guido Trotter
    script.write("if [ -x '%s' ]; then\n" % self._KVM_NETWORK_SCRIPT)
178 eb58f9b1 Guido Trotter
    script.write("  # Execute the user-specific vif file\n")
179 5420ffc9 Guido Trotter
    script.write("  %s\n" % self._KVM_NETWORK_SCRIPT)
180 eb58f9b1 Guido Trotter
    script.write("else\n")
181 eb58f9b1 Guido Trotter
    script.write("  /sbin/ifconfig $INTERFACE 0.0.0.0 up\n")
182 bef9c750 Guido Trotter
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
183 bef9c750 Guido Trotter
      script.write("  # Connect the interface to the bridge\n")
184 bef9c750 Guido Trotter
      script.write("  /usr/sbin/brctl addif $BRIDGE $INTERFACE\n")
185 bef9c750 Guido Trotter
    elif nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_ROUTED:
186 bef9c750 Guido Trotter
      script.write("  # Route traffic targeted at the IP to the interface\n")
187 7c60f7a2 Guido Trotter
      if nic.nicparams[constants.NIC_LINK]:
188 2c5afffb Guido Trotter
        script.write("  while /sbin/ip rule del dev $INTERFACE; do :; done\n")
189 2c5afffb Guido Trotter
        script.write("  /sbin/ip rule add dev $INTERFACE table $LINK\n")
190 8866ec86 Guido Trotter
        script.write("  /sbin/ip route replace $IP table $LINK proto static"
191 d63218ce Guido Trotter
                     " dev $INTERFACE\n")
192 7c60f7a2 Guido Trotter
      else:
193 8866ec86 Guido Trotter
        script.write("  /sbin/ip route replace $IP proto static"
194 8866ec86 Guido Trotter
                     " dev $INTERFACE\n")
195 e014f1d0 Guido Trotter
      interface_v4_conf = "/proc/sys/net/ipv4/conf/$INTERFACE"
196 e014f1d0 Guido Trotter
      interface_v6_conf = "/proc/sys/net/ipv6/conf/$INTERFACE"
197 e014f1d0 Guido Trotter
      script.write("  if [ -d %s ]; then\n" % interface_v4_conf)
198 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/proxy_arp\n" % interface_v4_conf)
199 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/forwarding\n" % interface_v4_conf)
200 e014f1d0 Guido Trotter
      script.write("  fi\n")
201 e014f1d0 Guido Trotter
      script.write("  if [ -d %s ]; then\n" % interface_v6_conf)
202 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/proxy_ndp\n" % interface_v6_conf)
203 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/forwarding\n" % interface_v6_conf)
204 e014f1d0 Guido Trotter
      script.write("  fi\n")
205 eb58f9b1 Guido Trotter
    script.write("fi\n\n")
206 eb58f9b1 Guido Trotter
    # As much as we'd like to put this in our _ROOT_DIR, that will happen to be
207 eb58f9b1 Guido Trotter
    # mounted noexec sometimes, so we'll have to find another place.
208 eb58f9b1 Guido Trotter
    (tmpfd, tmpfile_name) = tempfile.mkstemp()
209 eb58f9b1 Guido Trotter
    tmpfile = os.fdopen(tmpfd, 'w')
210 d73ef63f Michael Hanselmann
    try:
211 d73ef63f Michael Hanselmann
      tmpfile.write(script.getvalue())
212 d73ef63f Michael Hanselmann
    finally:
213 d73ef63f Michael Hanselmann
      tmpfile.close()
214 eb58f9b1 Guido Trotter
    os.chmod(tmpfile_name, 0755)
215 eb58f9b1 Guido Trotter
    return tmpfile_name
216 eb58f9b1 Guido Trotter
217 eb58f9b1 Guido Trotter
  def ListInstances(self):
218 eb58f9b1 Guido Trotter
    """Get the list of running instances.
219 eb58f9b1 Guido Trotter

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

223 eb58f9b1 Guido Trotter
    """
224 eb58f9b1 Guido Trotter
    result = []
225 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
226 08137f9e Iustin Pop
      filename = "%s/%s" % (self._PIDS_DIR, name)
227 08137f9e Iustin Pop
      if utils.IsProcessAlive(utils.ReadPidFile(filename)):
228 eb58f9b1 Guido Trotter
        result.append(name)
229 eb58f9b1 Guido Trotter
    return result
230 eb58f9b1 Guido Trotter
231 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
232 eb58f9b1 Guido Trotter
    """Get instance properties.
233 eb58f9b1 Guido Trotter

234 c41eea6e Iustin Pop
    @param instance_name: the instance name
235 c41eea6e Iustin Pop

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

238 eb58f9b1 Guido Trotter
    """
239 1f8b3a27 Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
240 1f8b3a27 Guido Trotter
    if not alive:
241 eb58f9b1 Guido Trotter
      return None
242 eb58f9b1 Guido Trotter
243 eb58f9b1 Guido Trotter
    cmdline_file = "/proc/%s/cmdline" % pid
244 eb58f9b1 Guido Trotter
    try:
245 1e37ad45 Michael Hanselmann
      cmdline = utils.ReadFile(cmdline_file)
246 90c024f6 Guido Trotter
    except EnvironmentError, err:
247 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to list instance %s: %s" %
248 eb58f9b1 Guido Trotter
                                   (instance_name, err))
249 eb58f9b1 Guido Trotter
250 eb58f9b1 Guido Trotter
    memory = 0
251 eb58f9b1 Guido Trotter
    vcpus = 0
252 eb58f9b1 Guido Trotter
    stat = "---b-"
253 eb58f9b1 Guido Trotter
    times = "0"
254 eb58f9b1 Guido Trotter
255 eb58f9b1 Guido Trotter
    arg_list = cmdline.split('\x00')
256 eb58f9b1 Guido Trotter
    while arg_list:
257 eb58f9b1 Guido Trotter
      arg =  arg_list.pop(0)
258 eb58f9b1 Guido Trotter
      if arg == '-m':
259 2a7e887b Guido Trotter
        memory = int(arg_list.pop(0))
260 eb58f9b1 Guido Trotter
      elif arg == '-smp':
261 2a7e887b Guido Trotter
        vcpus = int(arg_list.pop(0))
262 eb58f9b1 Guido Trotter
263 eb58f9b1 Guido Trotter
    return (instance_name, pid, memory, vcpus, stat, times)
264 eb58f9b1 Guido Trotter
265 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
266 eb58f9b1 Guido Trotter
    """Get properties of all instances.
267 eb58f9b1 Guido Trotter

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

270 eb58f9b1 Guido Trotter
    """
271 eb58f9b1 Guido Trotter
    data = []
272 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
273 08137f9e Iustin Pop
      filename = "%s/%s" % (self._PIDS_DIR, name)
274 08137f9e Iustin Pop
      if utils.IsProcessAlive(utils.ReadPidFile(filename)):
275 00ad5362 Guido Trotter
        try:
276 00ad5362 Guido Trotter
          info = self.GetInstanceInfo(name)
277 00ad5362 Guido Trotter
        except errors.HypervisorError, err:
278 00ad5362 Guido Trotter
          continue
279 00ad5362 Guido Trotter
        if info:
280 00ad5362 Guido Trotter
          data.append(info)
281 eb58f9b1 Guido Trotter
282 eb58f9b1 Guido Trotter
    return data
283 eb58f9b1 Guido Trotter
284 07813a9e Iustin Pop
  def _GenerateKVMRuntime(self, instance, block_devices):
285 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
286 eb58f9b1 Guido Trotter

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

419 38e250ba Guido Trotter
    """
420 38e250ba Guido Trotter
    try:
421 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
422 38e250ba Guido Trotter
                      data=data)
423 90c024f6 Guido Trotter
    except EnvironmentError, err:
424 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
425 38e250ba Guido Trotter
426 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
427 38e250ba Guido Trotter
    """Read an instance's KVM runtime
428 38e250ba Guido Trotter

429 38e250ba Guido Trotter
    """
430 38e250ba Guido Trotter
    try:
431 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
432 90c024f6 Guido Trotter
    except EnvironmentError, err:
433 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
434 38e250ba Guido Trotter
    return file_content
435 38e250ba Guido Trotter
436 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
437 38e250ba Guido Trotter
    """Save an instance's KVM runtime
438 38e250ba Guido Trotter

439 38e250ba Guido Trotter
    """
440 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
441 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
442 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
443 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
444 38e250ba Guido Trotter
445 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
446 38e250ba Guido Trotter
    """Load an instance's KVM runtime
447 38e250ba Guido Trotter

448 38e250ba Guido Trotter
    """
449 30e42c4e Guido Trotter
    if not serialized_runtime:
450 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
451 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
452 c2672466 Guido Trotter
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
453 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
454 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
455 38e250ba Guido Trotter
456 30e42c4e Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
457 ee5f20b0 Guido Trotter
    """Execute a KVM cmd, after completing it with some last minute data
458 ee5f20b0 Guido Trotter

459 30e42c4e Guido Trotter
    @type incoming: tuple of strings
460 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
461 30e42c4e Guido Trotter

462 ee5f20b0 Guido Trotter
    """
463 1f8b3a27 Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance.name)
464 6e6bb8d5 Guido Trotter
    hvp = instance.hvparams
465 1f8b3a27 Guido Trotter
    if alive:
466 ee5f20b0 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s" %
467 ee5f20b0 Guido Trotter
                                   (instance.name, "already running"))
468 ee5f20b0 Guido Trotter
469 ee5f20b0 Guido Trotter
    temp_files = []
470 ee5f20b0 Guido Trotter
471 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
472 ee5f20b0 Guido Trotter
473 ee5f20b0 Guido Trotter
    if not kvm_nics:
474 ee5f20b0 Guido Trotter
      kvm_cmd.extend(['-net', 'none'])
475 ee5f20b0 Guido Trotter
    else:
476 37f88dc6 Guido Trotter
      nic_type = hvparams[constants.HV_NIC_TYPE]
477 37f88dc6 Guido Trotter
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
478 37f88dc6 Guido Trotter
        nic_model = "model=virtio"
479 37f88dc6 Guido Trotter
      else:
480 37f88dc6 Guido Trotter
        nic_model = "model=%s" % nic_type
481 37f88dc6 Guido Trotter
482 ee5f20b0 Guido Trotter
      for nic_seq, nic in enumerate(kvm_nics):
483 37f88dc6 Guido Trotter
        nic_val = "nic,macaddr=%s,%s" % (nic.mac, nic_model)
484 ee5f20b0 Guido Trotter
        script = self._WriteNetScript(instance, nic_seq, nic)
485 ee5f20b0 Guido Trotter
        kvm_cmd.extend(['-net', nic_val])
486 ee5f20b0 Guido Trotter
        kvm_cmd.extend(['-net', 'tap,script=%s' % script])
487 ee5f20b0 Guido Trotter
        temp_files.append(script)
488 ee5f20b0 Guido Trotter
489 30e42c4e Guido Trotter
    if incoming:
490 30e42c4e Guido Trotter
      target, port = incoming
491 30e42c4e Guido Trotter
      kvm_cmd.extend(['-incoming', 'tcp:%s:%s' % (target, port)])
492 30e42c4e Guido Trotter
493 6e6bb8d5 Guido Trotter
    vnc_pwd_file = hvp[constants.HV_VNC_PASSWORD_FILE]
494 6e6bb8d5 Guido Trotter
    vnc_pwd = None
495 6e6bb8d5 Guido Trotter
    if vnc_pwd_file:
496 6e6bb8d5 Guido Trotter
      try:
497 6e6bb8d5 Guido Trotter
        vnc_pwd = utils.ReadFile(vnc_pwd_file)
498 6e6bb8d5 Guido Trotter
      except EnvironmentError, err:
499 6e6bb8d5 Guido Trotter
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
500 6e6bb8d5 Guido Trotter
                                     % (vnc_pwd_file, err))
501 6e6bb8d5 Guido Trotter
502 eb58f9b1 Guido Trotter
    result = utils.RunCmd(kvm_cmd)
503 eb58f9b1 Guido Trotter
    if result.failed:
504 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
505 eb58f9b1 Guido Trotter
                                   (instance.name, result.fail_reason,
506 eb58f9b1 Guido Trotter
                                    result.output))
507 eb58f9b1 Guido Trotter
508 eb58f9b1 Guido Trotter
    if not utils.IsProcessAlive(utils.ReadPidFile(pidfile)):
509 88df4f39 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" %
510 eb58f9b1 Guido Trotter
                                   (instance.name))
511 eb58f9b1 Guido Trotter
512 6e6bb8d5 Guido Trotter
    if vnc_pwd:
513 6e6bb8d5 Guido Trotter
      change_cmd = 'change vnc password %s' % vnc_pwd
514 6e6bb8d5 Guido Trotter
      self._CallMonitorCommand(instance.name, change_cmd)
515 6e6bb8d5 Guido Trotter
516 08137f9e Iustin Pop
    for filename in temp_files:
517 08137f9e Iustin Pop
      utils.RemoveFile(filename)
518 eb58f9b1 Guido Trotter
519 07813a9e Iustin Pop
  def StartInstance(self, instance, block_devices):
520 ee5f20b0 Guido Trotter
    """Start an instance.
521 ee5f20b0 Guido Trotter

522 ee5f20b0 Guido Trotter
    """
523 1f8b3a27 Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance.name)
524 1f8b3a27 Guido Trotter
    if alive:
525 ee5f20b0 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s" %
526 ee5f20b0 Guido Trotter
                                   (instance.name, "already running"))
527 ee5f20b0 Guido Trotter
528 07813a9e Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices)
529 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
530 ee5f20b0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
531 ee5f20b0 Guido Trotter
532 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
533 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
534 6567aff3 Guido Trotter

535 6567aff3 Guido Trotter
    """
536 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
537 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
538 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
539 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
540 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
541 6567aff3 Guido Trotter
    if result.failed:
542 6567aff3 Guido Trotter
      msg = ("Failed to send command '%s' to instance %s."
543 6567aff3 Guido Trotter
             " output: %s, error: %s, fail_reason: %s" %
544 9798fcae Guido Trotter
             (command, instance_name,
545 9798fcae Guido Trotter
              result.stdout, result.stderr, result.fail_reason))
546 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
547 6567aff3 Guido Trotter
548 6567aff3 Guido Trotter
    return result
549 6567aff3 Guido Trotter
550 07b49e41 Guido Trotter
  def StopInstance(self, instance, force=False, retry=False):
551 eb58f9b1 Guido Trotter
    """Stop an instance.
552 eb58f9b1 Guido Trotter

553 eb58f9b1 Guido Trotter
    """
554 1f8b3a27 Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance.name)
555 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
556 6b5605e8 Iustin Pop
      if force or not instance.hvparams[constants.HV_ACPI]:
557 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
558 eb58f9b1 Guido Trotter
      else:
559 4ad45119 Guido Trotter
        self._CallMonitorCommand(instance.name, 'system_powerdown')
560 eb58f9b1 Guido Trotter
561 eb58f9b1 Guido Trotter
    if not utils.IsProcessAlive(pid):
562 7e66c35b Guido Trotter
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
563 6567aff3 Guido Trotter
      return True
564 6567aff3 Guido Trotter
    else:
565 6567aff3 Guido Trotter
      return False
566 eb58f9b1 Guido Trotter
567 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
568 eb58f9b1 Guido Trotter
    """Reboot an instance.
569 eb58f9b1 Guido Trotter

570 eb58f9b1 Guido Trotter
    """
571 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
572 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
573 eb58f9b1 Guido Trotter
    # to shutdown and restart.
574 1f8b3a27 Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance.name)
575 1f8b3a27 Guido Trotter
    if not alive:
576 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
577 78411c60 Iustin Pop
                                   " not running" % instance.name)
578 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
579 f02881e0 Guido Trotter
    # ...first load it...
580 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
581 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
582 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
583 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
584 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
585 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
586 f02881e0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
587 eb58f9b1 Guido Trotter
588 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
589 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
590 30e42c4e Guido Trotter

591 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
592 30e42c4e Guido Trotter
    @param instance: instance to be migrated
593 30e42c4e Guido Trotter
    @rtype: string
594 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
595 30e42c4e Guido Trotter

596 30e42c4e Guido Trotter
    """
597 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
598 30e42c4e Guido Trotter
599 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
600 30e42c4e Guido Trotter
    """Prepare to accept an instance.
601 30e42c4e Guido Trotter

602 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
603 30e42c4e Guido Trotter
    @param instance: instance to be accepted
604 30e42c4e Guido Trotter
    @type info: string
605 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
606 30e42c4e Guido Trotter
    @type target: string
607 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
608 30e42c4e Guido Trotter

609 30e42c4e Guido Trotter
    """
610 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
611 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
612 30e42c4e Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
613 30e42c4e Guido Trotter
614 30e42c4e Guido Trotter
  def FinalizeMigration(self, instance, info, success):
615 30e42c4e Guido Trotter
    """Finalize an instance migration.
616 30e42c4e Guido Trotter

617 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
618 30e42c4e Guido Trotter

619 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
620 30e42c4e Guido Trotter
    @param instance: instance whose migration is being aborted
621 30e42c4e Guido Trotter

622 30e42c4e Guido Trotter
    """
623 30e42c4e Guido Trotter
    if success:
624 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
625 30e42c4e Guido Trotter
    else:
626 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
627 30e42c4e Guido Trotter
628 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
629 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
630 30e42c4e Guido Trotter

631 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
632 30e42c4e Guido Trotter
    currently running.
633 30e42c4e Guido Trotter

634 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
635 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
636 30e42c4e Guido Trotter
    @type target: string
637 30e42c4e Guido Trotter
    @param target: ip address of the target node
638 30e42c4e Guido Trotter
    @type live: boolean
639 30e42c4e Guido Trotter
    @param live: perform a live migration
640 30e42c4e Guido Trotter

641 30e42c4e Guido Trotter
    """
642 58d38b02 Iustin Pop
    instance_name = instance.name
643 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
644 30e42c4e Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
645 30e42c4e Guido Trotter
    if not alive:
646 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
647 30e42c4e Guido Trotter
648 50716be0 Iustin Pop
    if not utils.TcpPing(target, port, live_port_needed=True):
649 50716be0 Iustin Pop
      raise errors.HypervisorError("Remote host %s not listening on port"
650 50716be0 Iustin Pop
                                   " %s, cannot migrate" % (target, port))
651 50716be0 Iustin Pop
652 30e42c4e Guido Trotter
    if not live:
653 30e42c4e Guido Trotter
      self._CallMonitorCommand(instance_name, 'stop')
654 30e42c4e Guido Trotter
655 641ae041 Iustin Pop
    migrate_command = 'migrate -d tcp:%s:%s' % (target, port)
656 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
657 30e42c4e Guido Trotter
658 30e42c4e Guido Trotter
    info_command = 'info migrate'
659 30e42c4e Guido Trotter
    done = False
660 30e42c4e Guido Trotter
    while not done:
661 30e42c4e Guido Trotter
      result = self._CallMonitorCommand(instance_name, info_command)
662 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
663 30e42c4e Guido Trotter
      if not match:
664 30e42c4e Guido Trotter
        raise errors.HypervisorError("Unknown 'info migrate' result: %s" %
665 30e42c4e Guido Trotter
                                     result.stdout)
666 30e42c4e Guido Trotter
      else:
667 30e42c4e Guido Trotter
        status = match.group(1)
668 30e42c4e Guido Trotter
        if status == 'completed':
669 30e42c4e Guido Trotter
          done = True
670 30e42c4e Guido Trotter
        elif status == 'active':
671 30e42c4e Guido Trotter
          time.sleep(2)
672 c087266c Guido Trotter
        elif status == 'failed' or status == 'cancelled':
673 c087266c Guido Trotter
          if not live:
674 c087266c Guido Trotter
            self._CallMonitorCommand(instance_name, 'cont')
675 c087266c Guido Trotter
          raise errors.HypervisorError("Migration %s at the kvm level" %
676 c087266c Guido Trotter
                                       status)
677 30e42c4e Guido Trotter
        else:
678 30e42c4e Guido Trotter
          logging.info("KVM: unknown migration status '%s'" % status)
679 30e42c4e Guido Trotter
          time.sleep(2)
680 30e42c4e Guido Trotter
681 30e42c4e Guido Trotter
    utils.KillProcess(pid)
682 7b381438 Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
683 30e42c4e Guido Trotter
684 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
685 eb58f9b1 Guido Trotter
    """Return information about the node.
686 eb58f9b1 Guido Trotter

687 572e52bf Iustin Pop
    This is just a wrapper over the base GetLinuxNodeInfo method.
688 572e52bf Iustin Pop

689 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
690 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
691 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
692 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
693 eb58f9b1 Guido Trotter

694 eb58f9b1 Guido Trotter
    """
695 572e52bf Iustin Pop
    return self.GetLinuxNodeInfo()
696 eb58f9b1 Guido Trotter
697 637ce7f9 Guido Trotter
  @classmethod
698 5431b2e4 Guido Trotter
  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
699 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
700 eb58f9b1 Guido Trotter

701 eb58f9b1 Guido Trotter
    """
702 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
703 86d6bc2a Guido Trotter
      shell_command = ("%s STDIO,%s UNIX-CONNECT:%s" %
704 86d6bc2a Guido Trotter
                       (constants.SOCAT_PATH, cls._SocatUnixConsoleParams(),
705 a2faf9ee Guido Trotter
                        utils.ShellQuote(cls._InstanceSerial(instance.name))))
706 a2faf9ee Guido Trotter
    else:
707 a2faf9ee Guido Trotter
      shell_command = "echo 'No serial shell for instance %s'" % instance.name
708 3be34f57 Guido Trotter
709 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
710 3be34f57 Guido Trotter
    if vnc_bind_address:
711 377d74c9 Guido Trotter
      if instance.network_port > constants.VNC_BASE_PORT:
712 377d74c9 Guido Trotter
        display = instance.network_port - constants.VNC_BASE_PORT
713 3be34f57 Guido Trotter
        vnc_command = ("echo 'Instance has VNC listening on %s:%d"
714 3be34f57 Guido Trotter
                       " (display: %d)'" % (vnc_bind_address,
715 3be34f57 Guido Trotter
                                            instance.network_port,
716 3be34f57 Guido Trotter
                                            display))
717 3be34f57 Guido Trotter
        shell_command = "%s; %s" % (vnc_command, shell_command)
718 3be34f57 Guido Trotter
719 a2faf9ee Guido Trotter
    return shell_command
720 eb58f9b1 Guido Trotter
721 eb58f9b1 Guido Trotter
  def Verify(self):
722 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
723 eb58f9b1 Guido Trotter

724 eb58f9b1 Guido Trotter
    Check that the binary exists.
725 eb58f9b1 Guido Trotter

726 eb58f9b1 Guido Trotter
    """
727 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
728 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
729 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
730 14aa53cb Guido Trotter
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
731 14aa53cb Guido Trotter
732 6b5605e8 Iustin Pop
733 6b5605e8 Iustin Pop
  @classmethod
734 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
735 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
736 6b5605e8 Iustin Pop

737 6b5605e8 Iustin Pop
    @type hvparams:  dict
738 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
739 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
740 6b5605e8 Iustin Pop

741 6b5605e8 Iustin Pop
    """
742 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
743 6b5605e8 Iustin Pop
744 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
745 df5ab9f0 Guido Trotter
    if kernel_path:
746 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
747 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
748 205ab586 Iustin Pop
                                     " if a kernel is defined")
749 6b5605e8 Iustin Pop
750 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
751 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
752 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
753 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
754 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
755 66d5dbef Guido Trotter
756 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
757 66d5dbef Guido Trotter
758 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
759 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
760 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
761 835528af Iustin Pop
                                   " ISO path")
762 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_NETWORK and
763 205ab586 Iustin Pop
        hvparams[constants.HV_NIC_TYPE] == constants.HT_NIC_PARAVIRTUAL):
764 8745c3d7 Guido Trotter
      raise errors.HypervisorError("Cannot boot from a paravirtual NIC. Please"
765 835528af Iustin Pop
                                   " change the NIC type.")
766 f5118ade Iustin Pop
767 f5118ade Iustin Pop
  @classmethod
768 f5118ade Iustin Pop
  def PowercycleNode(cls):
769 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
770 f5118ade Iustin Pop

771 f5118ade Iustin Pop
    """
772 f5118ade Iustin Pop
    cls.LinuxPowercycle()