Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 3374afa9

History | View | Annotate | Download (25.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 205ab586 Iustin Pop
    constants.HV_VNC_BIND_ADDRESS: \
59 29921401 Iustin Pop
    (False, lambda x: (utils.IsValidIP(x) or utils.IsNormAbsPath(x)),
60 205ab586 Iustin Pop
     "the VNC bind address must be either a valid IP address or an absolute"
61 205ab586 Iustin Pop
     " 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 205ab586 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
66 205ab586 Iustin Pop
    constants.HV_BOOT_ORDER: \
67 205ab586 Iustin Pop
    hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
68 205ab586 Iustin Pop
    constants.HV_NIC_TYPE: \
69 205ab586 Iustin Pop
    hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
70 205ab586 Iustin Pop
    constants.HV_DISK_TYPE: \
71 205ab586 Iustin Pop
    hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
72 205ab586 Iustin Pop
    constants.HV_USB_MOUSE: \
73 205ab586 Iustin Pop
    hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
74 205ab586 Iustin Pop
    }
75 6b5605e8 Iustin Pop
76 30e42c4e Guido Trotter
  _MIGRATION_STATUS_RE = re.compile('Migration\s+status:\s+(\w+)',
77 30e42c4e Guido Trotter
                                    re.M | re.I)
78 30e42c4e Guido Trotter
79 5420ffc9 Guido Trotter
  _KVM_NETWORK_SCRIPT = constants.SYSCONFDIR + "/ganeti/kvm-vif-bridge"
80 5420ffc9 Guido Trotter
81 64bfbc08 Guido Trotter
  ANCILLARY_FILES = [
82 64bfbc08 Guido Trotter
    _KVM_NETWORK_SCRIPT,
83 64bfbc08 Guido Trotter
    ]
84 64bfbc08 Guido Trotter
85 eb58f9b1 Guido Trotter
  def __init__(self):
86 eb58f9b1 Guido Trotter
    hv_base.BaseHypervisor.__init__(self)
87 eb58f9b1 Guido Trotter
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
88 eb58f9b1 Guido Trotter
    # in a tmpfs filesystem or has been otherwise wiped out.
89 29921401 Iustin Pop
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
90 9afb67fe Guido Trotter
    utils.EnsureDirs(dirs)
91 eb58f9b1 Guido Trotter
92 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
93 1f8b3a27 Guido Trotter
    """Returns the instance pid and pidfile
94 1f8b3a27 Guido Trotter

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

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

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

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

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

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

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

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

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

191 eb58f9b1 Guido Trotter
    """
192 eb58f9b1 Guido Trotter
    result = []
193 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
194 08137f9e Iustin Pop
      filename = "%s/%s" % (self._PIDS_DIR, name)
195 08137f9e Iustin Pop
      if utils.IsProcessAlive(utils.ReadPidFile(filename)):
196 eb58f9b1 Guido Trotter
        result.append(name)
197 eb58f9b1 Guido Trotter
    return result
198 eb58f9b1 Guido Trotter
199 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
200 eb58f9b1 Guido Trotter
    """Get instance properties.
201 eb58f9b1 Guido Trotter

202 c41eea6e Iustin Pop
    @param instance_name: the instance name
203 c41eea6e Iustin Pop

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

206 eb58f9b1 Guido Trotter
    """
207 1f8b3a27 Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
208 1f8b3a27 Guido Trotter
    if not alive:
209 eb58f9b1 Guido Trotter
      return None
210 eb58f9b1 Guido Trotter
211 eb58f9b1 Guido Trotter
    cmdline_file = "/proc/%s/cmdline" % pid
212 eb58f9b1 Guido Trotter
    try:
213 eb58f9b1 Guido Trotter
      fh = open(cmdline_file, 'r')
214 eb58f9b1 Guido Trotter
      try:
215 eb58f9b1 Guido Trotter
        cmdline = fh.read()
216 eb58f9b1 Guido Trotter
      finally:
217 eb58f9b1 Guido Trotter
        fh.close()
218 90c024f6 Guido Trotter
    except EnvironmentError, err:
219 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to list instance %s: %s" %
220 eb58f9b1 Guido Trotter
                                   (instance_name, err))
221 eb58f9b1 Guido Trotter
222 eb58f9b1 Guido Trotter
    memory = 0
223 eb58f9b1 Guido Trotter
    vcpus = 0
224 eb58f9b1 Guido Trotter
    stat = "---b-"
225 eb58f9b1 Guido Trotter
    times = "0"
226 eb58f9b1 Guido Trotter
227 eb58f9b1 Guido Trotter
    arg_list = cmdline.split('\x00')
228 eb58f9b1 Guido Trotter
    while arg_list:
229 eb58f9b1 Guido Trotter
      arg =  arg_list.pop(0)
230 eb58f9b1 Guido Trotter
      if arg == '-m':
231 2a7e887b Guido Trotter
        memory = int(arg_list.pop(0))
232 eb58f9b1 Guido Trotter
      elif arg == '-smp':
233 2a7e887b Guido Trotter
        vcpus = int(arg_list.pop(0))
234 eb58f9b1 Guido Trotter
235 eb58f9b1 Guido Trotter
    return (instance_name, pid, memory, vcpus, stat, times)
236 eb58f9b1 Guido Trotter
237 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
238 eb58f9b1 Guido Trotter
    """Get properties of all instances.
239 eb58f9b1 Guido Trotter

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

242 eb58f9b1 Guido Trotter
    """
243 eb58f9b1 Guido Trotter
    data = []
244 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
245 08137f9e Iustin Pop
      filename = "%s/%s" % (self._PIDS_DIR, name)
246 08137f9e Iustin Pop
      if utils.IsProcessAlive(utils.ReadPidFile(filename)):
247 00ad5362 Guido Trotter
        try:
248 00ad5362 Guido Trotter
          info = self.GetInstanceInfo(name)
249 00ad5362 Guido Trotter
        except errors.HypervisorError, err:
250 00ad5362 Guido Trotter
          continue
251 00ad5362 Guido Trotter
        if info:
252 00ad5362 Guido Trotter
          data.append(info)
253 eb58f9b1 Guido Trotter
254 eb58f9b1 Guido Trotter
    return data
255 eb58f9b1 Guido Trotter
256 07813a9e Iustin Pop
  def _GenerateKVMRuntime(self, instance, block_devices):
257 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
258 eb58f9b1 Guido Trotter

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

386 38e250ba Guido Trotter
    """
387 38e250ba Guido Trotter
    try:
388 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
389 38e250ba Guido Trotter
                      data=data)
390 90c024f6 Guido Trotter
    except EnvironmentError, err:
391 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
392 38e250ba Guido Trotter
393 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
394 38e250ba Guido Trotter
    """Read an instance's KVM runtime
395 38e250ba Guido Trotter

396 38e250ba Guido Trotter
    """
397 38e250ba Guido Trotter
    try:
398 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
399 90c024f6 Guido Trotter
    except EnvironmentError, err:
400 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
401 38e250ba Guido Trotter
    return file_content
402 38e250ba Guido Trotter
403 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
404 38e250ba Guido Trotter
    """Save an instance's KVM runtime
405 38e250ba Guido Trotter

406 38e250ba Guido Trotter
    """
407 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
408 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
409 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
410 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
411 38e250ba Guido Trotter
412 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
413 38e250ba Guido Trotter
    """Load an instance's KVM runtime
414 38e250ba Guido Trotter

415 38e250ba Guido Trotter
    """
416 30e42c4e Guido Trotter
    if not serialized_runtime:
417 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
418 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
419 c2672466 Guido Trotter
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
420 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
421 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
422 38e250ba Guido Trotter
423 30e42c4e Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
424 ee5f20b0 Guido Trotter
    """Execute a KVM cmd, after completing it with some last minute data
425 ee5f20b0 Guido Trotter

426 30e42c4e Guido Trotter
    @type incoming: tuple of strings
427 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
428 30e42c4e Guido Trotter

429 ee5f20b0 Guido Trotter
    """
430 1f8b3a27 Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance.name)
431 1f8b3a27 Guido Trotter
    if alive:
432 ee5f20b0 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s" %
433 ee5f20b0 Guido Trotter
                                   (instance.name, "already running"))
434 ee5f20b0 Guido Trotter
435 ee5f20b0 Guido Trotter
    temp_files = []
436 ee5f20b0 Guido Trotter
437 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
438 ee5f20b0 Guido Trotter
439 ee5f20b0 Guido Trotter
    if not kvm_nics:
440 ee5f20b0 Guido Trotter
      kvm_cmd.extend(['-net', 'none'])
441 ee5f20b0 Guido Trotter
    else:
442 37f88dc6 Guido Trotter
      nic_type = hvparams[constants.HV_NIC_TYPE]
443 37f88dc6 Guido Trotter
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
444 37f88dc6 Guido Trotter
        nic_model = "model=virtio"
445 37f88dc6 Guido Trotter
      else:
446 37f88dc6 Guido Trotter
        nic_model = "model=%s" % nic_type
447 37f88dc6 Guido Trotter
448 ee5f20b0 Guido Trotter
      for nic_seq, nic in enumerate(kvm_nics):
449 37f88dc6 Guido Trotter
        nic_val = "nic,macaddr=%s,%s" % (nic.mac, nic_model)
450 ee5f20b0 Guido Trotter
        script = self._WriteNetScript(instance, nic_seq, nic)
451 ee5f20b0 Guido Trotter
        kvm_cmd.extend(['-net', nic_val])
452 ee5f20b0 Guido Trotter
        kvm_cmd.extend(['-net', 'tap,script=%s' % script])
453 ee5f20b0 Guido Trotter
        temp_files.append(script)
454 ee5f20b0 Guido Trotter
455 30e42c4e Guido Trotter
    if incoming:
456 30e42c4e Guido Trotter
      target, port = incoming
457 30e42c4e Guido Trotter
      kvm_cmd.extend(['-incoming', 'tcp:%s:%s' % (target, port)])
458 30e42c4e Guido Trotter
459 eb58f9b1 Guido Trotter
    result = utils.RunCmd(kvm_cmd)
460 eb58f9b1 Guido Trotter
    if result.failed:
461 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
462 eb58f9b1 Guido Trotter
                                   (instance.name, result.fail_reason,
463 eb58f9b1 Guido Trotter
                                    result.output))
464 eb58f9b1 Guido Trotter
465 eb58f9b1 Guido Trotter
    if not utils.IsProcessAlive(utils.ReadPidFile(pidfile)):
466 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s" %
467 eb58f9b1 Guido Trotter
                                   (instance.name))
468 eb58f9b1 Guido Trotter
469 08137f9e Iustin Pop
    for filename in temp_files:
470 08137f9e Iustin Pop
      utils.RemoveFile(filename)
471 eb58f9b1 Guido Trotter
472 07813a9e Iustin Pop
  def StartInstance(self, instance, block_devices):
473 ee5f20b0 Guido Trotter
    """Start an instance.
474 ee5f20b0 Guido Trotter

475 ee5f20b0 Guido Trotter
    """
476 1f8b3a27 Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance.name)
477 1f8b3a27 Guido Trotter
    if alive:
478 ee5f20b0 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s" %
479 ee5f20b0 Guido Trotter
                                   (instance.name, "already running"))
480 ee5f20b0 Guido Trotter
481 07813a9e Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices)
482 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
483 ee5f20b0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
484 ee5f20b0 Guido Trotter
485 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
486 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
487 6567aff3 Guido Trotter

488 6567aff3 Guido Trotter
    """
489 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
490 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
491 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
492 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
493 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
494 6567aff3 Guido Trotter
    if result.failed:
495 6567aff3 Guido Trotter
      msg = ("Failed to send command '%s' to instance %s."
496 6567aff3 Guido Trotter
             " output: %s, error: %s, fail_reason: %s" %
497 9798fcae Guido Trotter
             (command, instance_name,
498 9798fcae Guido Trotter
              result.stdout, result.stderr, result.fail_reason))
499 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
500 6567aff3 Guido Trotter
501 6567aff3 Guido Trotter
    return result
502 6567aff3 Guido Trotter
503 6567aff3 Guido Trotter
  def _RetryInstancePowerdown(self, instance, pid, timeout=30):
504 6567aff3 Guido Trotter
    """Wait for an instance  to power down.
505 6567aff3 Guido Trotter

506 6567aff3 Guido Trotter
    """
507 6567aff3 Guido Trotter
    # Wait up to $timeout seconds
508 6567aff3 Guido Trotter
    end = time.time() + timeout
509 6567aff3 Guido Trotter
    wait = 1
510 6567aff3 Guido Trotter
    while time.time() < end and utils.IsProcessAlive(pid):
511 6567aff3 Guido Trotter
      self._CallMonitorCommand(instance.name, 'system_powerdown')
512 6567aff3 Guido Trotter
      time.sleep(wait)
513 6567aff3 Guido Trotter
      # Make wait time longer for next try
514 6567aff3 Guido Trotter
      if wait < 5:
515 6567aff3 Guido Trotter
        wait *= 1.3
516 6567aff3 Guido Trotter
517 eb58f9b1 Guido Trotter
  def StopInstance(self, instance, force=False):
518 eb58f9b1 Guido Trotter
    """Stop an instance.
519 eb58f9b1 Guido Trotter

520 eb58f9b1 Guido Trotter
    """
521 1f8b3a27 Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance.name)
522 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
523 6b5605e8 Iustin Pop
      if force or not instance.hvparams[constants.HV_ACPI]:
524 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
525 eb58f9b1 Guido Trotter
      else:
526 6567aff3 Guido Trotter
        self._RetryInstancePowerdown(instance, pid)
527 eb58f9b1 Guido Trotter
528 eb58f9b1 Guido Trotter
    if not utils.IsProcessAlive(pid):
529 7e66c35b Guido Trotter
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
530 6567aff3 Guido Trotter
      return True
531 6567aff3 Guido Trotter
    else:
532 6567aff3 Guido Trotter
      return False
533 eb58f9b1 Guido Trotter
534 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
535 eb58f9b1 Guido Trotter
    """Reboot an instance.
536 eb58f9b1 Guido Trotter

537 eb58f9b1 Guido Trotter
    """
538 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
539 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
540 eb58f9b1 Guido Trotter
    # to shutdown and restart.
541 1f8b3a27 Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance.name)
542 1f8b3a27 Guido Trotter
    if not alive:
543 1f8b3a27 Guido Trotter
      raise errors.HypervisorError("Failed to reboot instance %s: not running" %
544 1f8b3a27 Guido Trotter
                                             (instance.name))
545 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
546 f02881e0 Guido Trotter
    # ...first load it...
547 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
548 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
549 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
550 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
551 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
552 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
553 f02881e0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
554 eb58f9b1 Guido Trotter
555 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
556 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
557 30e42c4e Guido Trotter

558 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
559 30e42c4e Guido Trotter
    @param instance: instance to be migrated
560 30e42c4e Guido Trotter
    @rtype: string
561 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
562 30e42c4e Guido Trotter

563 30e42c4e Guido Trotter
    """
564 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
565 30e42c4e Guido Trotter
566 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
567 30e42c4e Guido Trotter
    """Prepare to accept an instance.
568 30e42c4e Guido Trotter

569 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
570 30e42c4e Guido Trotter
    @param instance: instance to be accepted
571 30e42c4e Guido Trotter
    @type info: string
572 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
573 30e42c4e Guido Trotter
    @type target: string
574 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
575 30e42c4e Guido Trotter

576 30e42c4e Guido Trotter
    """
577 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
578 30e42c4e Guido Trotter
    incoming_address = (target, constants.KVM_MIGRATION_PORT)
579 30e42c4e Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
580 30e42c4e Guido Trotter
581 30e42c4e Guido Trotter
  def FinalizeMigration(self, instance, info, success):
582 30e42c4e Guido Trotter
    """Finalize an instance migration.
583 30e42c4e Guido Trotter

584 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
585 30e42c4e Guido Trotter

586 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
587 30e42c4e Guido Trotter
    @param instance: instance whose migration is being aborted
588 30e42c4e Guido Trotter

589 30e42c4e Guido Trotter
    """
590 30e42c4e Guido Trotter
    if success:
591 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
592 30e42c4e Guido Trotter
    else:
593 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
594 30e42c4e Guido Trotter
595 30e42c4e Guido Trotter
  def MigrateInstance(self, instance_name, target, live):
596 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
597 30e42c4e Guido Trotter

598 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
599 30e42c4e Guido Trotter
    currently running.
600 30e42c4e Guido Trotter

601 30e42c4e Guido Trotter
    @type instance_name: string
602 30e42c4e Guido Trotter
    @param instance_name: name of the instance to be migrated
603 30e42c4e Guido Trotter
    @type target: string
604 30e42c4e Guido Trotter
    @param target: ip address of the target node
605 30e42c4e Guido Trotter
    @type live: boolean
606 30e42c4e Guido Trotter
    @param live: perform a live migration
607 30e42c4e Guido Trotter

608 30e42c4e Guido Trotter
    """
609 30e42c4e Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
610 30e42c4e Guido Trotter
    if not alive:
611 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
612 30e42c4e Guido Trotter
613 30e42c4e Guido Trotter
    if not live:
614 30e42c4e Guido Trotter
      self._CallMonitorCommand(instance_name, 'stop')
615 30e42c4e Guido Trotter
616 30e42c4e Guido Trotter
    migrate_command = ('migrate -d tcp:%s:%s' %
617 30e42c4e Guido Trotter
                       (target, constants.KVM_MIGRATION_PORT))
618 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
619 30e42c4e Guido Trotter
620 30e42c4e Guido Trotter
    info_command = 'info migrate'
621 30e42c4e Guido Trotter
    done = False
622 30e42c4e Guido Trotter
    while not done:
623 30e42c4e Guido Trotter
      result = self._CallMonitorCommand(instance_name, info_command)
624 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
625 30e42c4e Guido Trotter
      if not match:
626 30e42c4e Guido Trotter
        raise errors.HypervisorError("Unknown 'info migrate' result: %s" %
627 30e42c4e Guido Trotter
                                     result.stdout)
628 30e42c4e Guido Trotter
      else:
629 30e42c4e Guido Trotter
        status = match.group(1)
630 30e42c4e Guido Trotter
        if status == 'completed':
631 30e42c4e Guido Trotter
          done = True
632 30e42c4e Guido Trotter
        elif status == 'active':
633 30e42c4e Guido Trotter
          time.sleep(2)
634 c087266c Guido Trotter
        elif status == 'failed' or status == 'cancelled':
635 c087266c Guido Trotter
          if not live:
636 c087266c Guido Trotter
            self._CallMonitorCommand(instance_name, 'cont')
637 c087266c Guido Trotter
          raise errors.HypervisorError("Migration %s at the kvm level" %
638 c087266c Guido Trotter
                                       status)
639 30e42c4e Guido Trotter
        else:
640 30e42c4e Guido Trotter
          logging.info("KVM: unknown migration status '%s'" % status)
641 30e42c4e Guido Trotter
          time.sleep(2)
642 30e42c4e Guido Trotter
643 30e42c4e Guido Trotter
    utils.KillProcess(pid)
644 7b381438 Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
645 30e42c4e Guido Trotter
646 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
647 eb58f9b1 Guido Trotter
    """Return information about the node.
648 eb58f9b1 Guido Trotter

649 572e52bf Iustin Pop
    This is just a wrapper over the base GetLinuxNodeInfo method.
650 572e52bf Iustin Pop

651 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
652 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
653 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
654 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
655 eb58f9b1 Guido Trotter

656 eb58f9b1 Guido Trotter
    """
657 572e52bf Iustin Pop
    return self.GetLinuxNodeInfo()
658 eb58f9b1 Guido Trotter
659 637ce7f9 Guido Trotter
  @classmethod
660 5431b2e4 Guido Trotter
  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
661 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
662 eb58f9b1 Guido Trotter

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

693 eb58f9b1 Guido Trotter
    Check that the binary exists.
694 eb58f9b1 Guido Trotter

695 eb58f9b1 Guido Trotter
    """
696 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
697 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
698 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
699 14aa53cb Guido Trotter
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
700 14aa53cb Guido Trotter
701 6b5605e8 Iustin Pop
702 6b5605e8 Iustin Pop
  @classmethod
703 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
704 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
705 6b5605e8 Iustin Pop

706 6b5605e8 Iustin Pop
    @type hvparams:  dict
707 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
708 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
709 6b5605e8 Iustin Pop

710 6b5605e8 Iustin Pop
    """
711 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
712 6b5605e8 Iustin Pop
713 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
714 df5ab9f0 Guido Trotter
    if kernel_path:
715 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
716 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
717 205ab586 Iustin Pop
                                     " if a kernel is defined")
718 6b5605e8 Iustin Pop
719 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
720 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
721 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
722 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
723 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
724 66d5dbef Guido Trotter
725 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
726 66d5dbef Guido Trotter
727 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
728 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
729 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
730 835528af Iustin Pop
                                   " ISO path")
731 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_NETWORK and
732 205ab586 Iustin Pop
        hvparams[constants.HV_NIC_TYPE] == constants.HT_NIC_PARAVIRTUAL):
733 8745c3d7 Guido Trotter
      raise errors.HypervisorError("Cannot boot from a paravirtual NIC. Please"
734 835528af Iustin Pop
                                   " change the NIC type.")
735 f5118ade Iustin Pop
736 f5118ade Iustin Pop
  @classmethod
737 f5118ade Iustin Pop
  def PowercycleNode(cls):
738 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
739 f5118ade Iustin Pop

740 f5118ade Iustin Pop
    """
741 f5118ade Iustin Pop
    cls.LinuxPowercycle()