Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 5905901c

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

100 98ec75d6 Iustin Pop
    """
101 98ec75d6 Iustin Pop
    pidfile = "%s/%s" % (self._PIDS_DIR, instance_name)
102 98ec75d6 Iustin Pop
    return pidfile
103 98ec75d6 Iustin Pop
104 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
105 1f8b3a27 Guido Trotter
    """Returns the instance pid and pidfile
106 1f8b3a27 Guido Trotter

107 1f8b3a27 Guido Trotter
    """
108 98ec75d6 Iustin Pop
    pidfile = self._InstancePidFile(instance_name)
109 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
110 1f8b3a27 Guido Trotter
    alive = utils.IsProcessAlive(pid)
111 1f8b3a27 Guido Trotter
112 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
113 1f8b3a27 Guido Trotter
114 5905901c Iustin Pop
  def _CheckDown(self, instance_name):
115 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
116 5905901c Iustin Pop

117 5905901c Iustin Pop
    """
118 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
119 5905901c Iustin Pop
    if alive:
120 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
121 5905901c Iustin Pop
                                   (instance_name, "already running"))
122 5905901c Iustin Pop
123 0df4d98a Guido Trotter
  @classmethod
124 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
125 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
126 c4fbefc8 Guido Trotter

127 c4fbefc8 Guido Trotter
    """
128 0df4d98a Guido Trotter
    return '%s/%s.monitor' % (cls._CTRL_DIR, instance_name)
129 c4fbefc8 Guido Trotter
130 0df4d98a Guido Trotter
  @classmethod
131 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
132 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
133 c4fbefc8 Guido Trotter

134 c4fbefc8 Guido Trotter
    """
135 0df4d98a Guido Trotter
    return '%s/%s.serial' % (cls._CTRL_DIR, instance_name)
136 c4fbefc8 Guido Trotter
137 86d6bc2a Guido Trotter
  @staticmethod
138 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
139 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
140 86d6bc2a Guido Trotter

141 86d6bc2a Guido Trotter
    If we have a new-enough socat we can use raw mode with an escape character.
142 86d6bc2a Guido Trotter

143 86d6bc2a Guido Trotter
    """
144 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
145 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
146 86d6bc2a Guido Trotter
    else:
147 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
148 86d6bc2a Guido Trotter
149 0df4d98a Guido Trotter
  @classmethod
150 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
151 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
152 38e250ba Guido Trotter

153 38e250ba Guido Trotter
    """
154 0df4d98a Guido Trotter
    return '%s/%s.runtime' % (cls._CONF_DIR, instance_name)
155 38e250ba Guido Trotter
156 7e66c35b Guido Trotter
  @classmethod
157 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
158 7e66c35b Guido Trotter
    """Removes an instance's rutime sockets/files.
159 7e66c35b Guido Trotter

160 7e66c35b Guido Trotter
    """
161 7e66c35b Guido Trotter
    utils.RemoveFile(pidfile)
162 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
163 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceSerial(instance_name))
164 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
165 7e66c35b Guido Trotter
166 eb58f9b1 Guido Trotter
  def _WriteNetScript(self, instance, seq, nic):
167 eb58f9b1 Guido Trotter
    """Write a script to connect a net interface to the proper bridge.
168 eb58f9b1 Guido Trotter

169 eb58f9b1 Guido Trotter
    This can be used by any qemu-type hypervisor.
170 eb58f9b1 Guido Trotter

171 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
172 eb58f9b1 Guido Trotter
    @type instance: instance object
173 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
174 eb58f9b1 Guido Trotter
    @type seq: int
175 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
176 eb58f9b1 Guido Trotter
    @type nic: nic object
177 eb58f9b1 Guido Trotter
    @return: netscript file name
178 eb58f9b1 Guido Trotter
    @rtype: string
179 eb58f9b1 Guido Trotter

180 eb58f9b1 Guido Trotter
    """
181 eb58f9b1 Guido Trotter
    script = StringIO()
182 eb58f9b1 Guido Trotter
    script.write("#!/bin/sh\n")
183 eb58f9b1 Guido Trotter
    script.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
184 eb58f9b1 Guido Trotter
    script.write("export INSTANCE=%s\n" % instance.name)
185 eb58f9b1 Guido Trotter
    script.write("export MAC=%s\n" % nic.mac)
186 bef9c750 Guido Trotter
    if nic.ip:
187 bef9c750 Guido Trotter
      script.write("export IP=%s\n" % nic.ip)
188 bef9c750 Guido Trotter
    script.write("export MODE=%s\n" % nic.nicparams[constants.NIC_MODE])
189 bef9c750 Guido Trotter
    if nic.nicparams[constants.NIC_LINK]:
190 bef9c750 Guido Trotter
      script.write("export LINK=%s\n" % nic.nicparams[constants.NIC_LINK])
191 bef9c750 Guido Trotter
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
192 bef9c750 Guido Trotter
      script.write("export BRIDGE=%s\n" % nic.nicparams[constants.NIC_LINK])
193 eb58f9b1 Guido Trotter
    script.write("export INTERFACE=$1\n")
194 eb58f9b1 Guido Trotter
    # TODO: make this configurable at ./configure time
195 5420ffc9 Guido Trotter
    script.write("if [ -x '%s' ]; then\n" % self._KVM_NETWORK_SCRIPT)
196 eb58f9b1 Guido Trotter
    script.write("  # Execute the user-specific vif file\n")
197 5420ffc9 Guido Trotter
    script.write("  %s\n" % self._KVM_NETWORK_SCRIPT)
198 eb58f9b1 Guido Trotter
    script.write("else\n")
199 eb58f9b1 Guido Trotter
    script.write("  /sbin/ifconfig $INTERFACE 0.0.0.0 up\n")
200 bef9c750 Guido Trotter
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
201 bef9c750 Guido Trotter
      script.write("  # Connect the interface to the bridge\n")
202 bef9c750 Guido Trotter
      script.write("  /usr/sbin/brctl addif $BRIDGE $INTERFACE\n")
203 bef9c750 Guido Trotter
    elif nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_ROUTED:
204 94c2ed34 Guido Trotter
      if not nic.ip:
205 94c2ed34 Guido Trotter
        raise errors.HypervisorError("nic/%d is routed, but has no ip." % seq)
206 bef9c750 Guido Trotter
      script.write("  # Route traffic targeted at the IP to the interface\n")
207 7c60f7a2 Guido Trotter
      if nic.nicparams[constants.NIC_LINK]:
208 2c5afffb Guido Trotter
        script.write("  while /sbin/ip rule del dev $INTERFACE; do :; done\n")
209 2c5afffb Guido Trotter
        script.write("  /sbin/ip rule add dev $INTERFACE table $LINK\n")
210 8866ec86 Guido Trotter
        script.write("  /sbin/ip route replace $IP table $LINK proto static"
211 d63218ce Guido Trotter
                     " dev $INTERFACE\n")
212 7c60f7a2 Guido Trotter
      else:
213 8866ec86 Guido Trotter
        script.write("  /sbin/ip route replace $IP proto static"
214 8866ec86 Guido Trotter
                     " dev $INTERFACE\n")
215 e014f1d0 Guido Trotter
      interface_v4_conf = "/proc/sys/net/ipv4/conf/$INTERFACE"
216 e014f1d0 Guido Trotter
      interface_v6_conf = "/proc/sys/net/ipv6/conf/$INTERFACE"
217 e014f1d0 Guido Trotter
      script.write("  if [ -d %s ]; then\n" % interface_v4_conf)
218 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/proxy_arp\n" % interface_v4_conf)
219 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/forwarding\n" % interface_v4_conf)
220 e014f1d0 Guido Trotter
      script.write("  fi\n")
221 e014f1d0 Guido Trotter
      script.write("  if [ -d %s ]; then\n" % interface_v6_conf)
222 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/proxy_ndp\n" % interface_v6_conf)
223 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/forwarding\n" % interface_v6_conf)
224 e014f1d0 Guido Trotter
      script.write("  fi\n")
225 eb58f9b1 Guido Trotter
    script.write("fi\n\n")
226 eb58f9b1 Guido Trotter
    # As much as we'd like to put this in our _ROOT_DIR, that will happen to be
227 eb58f9b1 Guido Trotter
    # mounted noexec sometimes, so we'll have to find another place.
228 eb58f9b1 Guido Trotter
    (tmpfd, tmpfile_name) = tempfile.mkstemp()
229 eb58f9b1 Guido Trotter
    tmpfile = os.fdopen(tmpfd, 'w')
230 d73ef63f Michael Hanselmann
    try:
231 d73ef63f Michael Hanselmann
      tmpfile.write(script.getvalue())
232 d73ef63f Michael Hanselmann
    finally:
233 d73ef63f Michael Hanselmann
      tmpfile.close()
234 eb58f9b1 Guido Trotter
    os.chmod(tmpfile_name, 0755)
235 eb58f9b1 Guido Trotter
    return tmpfile_name
236 eb58f9b1 Guido Trotter
237 eb58f9b1 Guido Trotter
  def ListInstances(self):
238 eb58f9b1 Guido Trotter
    """Get the list of running instances.
239 eb58f9b1 Guido Trotter

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

243 eb58f9b1 Guido Trotter
    """
244 eb58f9b1 Guido Trotter
    result = []
245 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
246 08137f9e Iustin Pop
      filename = "%s/%s" % (self._PIDS_DIR, name)
247 08137f9e Iustin Pop
      if utils.IsProcessAlive(utils.ReadPidFile(filename)):
248 eb58f9b1 Guido Trotter
        result.append(name)
249 eb58f9b1 Guido Trotter
    return result
250 eb58f9b1 Guido Trotter
251 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
252 eb58f9b1 Guido Trotter
    """Get instance properties.
253 eb58f9b1 Guido Trotter

254 c41eea6e Iustin Pop
    @param instance_name: the instance name
255 c41eea6e Iustin Pop

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

258 eb58f9b1 Guido Trotter
    """
259 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
260 1f8b3a27 Guido Trotter
    if not alive:
261 eb58f9b1 Guido Trotter
      return None
262 eb58f9b1 Guido Trotter
263 eb58f9b1 Guido Trotter
    cmdline_file = "/proc/%s/cmdline" % pid
264 eb58f9b1 Guido Trotter
    try:
265 1e37ad45 Michael Hanselmann
      cmdline = utils.ReadFile(cmdline_file)
266 90c024f6 Guido Trotter
    except EnvironmentError, err:
267 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to list instance %s: %s" %
268 eb58f9b1 Guido Trotter
                                   (instance_name, err))
269 eb58f9b1 Guido Trotter
270 eb58f9b1 Guido Trotter
    memory = 0
271 eb58f9b1 Guido Trotter
    vcpus = 0
272 eb58f9b1 Guido Trotter
    stat = "---b-"
273 eb58f9b1 Guido Trotter
    times = "0"
274 eb58f9b1 Guido Trotter
275 eb58f9b1 Guido Trotter
    arg_list = cmdline.split('\x00')
276 eb58f9b1 Guido Trotter
    while arg_list:
277 eb58f9b1 Guido Trotter
      arg =  arg_list.pop(0)
278 eb58f9b1 Guido Trotter
      if arg == '-m':
279 2a7e887b Guido Trotter
        memory = int(arg_list.pop(0))
280 eb58f9b1 Guido Trotter
      elif arg == '-smp':
281 2a7e887b Guido Trotter
        vcpus = int(arg_list.pop(0))
282 eb58f9b1 Guido Trotter
283 eb58f9b1 Guido Trotter
    return (instance_name, pid, memory, vcpus, stat, times)
284 eb58f9b1 Guido Trotter
285 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
286 eb58f9b1 Guido Trotter
    """Get properties of all instances.
287 eb58f9b1 Guido Trotter

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

290 eb58f9b1 Guido Trotter
    """
291 eb58f9b1 Guido Trotter
    data = []
292 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
293 08137f9e Iustin Pop
      filename = "%s/%s" % (self._PIDS_DIR, name)
294 08137f9e Iustin Pop
      if utils.IsProcessAlive(utils.ReadPidFile(filename)):
295 00ad5362 Guido Trotter
        try:
296 00ad5362 Guido Trotter
          info = self.GetInstanceInfo(name)
297 1122eb25 Iustin Pop
        except errors.HypervisorError:
298 00ad5362 Guido Trotter
          continue
299 00ad5362 Guido Trotter
        if info:
300 00ad5362 Guido Trotter
          data.append(info)
301 eb58f9b1 Guido Trotter
302 eb58f9b1 Guido Trotter
    return data
303 eb58f9b1 Guido Trotter
304 07813a9e Iustin Pop
  def _GenerateKVMRuntime(self, instance, block_devices):
305 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
306 eb58f9b1 Guido Trotter

307 eb58f9b1 Guido Trotter
    """
308 98ec75d6 Iustin Pop
    pidfile  = self._InstancePidFile(instance.name)
309 eb58f9b1 Guido Trotter
    kvm = constants.KVM_PATH
310 eb58f9b1 Guido Trotter
    kvm_cmd = [kvm]
311 8b3fd458 Iustin Pop
    kvm_cmd.extend(['-m', instance.beparams[constants.BE_MEMORY]])
312 8b3fd458 Iustin Pop
    kvm_cmd.extend(['-smp', instance.beparams[constants.BE_VCPUS]])
313 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-pidfile', pidfile])
314 eb58f9b1 Guido Trotter
    # used just by the vnc server, if enabled
315 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-name', instance.name])
316 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-daemonize'])
317 6b5605e8 Iustin Pop
    if not instance.hvparams[constants.HV_ACPI]:
318 eb58f9b1 Guido Trotter
      kvm_cmd.extend(['-no-acpi'])
319 eb58f9b1 Guido Trotter
320 a985b417 Iustin Pop
    hvp = instance.hvparams
321 835528af Iustin Pop
    boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
322 835528af Iustin Pop
    boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
323 835528af Iustin Pop
    boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
324 8745c3d7 Guido Trotter
325 8745c3d7 Guido Trotter
    if boot_network:
326 8745c3d7 Guido Trotter
      kvm_cmd.extend(['-boot', 'n'])
327 1213604d Guido Trotter
328 a985b417 Iustin Pop
    disk_type = hvp[constants.HV_DISK_TYPE]
329 1213604d Guido Trotter
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
330 1213604d Guido Trotter
      if_val = ',if=virtio'
331 1213604d Guido Trotter
    else:
332 1213604d Guido Trotter
      if_val = ',if=%s' % disk_type
333 19572932 Iustin Pop
    # Cache mode
334 19572932 Iustin Pop
    disk_cache = hvp[constants.HV_DISK_CACHE]
335 19572932 Iustin Pop
    if disk_cache != constants.HT_CACHE_DEFAULT:
336 19572932 Iustin Pop
      cache_val = ",cache=%s" % disk_cache
337 19572932 Iustin Pop
    else:
338 19572932 Iustin Pop
      cache_val = ""
339 069cfbf1 Iustin Pop
    for cfdev, dev_path in block_devices:
340 d34b16d7 Iustin Pop
      if cfdev.mode != constants.DISK_RDWR:
341 d34b16d7 Iustin Pop
        raise errors.HypervisorError("Instance has read-only disks which"
342 d34b16d7 Iustin Pop
                                     " are not supported by KVM")
343 eb58f9b1 Guido Trotter
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
344 66d5dbef Guido Trotter
      if boot_disk:
345 9dd363eb Guido Trotter
        kvm_cmd.extend(['-boot', 'c'])
346 eb58f9b1 Guido Trotter
        boot_val = ',boot=on'
347 8745c3d7 Guido Trotter
        # We only boot from the first disk
348 66d5dbef Guido Trotter
        boot_disk = False
349 eb58f9b1 Guido Trotter
      else:
350 eb58f9b1 Guido Trotter
        boot_val = ''
351 eb58f9b1 Guido Trotter
352 19572932 Iustin Pop
      drive_val = 'file=%s,format=raw%s%s%s' % (dev_path, if_val, boot_val,
353 19572932 Iustin Pop
                                                cache_val)
354 eb58f9b1 Guido Trotter
      kvm_cmd.extend(['-drive', drive_val])
355 eb58f9b1 Guido Trotter
356 a985b417 Iustin Pop
    iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
357 66d5dbef Guido Trotter
    if iso_image:
358 9dd363eb Guido Trotter
      options = ',format=raw,media=cdrom'
359 66d5dbef Guido Trotter
      if boot_cdrom:
360 9dd363eb Guido Trotter
        kvm_cmd.extend(['-boot', 'd'])
361 66d5dbef Guido Trotter
        options = '%s,boot=on' % options
362 9dd363eb Guido Trotter
      else:
363 9dd363eb Guido Trotter
        options = '%s,if=virtio' % options
364 66d5dbef Guido Trotter
      drive_val = 'file=%s%s' % (iso_image, options)
365 66d5dbef Guido Trotter
      kvm_cmd.extend(['-drive', drive_val])
366 66d5dbef Guido Trotter
367 a985b417 Iustin Pop
    kernel_path = hvp[constants.HV_KERNEL_PATH]
368 df5ab9f0 Guido Trotter
    if kernel_path:
369 df5ab9f0 Guido Trotter
      kvm_cmd.extend(['-kernel', kernel_path])
370 a985b417 Iustin Pop
      initrd_path = hvp[constants.HV_INITRD_PATH]
371 df5ab9f0 Guido Trotter
      if initrd_path:
372 df5ab9f0 Guido Trotter
        kvm_cmd.extend(['-initrd', initrd_path])
373 07813a9e Iustin Pop
      root_append = ['root=%s' % hvp[constants.HV_ROOT_PATH],
374 07813a9e Iustin Pop
                     hvp[constants.HV_KERNEL_ARGS]]
375 07813a9e Iustin Pop
      if hvp[constants.HV_SERIAL_CONSOLE]:
376 07813a9e Iustin Pop
        root_append.append('console=ttyS0,38400')
377 07813a9e Iustin Pop
      kvm_cmd.extend(['-append', ' '.join(root_append)])
378 eb58f9b1 Guido Trotter
379 a985b417 Iustin Pop
    mouse_type = hvp[constants.HV_USB_MOUSE]
380 11344a50 Guido Trotter
    if mouse_type:
381 11344a50 Guido Trotter
      kvm_cmd.extend(['-usb'])
382 11344a50 Guido Trotter
      kvm_cmd.extend(['-usbdevice', mouse_type])
383 11344a50 Guido Trotter
384 a985b417 Iustin Pop
    vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
385 8470c8db Guido Trotter
    if vnc_bind_address:
386 8447f52b Guido Trotter
      if utils.IsValidIP(vnc_bind_address):
387 377d74c9 Guido Trotter
        if instance.network_port > constants.VNC_BASE_PORT:
388 377d74c9 Guido Trotter
          display = instance.network_port - constants.VNC_BASE_PORT
389 8447f52b Guido Trotter
          if vnc_bind_address == '0.0.0.0':
390 8447f52b Guido Trotter
            vnc_arg = ':%d' % (display)
391 8447f52b Guido Trotter
          else:
392 19498d6c Guido Trotter
            vnc_arg = '%s:%d' % (vnc_bind_address, display)
393 8470c8db Guido Trotter
        else:
394 8447f52b Guido Trotter
          logging.error("Network port is not a valid VNC display (%d < %d)."
395 07b8a2b5 Iustin Pop
                        " Not starting VNC", instance.network_port,
396 07b8a2b5 Iustin Pop
                        constants.VNC_BASE_PORT)
397 8447f52b Guido Trotter
          vnc_arg = 'none'
398 8b2d1013 Guido Trotter
399 8b2d1013 Guido Trotter
        # Only allow tls and other option when not binding to a file, for now.
400 8b2d1013 Guido Trotter
        # kvm/qemu gets confused otherwise about the filename to use.
401 8b2d1013 Guido Trotter
        vnc_append = ''
402 a985b417 Iustin Pop
        if hvp[constants.HV_VNC_TLS]:
403 8b2d1013 Guido Trotter
          vnc_append = '%s,tls' % vnc_append
404 a985b417 Iustin Pop
          if hvp[constants.HV_VNC_X509_VERIFY]:
405 8b2d1013 Guido Trotter
            vnc_append = '%s,x509verify=%s' % (vnc_append,
406 a985b417 Iustin Pop
                                               hvp[constants.HV_VNC_X509])
407 a985b417 Iustin Pop
          elif hvp[constants.HV_VNC_X509]:
408 8b2d1013 Guido Trotter
            vnc_append = '%s,x509=%s' % (vnc_append,
409 a985b417 Iustin Pop
                                         hvp[constants.HV_VNC_X509])
410 6e6bb8d5 Guido Trotter
        if hvp[constants.HV_VNC_PASSWORD_FILE]:
411 6e6bb8d5 Guido Trotter
          vnc_append = '%s,password' % vnc_append
412 6e6bb8d5 Guido Trotter
413 8b2d1013 Guido Trotter
        vnc_arg = '%s%s' % (vnc_arg, vnc_append)
414 8b2d1013 Guido Trotter
415 8470c8db Guido Trotter
      else:
416 8b2d1013 Guido Trotter
        vnc_arg = 'unix:%s/%s.vnc' % (vnc_bind_address, instance.name)
417 8b2d1013 Guido Trotter
418 8447f52b Guido Trotter
      kvm_cmd.extend(['-vnc', vnc_arg])
419 8470c8db Guido Trotter
    else:
420 8470c8db Guido Trotter
      kvm_cmd.extend(['-nographic'])
421 8470c8db Guido Trotter
422 69b99987 Michael Hanselmann
    monitor_dev = ("unix:%s,server,nowait" %
423 69b99987 Michael Hanselmann
                   self._InstanceMonitor(instance.name))
424 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-monitor', monitor_dev])
425 a985b417 Iustin Pop
    if hvp[constants.HV_SERIAL_CONSOLE]:
426 a985b417 Iustin Pop
      serial_dev = ('unix:%s,server,nowait' %
427 a985b417 Iustin Pop
                    self._InstanceSerial(instance.name))
428 a2faf9ee Guido Trotter
      kvm_cmd.extend(['-serial', serial_dev])
429 a2faf9ee Guido Trotter
    else:
430 a2faf9ee Guido Trotter
      kvm_cmd.extend(['-serial', 'none'])
431 eb58f9b1 Guido Trotter
432 6b970cef Jun Futagawa
    if hvp[constants.HV_USE_LOCALTIME]:
433 6b970cef Jun Futagawa
      kvm_cmd.extend(['-localtime'])
434 6b970cef Jun Futagawa
435 ee5f20b0 Guido Trotter
    # Save the current instance nics, but defer their expansion as parameters,
436 ee5f20b0 Guido Trotter
    # as we'll need to generate executable temp files for them.
437 ee5f20b0 Guido Trotter
    kvm_nics = instance.nics
438 a985b417 Iustin Pop
    hvparams = hvp
439 ee5f20b0 Guido Trotter
440 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
441 ee5f20b0 Guido Trotter
442 38e250ba Guido Trotter
  def _WriteKVMRuntime(self, instance_name, data):
443 38e250ba Guido Trotter
    """Write an instance's KVM runtime
444 38e250ba Guido Trotter

445 38e250ba Guido Trotter
    """
446 38e250ba Guido Trotter
    try:
447 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
448 38e250ba Guido Trotter
                      data=data)
449 90c024f6 Guido Trotter
    except EnvironmentError, err:
450 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
451 38e250ba Guido Trotter
452 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
453 38e250ba Guido Trotter
    """Read an instance's KVM runtime
454 38e250ba Guido Trotter

455 38e250ba Guido Trotter
    """
456 38e250ba Guido Trotter
    try:
457 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
458 90c024f6 Guido Trotter
    except EnvironmentError, err:
459 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
460 38e250ba Guido Trotter
    return file_content
461 38e250ba Guido Trotter
462 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
463 38e250ba Guido Trotter
    """Save an instance's KVM runtime
464 38e250ba Guido Trotter

465 38e250ba Guido Trotter
    """
466 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
467 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
468 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
469 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
470 38e250ba Guido Trotter
471 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
472 38e250ba Guido Trotter
    """Load an instance's KVM runtime
473 38e250ba Guido Trotter

474 38e250ba Guido Trotter
    """
475 30e42c4e Guido Trotter
    if not serialized_runtime:
476 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
477 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
478 c2672466 Guido Trotter
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
479 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
480 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
481 38e250ba Guido Trotter
482 30e42c4e Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
483 ee5f20b0 Guido Trotter
    """Execute a KVM cmd, after completing it with some last minute data
484 ee5f20b0 Guido Trotter

485 30e42c4e Guido Trotter
    @type incoming: tuple of strings
486 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
487 30e42c4e Guido Trotter

488 ee5f20b0 Guido Trotter
    """
489 6e6bb8d5 Guido Trotter
    hvp = instance.hvparams
490 5905901c Iustin Pop
    name = instance.name
491 5905901c Iustin Pop
    self._CheckDown(name)
492 ee5f20b0 Guido Trotter
493 ee5f20b0 Guido Trotter
    temp_files = []
494 ee5f20b0 Guido Trotter
495 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
496 ee5f20b0 Guido Trotter
497 ee5f20b0 Guido Trotter
    if not kvm_nics:
498 ee5f20b0 Guido Trotter
      kvm_cmd.extend(['-net', 'none'])
499 ee5f20b0 Guido Trotter
    else:
500 37f88dc6 Guido Trotter
      nic_type = hvparams[constants.HV_NIC_TYPE]
501 37f88dc6 Guido Trotter
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
502 37f88dc6 Guido Trotter
        nic_model = "model=virtio"
503 37f88dc6 Guido Trotter
      else:
504 37f88dc6 Guido Trotter
        nic_model = "model=%s" % nic_type
505 37f88dc6 Guido Trotter
506 ee5f20b0 Guido Trotter
      for nic_seq, nic in enumerate(kvm_nics):
507 37f88dc6 Guido Trotter
        nic_val = "nic,macaddr=%s,%s" % (nic.mac, nic_model)
508 ee5f20b0 Guido Trotter
        script = self._WriteNetScript(instance, nic_seq, nic)
509 ee5f20b0 Guido Trotter
        kvm_cmd.extend(['-net', nic_val])
510 ee5f20b0 Guido Trotter
        kvm_cmd.extend(['-net', 'tap,script=%s' % script])
511 ee5f20b0 Guido Trotter
        temp_files.append(script)
512 ee5f20b0 Guido Trotter
513 30e42c4e Guido Trotter
    if incoming:
514 30e42c4e Guido Trotter
      target, port = incoming
515 30e42c4e Guido Trotter
      kvm_cmd.extend(['-incoming', 'tcp:%s:%s' % (target, port)])
516 30e42c4e Guido Trotter
517 6e6bb8d5 Guido Trotter
    vnc_pwd_file = hvp[constants.HV_VNC_PASSWORD_FILE]
518 6e6bb8d5 Guido Trotter
    vnc_pwd = None
519 6e6bb8d5 Guido Trotter
    if vnc_pwd_file:
520 6e6bb8d5 Guido Trotter
      try:
521 6e6bb8d5 Guido Trotter
        vnc_pwd = utils.ReadFile(vnc_pwd_file)
522 6e6bb8d5 Guido Trotter
      except EnvironmentError, err:
523 6e6bb8d5 Guido Trotter
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
524 6e6bb8d5 Guido Trotter
                                     % (vnc_pwd_file, err))
525 6e6bb8d5 Guido Trotter
526 eb58f9b1 Guido Trotter
    result = utils.RunCmd(kvm_cmd)
527 eb58f9b1 Guido Trotter
    if result.failed:
528 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
529 5905901c Iustin Pop
                                   (name, result.fail_reason, result.output))
530 eb58f9b1 Guido Trotter
531 5905901c Iustin Pop
    if not self._InstancePidAlive(name)[2]:
532 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s" % name)
533 eb58f9b1 Guido Trotter
534 6e6bb8d5 Guido Trotter
    if vnc_pwd:
535 6e6bb8d5 Guido Trotter
      change_cmd = 'change vnc password %s' % vnc_pwd
536 6e6bb8d5 Guido Trotter
      self._CallMonitorCommand(instance.name, change_cmd)
537 6e6bb8d5 Guido Trotter
538 08137f9e Iustin Pop
    for filename in temp_files:
539 08137f9e Iustin Pop
      utils.RemoveFile(filename)
540 eb58f9b1 Guido Trotter
541 07813a9e Iustin Pop
  def StartInstance(self, instance, block_devices):
542 ee5f20b0 Guido Trotter
    """Start an instance.
543 ee5f20b0 Guido Trotter

544 ee5f20b0 Guido Trotter
    """
545 5905901c Iustin Pop
    self._CheckDown(instance.name)
546 07813a9e Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices)
547 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
548 ee5f20b0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
549 ee5f20b0 Guido Trotter
550 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
551 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
552 6567aff3 Guido Trotter

553 6567aff3 Guido Trotter
    """
554 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
555 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
556 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
557 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
558 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
559 6567aff3 Guido Trotter
    if result.failed:
560 6567aff3 Guido Trotter
      msg = ("Failed to send command '%s' to instance %s."
561 6567aff3 Guido Trotter
             " output: %s, error: %s, fail_reason: %s" %
562 9798fcae Guido Trotter
             (command, instance_name,
563 9798fcae Guido Trotter
              result.stdout, result.stderr, result.fail_reason))
564 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
565 6567aff3 Guido Trotter
566 6567aff3 Guido Trotter
    return result
567 6567aff3 Guido Trotter
568 07b49e41 Guido Trotter
  def StopInstance(self, instance, force=False, retry=False):
569 eb58f9b1 Guido Trotter
    """Stop an instance.
570 eb58f9b1 Guido Trotter

571 eb58f9b1 Guido Trotter
    """
572 1f8b3a27 Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance.name)
573 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
574 6b5605e8 Iustin Pop
      if force or not instance.hvparams[constants.HV_ACPI]:
575 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
576 eb58f9b1 Guido Trotter
      else:
577 4ad45119 Guido Trotter
        self._CallMonitorCommand(instance.name, 'system_powerdown')
578 eb58f9b1 Guido Trotter
579 eb58f9b1 Guido Trotter
    if not utils.IsProcessAlive(pid):
580 7e66c35b Guido Trotter
      self._RemoveInstanceRuntimeFiles(pidfile, instance.name)
581 6567aff3 Guido Trotter
      return True
582 6567aff3 Guido Trotter
    else:
583 6567aff3 Guido Trotter
      return False
584 eb58f9b1 Guido Trotter
585 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
586 eb58f9b1 Guido Trotter
    """Reboot an instance.
587 eb58f9b1 Guido Trotter

588 eb58f9b1 Guido Trotter
    """
589 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
590 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
591 eb58f9b1 Guido Trotter
    # to shutdown and restart.
592 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
593 1f8b3a27 Guido Trotter
    if not alive:
594 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
595 78411c60 Iustin Pop
                                   " not running" % instance.name)
596 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
597 f02881e0 Guido Trotter
    # ...first load it...
598 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
599 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
600 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
601 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
602 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
603 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
604 f02881e0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
605 eb58f9b1 Guido Trotter
606 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
607 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
608 30e42c4e Guido Trotter

609 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
610 30e42c4e Guido Trotter
    @param instance: instance to be migrated
611 30e42c4e Guido Trotter
    @rtype: string
612 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
613 30e42c4e Guido Trotter

614 30e42c4e Guido Trotter
    """
615 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
616 30e42c4e Guido Trotter
617 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
618 30e42c4e Guido Trotter
    """Prepare to accept an instance.
619 30e42c4e Guido Trotter

620 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
621 30e42c4e Guido Trotter
    @param instance: instance to be accepted
622 30e42c4e Guido Trotter
    @type info: string
623 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
624 30e42c4e Guido Trotter
    @type target: string
625 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
626 30e42c4e Guido Trotter

627 30e42c4e Guido Trotter
    """
628 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
629 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
630 30e42c4e Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
631 30e42c4e Guido Trotter
632 30e42c4e Guido Trotter
  def FinalizeMigration(self, instance, info, success):
633 30e42c4e Guido Trotter
    """Finalize an instance migration.
634 30e42c4e Guido Trotter

635 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
636 30e42c4e Guido Trotter

637 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
638 30e42c4e Guido Trotter
    @param instance: instance whose migration is being aborted
639 30e42c4e Guido Trotter

640 30e42c4e Guido Trotter
    """
641 30e42c4e Guido Trotter
    if success:
642 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
643 30e42c4e Guido Trotter
    else:
644 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
645 30e42c4e Guido Trotter
646 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
647 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
648 30e42c4e Guido Trotter

649 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
650 30e42c4e Guido Trotter
    currently running.
651 30e42c4e Guido Trotter

652 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
653 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
654 30e42c4e Guido Trotter
    @type target: string
655 30e42c4e Guido Trotter
    @param target: ip address of the target node
656 30e42c4e Guido Trotter
    @type live: boolean
657 30e42c4e Guido Trotter
    @param live: perform a live migration
658 30e42c4e Guido Trotter

659 30e42c4e Guido Trotter
    """
660 58d38b02 Iustin Pop
    instance_name = instance.name
661 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
662 30e42c4e Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
663 30e42c4e Guido Trotter
    if not alive:
664 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
665 30e42c4e Guido Trotter
666 50716be0 Iustin Pop
    if not utils.TcpPing(target, port, live_port_needed=True):
667 50716be0 Iustin Pop
      raise errors.HypervisorError("Remote host %s not listening on port"
668 50716be0 Iustin Pop
                                   " %s, cannot migrate" % (target, port))
669 50716be0 Iustin Pop
670 30e42c4e Guido Trotter
    if not live:
671 30e42c4e Guido Trotter
      self._CallMonitorCommand(instance_name, 'stop')
672 30e42c4e Guido Trotter
673 641ae041 Iustin Pop
    migrate_command = 'migrate -d tcp:%s:%s' % (target, port)
674 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
675 30e42c4e Guido Trotter
676 30e42c4e Guido Trotter
    info_command = 'info migrate'
677 30e42c4e Guido Trotter
    done = False
678 30e42c4e Guido Trotter
    while not done:
679 30e42c4e Guido Trotter
      result = self._CallMonitorCommand(instance_name, info_command)
680 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
681 30e42c4e Guido Trotter
      if not match:
682 30e42c4e Guido Trotter
        raise errors.HypervisorError("Unknown 'info migrate' result: %s" %
683 30e42c4e Guido Trotter
                                     result.stdout)
684 30e42c4e Guido Trotter
      else:
685 30e42c4e Guido Trotter
        status = match.group(1)
686 30e42c4e Guido Trotter
        if status == 'completed':
687 30e42c4e Guido Trotter
          done = True
688 30e42c4e Guido Trotter
        elif status == 'active':
689 30e42c4e Guido Trotter
          time.sleep(2)
690 c087266c Guido Trotter
        elif status == 'failed' or status == 'cancelled':
691 c087266c Guido Trotter
          if not live:
692 c087266c Guido Trotter
            self._CallMonitorCommand(instance_name, 'cont')
693 c087266c Guido Trotter
          raise errors.HypervisorError("Migration %s at the kvm level" %
694 c087266c Guido Trotter
                                       status)
695 30e42c4e Guido Trotter
        else:
696 07b8a2b5 Iustin Pop
          logging.info("KVM: unknown migration status '%s'", status)
697 30e42c4e Guido Trotter
          time.sleep(2)
698 30e42c4e Guido Trotter
699 30e42c4e Guido Trotter
    utils.KillProcess(pid)
700 7b381438 Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
701 30e42c4e Guido Trotter
702 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
703 eb58f9b1 Guido Trotter
    """Return information about the node.
704 eb58f9b1 Guido Trotter

705 572e52bf Iustin Pop
    This is just a wrapper over the base GetLinuxNodeInfo method.
706 572e52bf Iustin Pop

707 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
708 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
709 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
710 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
711 eb58f9b1 Guido Trotter

712 eb58f9b1 Guido Trotter
    """
713 572e52bf Iustin Pop
    return self.GetLinuxNodeInfo()
714 eb58f9b1 Guido Trotter
715 637ce7f9 Guido Trotter
  @classmethod
716 5431b2e4 Guido Trotter
  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
717 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
718 eb58f9b1 Guido Trotter

719 eb58f9b1 Guido Trotter
    """
720 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
721 86d6bc2a Guido Trotter
      shell_command = ("%s STDIO,%s UNIX-CONNECT:%s" %
722 86d6bc2a Guido Trotter
                       (constants.SOCAT_PATH, cls._SocatUnixConsoleParams(),
723 a2faf9ee Guido Trotter
                        utils.ShellQuote(cls._InstanceSerial(instance.name))))
724 a2faf9ee Guido Trotter
    else:
725 a2faf9ee Guido Trotter
      shell_command = "echo 'No serial shell for instance %s'" % instance.name
726 3be34f57 Guido Trotter
727 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
728 3be34f57 Guido Trotter
    if vnc_bind_address:
729 377d74c9 Guido Trotter
      if instance.network_port > constants.VNC_BASE_PORT:
730 377d74c9 Guido Trotter
        display = instance.network_port - constants.VNC_BASE_PORT
731 3be34f57 Guido Trotter
        vnc_command = ("echo 'Instance has VNC listening on %s:%d"
732 3be34f57 Guido Trotter
                       " (display: %d)'" % (vnc_bind_address,
733 3be34f57 Guido Trotter
                                            instance.network_port,
734 3be34f57 Guido Trotter
                                            display))
735 3be34f57 Guido Trotter
        shell_command = "%s; %s" % (vnc_command, shell_command)
736 3be34f57 Guido Trotter
737 a2faf9ee Guido Trotter
    return shell_command
738 eb58f9b1 Guido Trotter
739 eb58f9b1 Guido Trotter
  def Verify(self):
740 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
741 eb58f9b1 Guido Trotter

742 eb58f9b1 Guido Trotter
    Check that the binary exists.
743 eb58f9b1 Guido Trotter

744 eb58f9b1 Guido Trotter
    """
745 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
746 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
747 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
748 14aa53cb Guido Trotter
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
749 14aa53cb Guido Trotter
750 6b5605e8 Iustin Pop
751 6b5605e8 Iustin Pop
  @classmethod
752 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
753 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
754 6b5605e8 Iustin Pop

755 6b5605e8 Iustin Pop
    @type hvparams:  dict
756 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
757 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
758 6b5605e8 Iustin Pop

759 6b5605e8 Iustin Pop
    """
760 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
761 6b5605e8 Iustin Pop
762 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
763 df5ab9f0 Guido Trotter
    if kernel_path:
764 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
765 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
766 205ab586 Iustin Pop
                                     " if a kernel is defined")
767 6b5605e8 Iustin Pop
768 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
769 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
770 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
771 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
772 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
773 66d5dbef Guido Trotter
774 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
775 66d5dbef Guido Trotter
776 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
777 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
778 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
779 835528af Iustin Pop
                                   " ISO path")
780 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_NETWORK and
781 205ab586 Iustin Pop
        hvparams[constants.HV_NIC_TYPE] == constants.HT_NIC_PARAVIRTUAL):
782 8745c3d7 Guido Trotter
      raise errors.HypervisorError("Cannot boot from a paravirtual NIC. Please"
783 835528af Iustin Pop
                                   " change the NIC type.")
784 f5118ade Iustin Pop
785 f5118ade Iustin Pop
  @classmethod
786 f5118ade Iustin Pop
  def PowercycleNode(cls):
787 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
788 f5118ade Iustin Pop

789 f5118ade Iustin Pop
    """
790 f5118ade Iustin Pop
    cls.LinuxPowercycle()