Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 2c5afffb

History | View | Annotate | Download (26.4 kB)

1 eb58f9b1 Guido Trotter
#
2 eb58f9b1 Guido Trotter
#
3 eb58f9b1 Guido Trotter
4 eb58f9b1 Guido Trotter
# Copyright (C) 2008 Google Inc.
5 eb58f9b1 Guido Trotter
#
6 eb58f9b1 Guido Trotter
# This program is free software; you can redistribute it and/or modify
7 eb58f9b1 Guido Trotter
# it under the terms of the GNU General Public License as published by
8 eb58f9b1 Guido Trotter
# the Free Software Foundation; either version 2 of the License, or
9 eb58f9b1 Guido Trotter
# (at your option) any later version.
10 eb58f9b1 Guido Trotter
#
11 eb58f9b1 Guido Trotter
# This program is distributed in the hope that it will be useful, but
12 eb58f9b1 Guido Trotter
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 eb58f9b1 Guido Trotter
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 eb58f9b1 Guido Trotter
# General Public License for more details.
15 eb58f9b1 Guido Trotter
#
16 eb58f9b1 Guido Trotter
# You should have received a copy of the GNU General Public License
17 eb58f9b1 Guido Trotter
# along with this program; if not, write to the Free Software
18 eb58f9b1 Guido Trotter
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 eb58f9b1 Guido Trotter
# 02110-1301, USA.
20 eb58f9b1 Guido Trotter
21 eb58f9b1 Guido Trotter
22 eb58f9b1 Guido Trotter
"""KVM hypervisor
23 eb58f9b1 Guido Trotter

24 eb58f9b1 Guido Trotter
"""
25 eb58f9b1 Guido Trotter
26 eb58f9b1 Guido Trotter
import os
27 eb58f9b1 Guido Trotter
import os.path
28 eb58f9b1 Guido Trotter
import re
29 eb58f9b1 Guido Trotter
import tempfile
30 6567aff3 Guido Trotter
import time
31 30e42c4e Guido Trotter
import logging
32 eb58f9b1 Guido Trotter
from cStringIO import StringIO
33 eb58f9b1 Guido Trotter
34 eb58f9b1 Guido Trotter
from ganeti import utils
35 eb58f9b1 Guido Trotter
from ganeti import constants
36 eb58f9b1 Guido Trotter
from ganeti import errors
37 38e250ba Guido Trotter
from ganeti import serializer
38 38e250ba Guido Trotter
from ganeti import objects
39 eb58f9b1 Guido Trotter
from ganeti.hypervisor import hv_base
40 eb58f9b1 Guido Trotter
41 eb58f9b1 Guido Trotter
42 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
43 c4469f75 Guido Trotter
  """KVM hypervisor interface"""
44 eb58f9b1 Guido Trotter
45 eb58f9b1 Guido Trotter
  _ROOT_DIR = constants.RUN_GANETI_DIR + "/kvm-hypervisor"
46 a1d79fc6 Guido Trotter
  _PIDS_DIR = _ROOT_DIR + "/pid" # contains live instances pids
47 a1d79fc6 Guido Trotter
  _CTRL_DIR = _ROOT_DIR + "/ctrl" # contains instances control sockets
48 a1d79fc6 Guido Trotter
  _CONF_DIR = _ROOT_DIR + "/conf" # contains instances startup data
49 a1d79fc6 Guido Trotter
  _DIRS = [_ROOT_DIR, _PIDS_DIR, _CTRL_DIR, _CONF_DIR]
50 eb58f9b1 Guido Trotter
51 205ab586 Iustin Pop
  PARAMETERS = {
52 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK,
53 205ab586 Iustin Pop
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
54 205ab586 Iustin Pop
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
55 205ab586 Iustin Pop
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
56 205ab586 Iustin Pop
    constants.HV_ACPI: hv_base.NO_CHECK,
57 205ab586 Iustin Pop
    constants.HV_SERIAL_CONSOLE: hv_base.NO_CHECK,
58 d73ef63f Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS:
59 d73ef63f Michael Hanselmann
      (False, lambda x: (utils.IsValidIP(x) or utils.IsNormAbsPath(x)),
60 d73ef63f Michael Hanselmann
       "the VNC bind address must be either a valid IP address or an absolute"
61 d73ef63f Michael Hanselmann
       " pathname", None, None),
62 205ab586 Iustin Pop
    constants.HV_VNC_TLS: hv_base.NO_CHECK,
63 205ab586 Iustin Pop
    constants.HV_VNC_X509: hv_base.OPT_DIR_CHECK,
64 205ab586 Iustin Pop
    constants.HV_VNC_X509_VERIFY: hv_base.NO_CHECK,
65 6e6bb8d5 Guido Trotter
    constants.HV_VNC_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
66 205ab586 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
67 d73ef63f Michael Hanselmann
    constants.HV_BOOT_ORDER:
68 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
69 d73ef63f Michael Hanselmann
    constants.HV_NIC_TYPE:
70 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
71 d73ef63f Michael Hanselmann
    constants.HV_DISK_TYPE:
72 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
73 d73ef63f Michael Hanselmann
    constants.HV_USB_MOUSE:
74 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
75 205ab586 Iustin Pop
    }
76 6b5605e8 Iustin Pop
77 30e42c4e Guido Trotter
  _MIGRATION_STATUS_RE = re.compile('Migration\s+status:\s+(\w+)',
78 30e42c4e Guido Trotter
                                    re.M | re.I)
79 30e42c4e Guido Trotter
80 5420ffc9 Guido Trotter
  _KVM_NETWORK_SCRIPT = constants.SYSCONFDIR + "/ganeti/kvm-vif-bridge"
81 5420ffc9 Guido Trotter
82 64bfbc08 Guido Trotter
  ANCILLARY_FILES = [
83 64bfbc08 Guido Trotter
    _KVM_NETWORK_SCRIPT,
84 64bfbc08 Guido Trotter
    ]
85 64bfbc08 Guido Trotter
86 eb58f9b1 Guido Trotter
  def __init__(self):
87 eb58f9b1 Guido Trotter
    hv_base.BaseHypervisor.__init__(self)
88 eb58f9b1 Guido Trotter
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
89 eb58f9b1 Guido Trotter
    # in a tmpfs filesystem or has been otherwise wiped out.
90 29921401 Iustin Pop
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
91 9afb67fe Guido Trotter
    utils.EnsureDirs(dirs)
92 eb58f9b1 Guido Trotter
93 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
94 1f8b3a27 Guido Trotter
    """Returns the instance pid and pidfile
95 1f8b3a27 Guido Trotter

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

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

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

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

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

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

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

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

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

202 eb58f9b1 Guido Trotter
    """
203 eb58f9b1 Guido Trotter
    result = []
204 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
205 08137f9e Iustin Pop
      filename = "%s/%s" % (self._PIDS_DIR, name)
206 08137f9e Iustin Pop
      if utils.IsProcessAlive(utils.ReadPidFile(filename)):
207 eb58f9b1 Guido Trotter
        result.append(name)
208 eb58f9b1 Guido Trotter
    return result
209 eb58f9b1 Guido Trotter
210 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
211 eb58f9b1 Guido Trotter
    """Get instance properties.
212 eb58f9b1 Guido Trotter

213 c41eea6e Iustin Pop
    @param instance_name: the instance name
214 c41eea6e Iustin Pop

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

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

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

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

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

395 38e250ba Guido Trotter
    """
396 38e250ba Guido Trotter
    try:
397 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
398 38e250ba Guido Trotter
                      data=data)
399 90c024f6 Guido Trotter
    except EnvironmentError, err:
400 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
401 38e250ba Guido Trotter
402 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
403 38e250ba Guido Trotter
    """Read an instance's KVM runtime
404 38e250ba Guido Trotter

405 38e250ba Guido Trotter
    """
406 38e250ba Guido Trotter
    try:
407 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
408 90c024f6 Guido Trotter
    except EnvironmentError, err:
409 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
410 38e250ba Guido Trotter
    return file_content
411 38e250ba Guido Trotter
412 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
413 38e250ba Guido Trotter
    """Save an instance's KVM runtime
414 38e250ba Guido Trotter

415 38e250ba Guido Trotter
    """
416 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
417 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
418 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
419 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
420 38e250ba Guido Trotter
421 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
422 38e250ba Guido Trotter
    """Load an instance's KVM runtime
423 38e250ba Guido Trotter

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

435 30e42c4e Guido Trotter
    @type incoming: tuple of strings
436 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
437 30e42c4e Guido Trotter

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

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

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

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

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

567 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
568 30e42c4e Guido Trotter
    @param instance: instance to be migrated
569 30e42c4e Guido Trotter
    @rtype: string
570 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
571 30e42c4e Guido Trotter

572 30e42c4e Guido Trotter
    """
573 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
574 30e42c4e Guido Trotter
575 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
576 30e42c4e Guido Trotter
    """Prepare to accept an instance.
577 30e42c4e Guido Trotter

578 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
579 30e42c4e Guido Trotter
    @param instance: instance to be accepted
580 30e42c4e Guido Trotter
    @type info: string
581 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
582 30e42c4e Guido Trotter
    @type target: string
583 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
584 30e42c4e Guido Trotter

585 30e42c4e Guido Trotter
    """
586 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
587 30e42c4e Guido Trotter
    incoming_address = (target, constants.KVM_MIGRATION_PORT)
588 30e42c4e Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
589 30e42c4e Guido Trotter
590 30e42c4e Guido Trotter
  def FinalizeMigration(self, instance, info, success):
591 30e42c4e Guido Trotter
    """Finalize an instance migration.
592 30e42c4e Guido Trotter

593 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
594 30e42c4e Guido Trotter

595 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
596 30e42c4e Guido Trotter
    @param instance: instance whose migration is being aborted
597 30e42c4e Guido Trotter

598 30e42c4e Guido Trotter
    """
599 30e42c4e Guido Trotter
    if success:
600 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
601 30e42c4e Guido Trotter
    else:
602 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
603 30e42c4e Guido Trotter
604 30e42c4e Guido Trotter
  def MigrateInstance(self, instance_name, target, live):
605 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
606 30e42c4e Guido Trotter

607 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
608 30e42c4e Guido Trotter
    currently running.
609 30e42c4e Guido Trotter

610 30e42c4e Guido Trotter
    @type instance_name: string
611 30e42c4e Guido Trotter
    @param instance_name: name of the instance to be migrated
612 30e42c4e Guido Trotter
    @type target: string
613 30e42c4e Guido Trotter
    @param target: ip address of the target node
614 30e42c4e Guido Trotter
    @type live: boolean
615 30e42c4e Guido Trotter
    @param live: perform a live migration
616 30e42c4e Guido Trotter

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

658 572e52bf Iustin Pop
    This is just a wrapper over the base GetLinuxNodeInfo method.
659 572e52bf Iustin Pop

660 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
661 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
662 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
663 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
664 eb58f9b1 Guido Trotter

665 eb58f9b1 Guido Trotter
    """
666 572e52bf Iustin Pop
    return self.GetLinuxNodeInfo()
667 eb58f9b1 Guido Trotter
668 637ce7f9 Guido Trotter
  @classmethod
669 5431b2e4 Guido Trotter
  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
670 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
671 eb58f9b1 Guido Trotter

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

702 eb58f9b1 Guido Trotter
    Check that the binary exists.
703 eb58f9b1 Guido Trotter

704 eb58f9b1 Guido Trotter
    """
705 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
706 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
707 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
708 14aa53cb Guido Trotter
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
709 14aa53cb Guido Trotter
710 6b5605e8 Iustin Pop
711 6b5605e8 Iustin Pop
  @classmethod
712 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
713 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
714 6b5605e8 Iustin Pop

715 6b5605e8 Iustin Pop
    @type hvparams:  dict
716 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
717 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
718 6b5605e8 Iustin Pop

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

749 f5118ade Iustin Pop
    """
750 f5118ade Iustin Pop
    cls.LinuxPowercycle()