Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 7c60f7a2

History | View | Annotate | Download (25.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 205ab586 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
66 d73ef63f Michael Hanselmann
    constants.HV_BOOT_ORDER:
67 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
68 d73ef63f Michael Hanselmann
    constants.HV_NIC_TYPE:
69 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
70 d73ef63f Michael Hanselmann
    constants.HV_DISK_TYPE:
71 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
72 d73ef63f Michael Hanselmann
    constants.HV_USB_MOUSE:
73 d73ef63f Michael Hanselmann
      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 7c60f7a2 Guido Trotter
      if nic.nicparams[constants.NIC_LINK]:
173 7c60f7a2 Guido Trotter
        script.write("  /sbin/ip route replace $IP/32 table $LINK dev $INTERFACE\n")
174 7c60f7a2 Guido Trotter
      else:
175 7c60f7a2 Guido Trotter
        script.write("  /sbin/ip route replace $IP/32 dev $INTERFACE\n")
176 bef9c750 Guido Trotter
      interface_proxy_arp = "/proc/sys/net/ipv4/conf/$INTERFACE/proxy_arp"
177 bef9c750 Guido Trotter
      script.write("  /bin/echo 1 > %s\n" % interface_proxy_arp)
178 eb58f9b1 Guido Trotter
    script.write("fi\n\n")
179 eb58f9b1 Guido Trotter
    # As much as we'd like to put this in our _ROOT_DIR, that will happen to be
180 eb58f9b1 Guido Trotter
    # mounted noexec sometimes, so we'll have to find another place.
181 eb58f9b1 Guido Trotter
    (tmpfd, tmpfile_name) = tempfile.mkstemp()
182 eb58f9b1 Guido Trotter
    tmpfile = os.fdopen(tmpfd, 'w')
183 d73ef63f Michael Hanselmann
    try:
184 d73ef63f Michael Hanselmann
      tmpfile.write(script.getvalue())
185 d73ef63f Michael Hanselmann
    finally:
186 d73ef63f Michael Hanselmann
      tmpfile.close()
187 eb58f9b1 Guido Trotter
    os.chmod(tmpfile_name, 0755)
188 eb58f9b1 Guido Trotter
    return tmpfile_name
189 eb58f9b1 Guido Trotter
190 eb58f9b1 Guido Trotter
  def ListInstances(self):
191 eb58f9b1 Guido Trotter
    """Get the list of running instances.
192 eb58f9b1 Guido Trotter

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

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

207 c41eea6e Iustin Pop
    @param instance_name: the instance name
208 c41eea6e Iustin Pop

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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