Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 9b94905f

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

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

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

114 c4fbefc8 Guido Trotter
    """
115 0df4d98a Guido Trotter
    return '%s/%s.serial' % (cls._CTRL_DIR, instance_name)
116 c4fbefc8 Guido Trotter
117 0df4d98a Guido Trotter
  @classmethod
118 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
119 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
120 38e250ba Guido Trotter

121 38e250ba Guido Trotter
    """
122 0df4d98a Guido Trotter
    return '%s/%s.runtime' % (cls._CONF_DIR, instance_name)
123 38e250ba Guido Trotter
124 7e66c35b Guido Trotter
  @classmethod
125 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
126 7e66c35b Guido Trotter
    """Removes an instance's rutime sockets/files.
127 7e66c35b Guido Trotter

128 7e66c35b Guido Trotter
    """
129 7e66c35b Guido Trotter
    utils.RemoveFile(pidfile)
130 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
131 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceSerial(instance_name))
132 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
133 7e66c35b Guido Trotter
134 eb58f9b1 Guido Trotter
  def _WriteNetScript(self, instance, seq, nic):
135 eb58f9b1 Guido Trotter
    """Write a script to connect a net interface to the proper bridge.
136 eb58f9b1 Guido Trotter

137 eb58f9b1 Guido Trotter
    This can be used by any qemu-type hypervisor.
138 eb58f9b1 Guido Trotter

139 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
140 eb58f9b1 Guido Trotter
    @type instance: instance object
141 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
142 eb58f9b1 Guido Trotter
    @type seq: int
143 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
144 eb58f9b1 Guido Trotter
    @type nic: nic object
145 eb58f9b1 Guido Trotter
    @return: netscript file name
146 eb58f9b1 Guido Trotter
    @rtype: string
147 eb58f9b1 Guido Trotter

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

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

209 eb58f9b1 Guido Trotter
    """
210 eb58f9b1 Guido Trotter
    result = []
211 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
212 08137f9e Iustin Pop
      filename = "%s/%s" % (self._PIDS_DIR, name)
213 08137f9e Iustin Pop
      if utils.IsProcessAlive(utils.ReadPidFile(filename)):
214 eb58f9b1 Guido Trotter
        result.append(name)
215 eb58f9b1 Guido Trotter
    return result
216 eb58f9b1 Guido Trotter
217 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
218 eb58f9b1 Guido Trotter
    """Get instance properties.
219 eb58f9b1 Guido Trotter

220 c41eea6e Iustin Pop
    @param instance_name: the instance name
221 c41eea6e Iustin Pop

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

224 eb58f9b1 Guido Trotter
    """
225 1f8b3a27 Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
226 1f8b3a27 Guido Trotter
    if not alive:
227 eb58f9b1 Guido Trotter
      return None
228 eb58f9b1 Guido Trotter
229 eb58f9b1 Guido Trotter
    cmdline_file = "/proc/%s/cmdline" % pid
230 eb58f9b1 Guido Trotter
    try:
231 1e37ad45 Michael Hanselmann
      cmdline = utils.ReadFile(cmdline_file)
232 90c024f6 Guido Trotter
    except EnvironmentError, err:
233 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to list instance %s: %s" %
234 eb58f9b1 Guido Trotter
                                   (instance_name, err))
235 eb58f9b1 Guido Trotter
236 eb58f9b1 Guido Trotter
    memory = 0
237 eb58f9b1 Guido Trotter
    vcpus = 0
238 eb58f9b1 Guido Trotter
    stat = "---b-"
239 eb58f9b1 Guido Trotter
    times = "0"
240 eb58f9b1 Guido Trotter
241 eb58f9b1 Guido Trotter
    arg_list = cmdline.split('\x00')
242 eb58f9b1 Guido Trotter
    while arg_list:
243 eb58f9b1 Guido Trotter
      arg =  arg_list.pop(0)
244 eb58f9b1 Guido Trotter
      if arg == '-m':
245 2a7e887b Guido Trotter
        memory = int(arg_list.pop(0))
246 eb58f9b1 Guido Trotter
      elif arg == '-smp':
247 2a7e887b Guido Trotter
        vcpus = int(arg_list.pop(0))
248 eb58f9b1 Guido Trotter
249 eb58f9b1 Guido Trotter
    return (instance_name, pid, memory, vcpus, stat, times)
250 eb58f9b1 Guido Trotter
251 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
252 eb58f9b1 Guido Trotter
    """Get properties of all instances.
253 eb58f9b1 Guido Trotter

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

256 eb58f9b1 Guido Trotter
    """
257 eb58f9b1 Guido Trotter
    data = []
258 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
259 08137f9e Iustin Pop
      filename = "%s/%s" % (self._PIDS_DIR, name)
260 08137f9e Iustin Pop
      if utils.IsProcessAlive(utils.ReadPidFile(filename)):
261 00ad5362 Guido Trotter
        try:
262 00ad5362 Guido Trotter
          info = self.GetInstanceInfo(name)
263 00ad5362 Guido Trotter
        except errors.HypervisorError, err:
264 00ad5362 Guido Trotter
          continue
265 00ad5362 Guido Trotter
        if info:
266 00ad5362 Guido Trotter
          data.append(info)
267 eb58f9b1 Guido Trotter
268 eb58f9b1 Guido Trotter
    return data
269 eb58f9b1 Guido Trotter
270 07813a9e Iustin Pop
  def _GenerateKVMRuntime(self, instance, block_devices):
271 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
272 eb58f9b1 Guido Trotter

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

402 38e250ba Guido Trotter
    """
403 38e250ba Guido Trotter
    try:
404 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
405 38e250ba Guido Trotter
                      data=data)
406 90c024f6 Guido Trotter
    except EnvironmentError, err:
407 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
408 38e250ba Guido Trotter
409 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
410 38e250ba Guido Trotter
    """Read an instance's KVM runtime
411 38e250ba Guido Trotter

412 38e250ba Guido Trotter
    """
413 38e250ba Guido Trotter
    try:
414 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
415 90c024f6 Guido Trotter
    except EnvironmentError, err:
416 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
417 38e250ba Guido Trotter
    return file_content
418 38e250ba Guido Trotter
419 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
420 38e250ba Guido Trotter
    """Save an instance's KVM runtime
421 38e250ba Guido Trotter

422 38e250ba Guido Trotter
    """
423 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
424 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
425 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
426 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
427 38e250ba Guido Trotter
428 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
429 38e250ba Guido Trotter
    """Load an instance's KVM runtime
430 38e250ba Guido Trotter

431 38e250ba Guido Trotter
    """
432 30e42c4e Guido Trotter
    if not serialized_runtime:
433 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
434 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
435 c2672466 Guido Trotter
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
436 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
437 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
438 38e250ba Guido Trotter
439 30e42c4e Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
440 ee5f20b0 Guido Trotter
    """Execute a KVM cmd, after completing it with some last minute data
441 ee5f20b0 Guido Trotter

442 30e42c4e Guido Trotter
    @type incoming: tuple of strings
443 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
444 30e42c4e Guido Trotter

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

505 ee5f20b0 Guido Trotter
    """
506 1f8b3a27 Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance.name)
507 1f8b3a27 Guido Trotter
    if alive:
508 ee5f20b0 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s" %
509 ee5f20b0 Guido Trotter
                                   (instance.name, "already running"))
510 ee5f20b0 Guido Trotter
511 07813a9e Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices)
512 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
513 ee5f20b0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
514 ee5f20b0 Guido Trotter
515 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
516 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
517 6567aff3 Guido Trotter

518 6567aff3 Guido Trotter
    """
519 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
520 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
521 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
522 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
523 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
524 6567aff3 Guido Trotter
    if result.failed:
525 6567aff3 Guido Trotter
      msg = ("Failed to send command '%s' to instance %s."
526 6567aff3 Guido Trotter
             " output: %s, error: %s, fail_reason: %s" %
527 9798fcae Guido Trotter
             (command, instance_name,
528 9798fcae Guido Trotter
              result.stdout, result.stderr, result.fail_reason))
529 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
530 6567aff3 Guido Trotter
531 6567aff3 Guido Trotter
    return result
532 6567aff3 Guido Trotter
533 07b49e41 Guido Trotter
  def StopInstance(self, instance, force=False, retry=False):
534 eb58f9b1 Guido Trotter
    """Stop an instance.
535 eb58f9b1 Guido Trotter

536 eb58f9b1 Guido Trotter
    """
537 1f8b3a27 Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance.name)
538 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
539 6b5605e8 Iustin Pop
      if force or not instance.hvparams[constants.HV_ACPI]:
540 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
541 eb58f9b1 Guido Trotter
      else:
542 4ad45119 Guido Trotter
        self._CallMonitorCommand(instance.name, 'system_powerdown')
543 eb58f9b1 Guido Trotter
544 eb58f9b1 Guido Trotter
    if not utils.IsProcessAlive(pid):
545 7e66c35b Guido Trotter
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
546 6567aff3 Guido Trotter
      return True
547 6567aff3 Guido Trotter
    else:
548 6567aff3 Guido Trotter
      return False
549 eb58f9b1 Guido Trotter
550 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
551 eb58f9b1 Guido Trotter
    """Reboot an instance.
552 eb58f9b1 Guido Trotter

553 eb58f9b1 Guido Trotter
    """
554 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
555 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
556 eb58f9b1 Guido Trotter
    # to shutdown and restart.
557 1f8b3a27 Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance.name)
558 1f8b3a27 Guido Trotter
    if not alive:
559 1f8b3a27 Guido Trotter
      raise errors.HypervisorError("Failed to reboot instance %s: not running" %
560 1f8b3a27 Guido Trotter
                                             (instance.name))
561 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
562 f02881e0 Guido Trotter
    # ...first load it...
563 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
564 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
565 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
566 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
567 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
568 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
569 f02881e0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
570 eb58f9b1 Guido Trotter
571 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
572 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
573 30e42c4e Guido Trotter

574 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
575 30e42c4e Guido Trotter
    @param instance: instance to be migrated
576 30e42c4e Guido Trotter
    @rtype: string
577 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
578 30e42c4e Guido Trotter

579 30e42c4e Guido Trotter
    """
580 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
581 30e42c4e Guido Trotter
582 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
583 30e42c4e Guido Trotter
    """Prepare to accept an instance.
584 30e42c4e Guido Trotter

585 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
586 30e42c4e Guido Trotter
    @param instance: instance to be accepted
587 30e42c4e Guido Trotter
    @type info: string
588 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
589 30e42c4e Guido Trotter
    @type target: string
590 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
591 30e42c4e Guido Trotter

592 30e42c4e Guido Trotter
    """
593 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
594 30e42c4e Guido Trotter
    incoming_address = (target, constants.KVM_MIGRATION_PORT)
595 30e42c4e Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
596 30e42c4e Guido Trotter
597 30e42c4e Guido Trotter
  def FinalizeMigration(self, instance, info, success):
598 30e42c4e Guido Trotter
    """Finalize an instance migration.
599 30e42c4e Guido Trotter

600 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
601 30e42c4e Guido Trotter

602 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
603 30e42c4e Guido Trotter
    @param instance: instance whose migration is being aborted
604 30e42c4e Guido Trotter

605 30e42c4e Guido Trotter
    """
606 30e42c4e Guido Trotter
    if success:
607 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
608 30e42c4e Guido Trotter
    else:
609 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
610 30e42c4e Guido Trotter
611 30e42c4e Guido Trotter
  def MigrateInstance(self, instance_name, target, live):
612 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
613 30e42c4e Guido Trotter

614 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
615 30e42c4e Guido Trotter
    currently running.
616 30e42c4e Guido Trotter

617 30e42c4e Guido Trotter
    @type instance_name: string
618 30e42c4e Guido Trotter
    @param instance_name: name of the instance to be migrated
619 30e42c4e Guido Trotter
    @type target: string
620 30e42c4e Guido Trotter
    @param target: ip address of the target node
621 30e42c4e Guido Trotter
    @type live: boolean
622 30e42c4e Guido Trotter
    @param live: perform a live migration
623 30e42c4e Guido Trotter

624 30e42c4e Guido Trotter
    """
625 30e42c4e Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
626 30e42c4e Guido Trotter
    if not alive:
627 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
628 30e42c4e Guido Trotter
629 30e42c4e Guido Trotter
    if not live:
630 30e42c4e Guido Trotter
      self._CallMonitorCommand(instance_name, 'stop')
631 30e42c4e Guido Trotter
632 30e42c4e Guido Trotter
    migrate_command = ('migrate -d tcp:%s:%s' %
633 30e42c4e Guido Trotter
                       (target, constants.KVM_MIGRATION_PORT))
634 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
635 30e42c4e Guido Trotter
636 30e42c4e Guido Trotter
    info_command = 'info migrate'
637 30e42c4e Guido Trotter
    done = False
638 30e42c4e Guido Trotter
    while not done:
639 30e42c4e Guido Trotter
      result = self._CallMonitorCommand(instance_name, info_command)
640 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
641 30e42c4e Guido Trotter
      if not match:
642 30e42c4e Guido Trotter
        raise errors.HypervisorError("Unknown 'info migrate' result: %s" %
643 30e42c4e Guido Trotter
                                     result.stdout)
644 30e42c4e Guido Trotter
      else:
645 30e42c4e Guido Trotter
        status = match.group(1)
646 30e42c4e Guido Trotter
        if status == 'completed':
647 30e42c4e Guido Trotter
          done = True
648 30e42c4e Guido Trotter
        elif status == 'active':
649 30e42c4e Guido Trotter
          time.sleep(2)
650 c087266c Guido Trotter
        elif status == 'failed' or status == 'cancelled':
651 c087266c Guido Trotter
          if not live:
652 c087266c Guido Trotter
            self._CallMonitorCommand(instance_name, 'cont')
653 c087266c Guido Trotter
          raise errors.HypervisorError("Migration %s at the kvm level" %
654 c087266c Guido Trotter
                                       status)
655 30e42c4e Guido Trotter
        else:
656 30e42c4e Guido Trotter
          logging.info("KVM: unknown migration status '%s'" % status)
657 30e42c4e Guido Trotter
          time.sleep(2)
658 30e42c4e Guido Trotter
659 30e42c4e Guido Trotter
    utils.KillProcess(pid)
660 7b381438 Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
661 30e42c4e Guido Trotter
662 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
663 eb58f9b1 Guido Trotter
    """Return information about the node.
664 eb58f9b1 Guido Trotter

665 572e52bf Iustin Pop
    This is just a wrapper over the base GetLinuxNodeInfo method.
666 572e52bf Iustin Pop

667 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
668 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
669 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
670 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
671 eb58f9b1 Guido Trotter

672 eb58f9b1 Guido Trotter
    """
673 572e52bf Iustin Pop
    return self.GetLinuxNodeInfo()
674 eb58f9b1 Guido Trotter
675 637ce7f9 Guido Trotter
  @classmethod
676 5431b2e4 Guido Trotter
  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
677 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
678 eb58f9b1 Guido Trotter

679 eb58f9b1 Guido Trotter
    """
680 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
681 a2faf9ee Guido Trotter
      # FIXME: The socat shell is not perfect. In particular the way we start
682 a2faf9ee Guido Trotter
      # it ctrl+c will close it, rather than being passed to the other end.
683 a2faf9ee Guido Trotter
      # On the other hand if we pass the option 'raw' (or ignbrk=1) there
684 a2faf9ee Guido Trotter
      # will be no way of exiting socat (except killing it from another shell)
685 a2faf9ee Guido Trotter
      # and ctrl+c doesn't work anyway, printing ^C rather than being
686 a2faf9ee Guido Trotter
      # interpreted by kvm. For now we'll leave it this way, which at least
687 a2faf9ee Guido Trotter
      # allows a minimal interaction and changes on the machine.
688 a2faf9ee Guido Trotter
      shell_command = ("%s STDIO,echo=0,icanon=0 UNIX-CONNECT:%s" %
689 a2faf9ee Guido Trotter
                       (constants.SOCAT_PATH,
690 a2faf9ee Guido Trotter
                        utils.ShellQuote(cls._InstanceSerial(instance.name))))
691 a2faf9ee Guido Trotter
    else:
692 a2faf9ee Guido Trotter
      shell_command = "echo 'No serial shell for instance %s'" % instance.name
693 3be34f57 Guido Trotter
694 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
695 3be34f57 Guido Trotter
    if vnc_bind_address:
696 377d74c9 Guido Trotter
      if instance.network_port > constants.VNC_BASE_PORT:
697 377d74c9 Guido Trotter
        display = instance.network_port - constants.VNC_BASE_PORT
698 3be34f57 Guido Trotter
        vnc_command = ("echo 'Instance has VNC listening on %s:%d"
699 3be34f57 Guido Trotter
                       " (display: %d)'" % (vnc_bind_address,
700 3be34f57 Guido Trotter
                                            instance.network_port,
701 3be34f57 Guido Trotter
                                            display))
702 3be34f57 Guido Trotter
        shell_command = "%s; %s" % (vnc_command, shell_command)
703 3be34f57 Guido Trotter
704 a2faf9ee Guido Trotter
    return shell_command
705 eb58f9b1 Guido Trotter
706 eb58f9b1 Guido Trotter
  def Verify(self):
707 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
708 eb58f9b1 Guido Trotter

709 eb58f9b1 Guido Trotter
    Check that the binary exists.
710 eb58f9b1 Guido Trotter

711 eb58f9b1 Guido Trotter
    """
712 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
713 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
714 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
715 14aa53cb Guido Trotter
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
716 14aa53cb Guido Trotter
717 6b5605e8 Iustin Pop
718 6b5605e8 Iustin Pop
  @classmethod
719 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
720 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
721 6b5605e8 Iustin Pop

722 6b5605e8 Iustin Pop
    @type hvparams:  dict
723 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
724 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
725 6b5605e8 Iustin Pop

726 6b5605e8 Iustin Pop
    """
727 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
728 6b5605e8 Iustin Pop
729 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
730 df5ab9f0 Guido Trotter
    if kernel_path:
731 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
732 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
733 205ab586 Iustin Pop
                                     " if a kernel is defined")
734 6b5605e8 Iustin Pop
735 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
736 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
737 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
738 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
739 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
740 66d5dbef Guido Trotter
741 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
742 66d5dbef Guido Trotter
743 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
744 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
745 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
746 835528af Iustin Pop
                                   " ISO path")
747 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_NETWORK and
748 205ab586 Iustin Pop
        hvparams[constants.HV_NIC_TYPE] == constants.HT_NIC_PARAVIRTUAL):
749 8745c3d7 Guido Trotter
      raise errors.HypervisorError("Cannot boot from a paravirtual NIC. Please"
750 835528af Iustin Pop
                                   " change the NIC type.")
751 f5118ade Iustin Pop
752 f5118ade Iustin Pop
  @classmethod
753 f5118ade Iustin Pop
  def PowercycleNode(cls):
754 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
755 f5118ade Iustin Pop

756 f5118ade Iustin Pop
    """
757 f5118ade Iustin Pop
    cls.LinuxPowercycle()