Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 1e37ad45

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 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 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 d73ef63f Michael Hanselmann
    try:
181 d73ef63f Michael Hanselmann
      tmpfile.write(script.getvalue())
182 d73ef63f Michael Hanselmann
    finally:
183 d73ef63f Michael Hanselmann
      tmpfile.close()
184 eb58f9b1 Guido Trotter
    os.chmod(tmpfile_name, 0755)
185 eb58f9b1 Guido Trotter
    return tmpfile_name
186 eb58f9b1 Guido Trotter
187 eb58f9b1 Guido Trotter
  def ListInstances(self):
188 eb58f9b1 Guido Trotter
    """Get the list of running instances.
189 eb58f9b1 Guido Trotter

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

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

204 c41eea6e Iustin Pop
    @param instance_name: the instance name
205 c41eea6e Iustin Pop

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

582 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
583 30e42c4e Guido Trotter

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

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

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

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

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

647 572e52bf Iustin Pop
    This is just a wrapper over the base GetLinuxNodeInfo method.
648 572e52bf Iustin Pop

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

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

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

691 eb58f9b1 Guido Trotter
    Check that the binary exists.
692 eb58f9b1 Guido Trotter

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

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

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

738 f5118ade Iustin Pop
    """
739 f5118ade Iustin Pop
    cls.LinuxPowercycle()