Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 78411c60

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

618 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
619 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
620 30e42c4e Guido Trotter
    @type target: string
621 30e42c4e Guido Trotter
    @param target: ip address of the target node
622 30e42c4e Guido Trotter
    @type live: boolean
623 30e42c4e Guido Trotter
    @param live: perform a live migration
624 30e42c4e Guido Trotter

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

667 572e52bf Iustin Pop
    This is just a wrapper over the base GetLinuxNodeInfo method.
668 572e52bf Iustin Pop

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

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

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

711 eb58f9b1 Guido Trotter
    Check that the binary exists.
712 eb58f9b1 Guido Trotter

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

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

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

758 f5118ade Iustin Pop
    """
759 f5118ade Iustin Pop
    cls.LinuxPowercycle()