Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (31.9 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 d19d94db Guido Trotter
import pwd
33 eb58f9b1 Guido Trotter
from cStringIO import StringIO
34 eb58f9b1 Guido Trotter
35 eb58f9b1 Guido Trotter
from ganeti import utils
36 eb58f9b1 Guido Trotter
from ganeti import constants
37 eb58f9b1 Guido Trotter
from ganeti import errors
38 38e250ba Guido Trotter
from ganeti import serializer
39 38e250ba Guido Trotter
from ganeti import objects
40 eb58f9b1 Guido Trotter
from ganeti.hypervisor import hv_base
41 eb58f9b1 Guido Trotter
42 eb58f9b1 Guido Trotter
43 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
44 c4469f75 Guido Trotter
  """KVM hypervisor interface"""
45 eb58f9b1 Guido Trotter
46 eb58f9b1 Guido Trotter
  _ROOT_DIR = constants.RUN_GANETI_DIR + "/kvm-hypervisor"
47 a1d79fc6 Guido Trotter
  _PIDS_DIR = _ROOT_DIR + "/pid" # contains live instances pids
48 7548396c Guido Trotter
  _UIDS_DIR = _ROOT_DIR + "/uid" # contains instances reserved uids
49 a1d79fc6 Guido Trotter
  _CTRL_DIR = _ROOT_DIR + "/ctrl" # contains instances control sockets
50 a1d79fc6 Guido Trotter
  _CONF_DIR = _ROOT_DIR + "/conf" # contains instances startup data
51 7548396c Guido Trotter
  _DIRS = [_ROOT_DIR, _PIDS_DIR, _UIDS_DIR, _CTRL_DIR, _CONF_DIR]
52 eb58f9b1 Guido Trotter
53 205ab586 Iustin Pop
  PARAMETERS = {
54 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK,
55 205ab586 Iustin Pop
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
56 205ab586 Iustin Pop
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
57 205ab586 Iustin Pop
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
58 205ab586 Iustin Pop
    constants.HV_ACPI: hv_base.NO_CHECK,
59 205ab586 Iustin Pop
    constants.HV_SERIAL_CONSOLE: hv_base.NO_CHECK,
60 d73ef63f Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS:
61 d73ef63f Michael Hanselmann
      (False, lambda x: (utils.IsValidIP(x) or utils.IsNormAbsPath(x)),
62 d73ef63f Michael Hanselmann
       "the VNC bind address must be either a valid IP address or an absolute"
63 d73ef63f Michael Hanselmann
       " pathname", None, None),
64 205ab586 Iustin Pop
    constants.HV_VNC_TLS: hv_base.NO_CHECK,
65 205ab586 Iustin Pop
    constants.HV_VNC_X509: hv_base.OPT_DIR_CHECK,
66 205ab586 Iustin Pop
    constants.HV_VNC_X509_VERIFY: hv_base.NO_CHECK,
67 6e6bb8d5 Guido Trotter
    constants.HV_VNC_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
68 205ab586 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
69 d73ef63f Michael Hanselmann
    constants.HV_BOOT_ORDER:
70 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
71 d73ef63f Michael Hanselmann
    constants.HV_NIC_TYPE:
72 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
73 d73ef63f Michael Hanselmann
    constants.HV_DISK_TYPE:
74 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
75 d73ef63f Michael Hanselmann
    constants.HV_USB_MOUSE:
76 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
77 78411c60 Iustin Pop
    constants.HV_MIGRATION_PORT: hv_base.NET_PORT_CHECK,
78 6b970cef Jun Futagawa
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
79 19572932 Iustin Pop
    constants.HV_DISK_CACHE:
80 19572932 Iustin Pop
      hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
81 d19d94db Guido Trotter
    constants.HV_SECURITY_MODEL:
82 d19d94db Guido Trotter
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_SM_TYPES),
83 d19d94db Guido Trotter
    constants.HV_SECURITY_DOMAIN: hv_base.NO_CHECK,
84 7ba594c0 Guido Trotter
    constants.HV_KVM_FLAG:
85 7ba594c0 Guido Trotter
      hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES),
86 205ab586 Iustin Pop
    }
87 6b5605e8 Iustin Pop
88 30e42c4e Guido Trotter
  _MIGRATION_STATUS_RE = re.compile('Migration\s+status:\s+(\w+)',
89 30e42c4e Guido Trotter
                                    re.M | re.I)
90 c4e388a5 Guido Trotter
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
91 c4e388a5 Guido Trotter
  _MIGRATION_INFO_RETRY_DELAY = 2
92 30e42c4e Guido Trotter
93 5420ffc9 Guido Trotter
  _KVM_NETWORK_SCRIPT = constants.SYSCONFDIR + "/ganeti/kvm-vif-bridge"
94 5420ffc9 Guido Trotter
95 64bfbc08 Guido Trotter
  ANCILLARY_FILES = [
96 64bfbc08 Guido Trotter
    _KVM_NETWORK_SCRIPT,
97 64bfbc08 Guido Trotter
    ]
98 64bfbc08 Guido Trotter
99 eb58f9b1 Guido Trotter
  def __init__(self):
100 eb58f9b1 Guido Trotter
    hv_base.BaseHypervisor.__init__(self)
101 eb58f9b1 Guido Trotter
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
102 eb58f9b1 Guido Trotter
    # in a tmpfs filesystem or has been otherwise wiped out.
103 29921401 Iustin Pop
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
104 9afb67fe Guido Trotter
    utils.EnsureDirs(dirs)
105 eb58f9b1 Guido Trotter
106 30786fc9 Iustin Pop
  @classmethod
107 30786fc9 Iustin Pop
  def _InstancePidFile(cls, instance_name):
108 98ec75d6 Iustin Pop
    """Returns the instance pidfile.
109 98ec75d6 Iustin Pop

110 98ec75d6 Iustin Pop
    """
111 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
112 98ec75d6 Iustin Pop
113 263b8de6 Guido Trotter
  @classmethod
114 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
115 7548396c Guido Trotter
    """Returns the instance uidfile.
116 7548396c Guido Trotter

117 7548396c Guido Trotter
    """
118 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
119 7548396c Guido Trotter
120 7548396c Guido Trotter
  @classmethod
121 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
122 263b8de6 Guido Trotter
    """Check pid file for instance information.
123 263b8de6 Guido Trotter

124 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
125 263b8de6 Guido Trotter
    information from its command line.
126 263b8de6 Guido Trotter

127 263b8de6 Guido Trotter
    @type pid: string or int
128 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
129 263b8de6 Guido Trotter
    @rtype: tuple
130 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
131 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
132 263b8de6 Guido Trotter

133 263b8de6 Guido Trotter
    """
134 263b8de6 Guido Trotter
    alive = utils.IsProcessAlive(pid)
135 263b8de6 Guido Trotter
    if not alive:
136 263b8de6 Guido Trotter
      raise errors.HypervisorError("Cannot get info for pid %s" % pid)
137 263b8de6 Guido Trotter
138 263b8de6 Guido Trotter
    cmdline_file = utils.PathJoin("/proc", str(pid), "cmdline")
139 263b8de6 Guido Trotter
    try:
140 263b8de6 Guido Trotter
      cmdline = utils.ReadFile(cmdline_file)
141 263b8de6 Guido Trotter
    except EnvironmentError, err:
142 263b8de6 Guido Trotter
      raise errors.HypervisorError("Can't open cmdline file for pid %s: %s" %
143 263b8de6 Guido Trotter
                                   (pid, err))
144 263b8de6 Guido Trotter
145 263b8de6 Guido Trotter
    instance = None
146 263b8de6 Guido Trotter
    memory = 0
147 263b8de6 Guido Trotter
    vcpus = 0
148 263b8de6 Guido Trotter
149 263b8de6 Guido Trotter
    arg_list = cmdline.split('\x00')
150 263b8de6 Guido Trotter
    while arg_list:
151 263b8de6 Guido Trotter
      arg =  arg_list.pop(0)
152 263b8de6 Guido Trotter
      if arg == "-name":
153 263b8de6 Guido Trotter
        instance = arg_list.pop(0)
154 263b8de6 Guido Trotter
      elif arg == "-m":
155 263b8de6 Guido Trotter
        memory = int(arg_list.pop(0))
156 263b8de6 Guido Trotter
      elif arg == "-smp":
157 263b8de6 Guido Trotter
        vcpus = int(arg_list.pop(0))
158 263b8de6 Guido Trotter
159 263b8de6 Guido Trotter
    if instance is None:
160 263b8de6 Guido Trotter
      raise errors.HypervisorError("Pid %s doesn't contain a ganeti kvm"
161 263b8de6 Guido Trotter
                                   " instance" % pid)
162 263b8de6 Guido Trotter
163 263b8de6 Guido Trotter
    return (instance, memory, vcpus)
164 263b8de6 Guido Trotter
165 1f8b3a27 Guido Trotter
  def _InstancePidAlive(self, instance_name):
166 263b8de6 Guido Trotter
    """Returns the instance pidfile, pid, and liveness.
167 263b8de6 Guido Trotter

168 263b8de6 Guido Trotter
    @type instance_name: string
169 263b8de6 Guido Trotter
    @param instance_name: instance name
170 263b8de6 Guido Trotter
    @rtype: tuple
171 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
172 1f8b3a27 Guido Trotter

173 1f8b3a27 Guido Trotter
    """
174 98ec75d6 Iustin Pop
    pidfile = self._InstancePidFile(instance_name)
175 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
176 263b8de6 Guido Trotter
177 263b8de6 Guido Trotter
    alive = False
178 263b8de6 Guido Trotter
    try:
179 263b8de6 Guido Trotter
      cmd_instance = self._InstancePidInfo(pid)[0]
180 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
181 263b8de6 Guido Trotter
    except errors.HypervisorError:
182 263b8de6 Guido Trotter
      pass
183 1f8b3a27 Guido Trotter
184 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
185 1f8b3a27 Guido Trotter
186 5905901c Iustin Pop
  def _CheckDown(self, instance_name):
187 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
188 5905901c Iustin Pop

189 5905901c Iustin Pop
    """
190 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
191 5905901c Iustin Pop
    if alive:
192 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
193 5905901c Iustin Pop
                                   (instance_name, "already running"))
194 5905901c Iustin Pop
195 0df4d98a Guido Trotter
  @classmethod
196 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
197 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
198 c4fbefc8 Guido Trotter

199 c4fbefc8 Guido Trotter
    """
200 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
201 c4fbefc8 Guido Trotter
202 0df4d98a Guido Trotter
  @classmethod
203 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
204 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
205 c4fbefc8 Guido Trotter

206 c4fbefc8 Guido Trotter
    """
207 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
208 c4fbefc8 Guido Trotter
209 86d6bc2a Guido Trotter
  @staticmethod
210 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
211 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
212 86d6bc2a Guido Trotter

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

215 86d6bc2a Guido Trotter
    """
216 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
217 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
218 86d6bc2a Guido Trotter
    else:
219 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
220 86d6bc2a Guido Trotter
221 0df4d98a Guido Trotter
  @classmethod
222 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
223 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
224 38e250ba Guido Trotter

225 38e250ba Guido Trotter
    """
226 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
227 38e250ba Guido Trotter
228 7e66c35b Guido Trotter
  @classmethod
229 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
230 7548396c Guido Trotter
    """Try to read a uid file
231 7548396c Guido Trotter

232 7548396c Guido Trotter
    """
233 7548396c Guido Trotter
    if os.path.exists(uid_file):
234 7548396c Guido Trotter
      try:
235 7548396c Guido Trotter
        uid = int(utils.ReadFile(uid_file))
236 7548396c Guido Trotter
      except EnvironmentError:
237 7548396c Guido Trotter
        logging.warning("Can't read uid file", exc_info=True)
238 7548396c Guido Trotter
        return None
239 7548396c Guido Trotter
      except (TypeError, ValueError):
240 7548396c Guido Trotter
        logging.warning("Can't parse uid file contents", exc_info=True)
241 7548396c Guido Trotter
        return None
242 7548396c Guido Trotter
    return uid
243 7548396c Guido Trotter
244 7548396c Guido Trotter
  @classmethod
245 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
246 7e66c35b Guido Trotter
    """Removes an instance's rutime sockets/files.
247 7e66c35b Guido Trotter

248 7e66c35b Guido Trotter
    """
249 7e66c35b Guido Trotter
    utils.RemoveFile(pidfile)
250 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
251 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceSerial(instance_name))
252 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
253 7548396c Guido Trotter
    uid_file = cls._InstanceUidFile(instance_name)
254 7548396c Guido Trotter
    uid = cls._TryReadUidFile(uid_file)
255 7548396c Guido Trotter
    utils.RemoveFile(uid_file)
256 7548396c Guido Trotter
    if uid is not None:
257 7548396c Guido Trotter
      uidpool.ReleaseUid(uid)
258 7e66c35b Guido Trotter
259 eb58f9b1 Guido Trotter
  def _WriteNetScript(self, instance, seq, nic):
260 eb58f9b1 Guido Trotter
    """Write a script to connect a net interface to the proper bridge.
261 eb58f9b1 Guido Trotter

262 eb58f9b1 Guido Trotter
    This can be used by any qemu-type hypervisor.
263 eb58f9b1 Guido Trotter

264 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
265 eb58f9b1 Guido Trotter
    @type instance: instance object
266 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
267 eb58f9b1 Guido Trotter
    @type seq: int
268 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
269 eb58f9b1 Guido Trotter
    @type nic: nic object
270 eb58f9b1 Guido Trotter
    @return: netscript file name
271 eb58f9b1 Guido Trotter
    @rtype: string
272 eb58f9b1 Guido Trotter

273 eb58f9b1 Guido Trotter
    """
274 eb58f9b1 Guido Trotter
    script = StringIO()
275 eb58f9b1 Guido Trotter
    script.write("#!/bin/sh\n")
276 eb58f9b1 Guido Trotter
    script.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
277 e8022bef Vitaly Kuznetsov
    script.write("PATH=$PATH:/sbin:/usr/sbin\n")
278 eb58f9b1 Guido Trotter
    script.write("export INSTANCE=%s\n" % instance.name)
279 eb58f9b1 Guido Trotter
    script.write("export MAC=%s\n" % nic.mac)
280 bef9c750 Guido Trotter
    if nic.ip:
281 bef9c750 Guido Trotter
      script.write("export IP=%s\n" % nic.ip)
282 bef9c750 Guido Trotter
    script.write("export MODE=%s\n" % nic.nicparams[constants.NIC_MODE])
283 bef9c750 Guido Trotter
    if nic.nicparams[constants.NIC_LINK]:
284 bef9c750 Guido Trotter
      script.write("export LINK=%s\n" % nic.nicparams[constants.NIC_LINK])
285 bef9c750 Guido Trotter
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
286 bef9c750 Guido Trotter
      script.write("export BRIDGE=%s\n" % nic.nicparams[constants.NIC_LINK])
287 eb58f9b1 Guido Trotter
    script.write("export INTERFACE=$1\n")
288 eb58f9b1 Guido Trotter
    # TODO: make this configurable at ./configure time
289 5420ffc9 Guido Trotter
    script.write("if [ -x '%s' ]; then\n" % self._KVM_NETWORK_SCRIPT)
290 eb58f9b1 Guido Trotter
    script.write("  # Execute the user-specific vif file\n")
291 5420ffc9 Guido Trotter
    script.write("  %s\n" % self._KVM_NETWORK_SCRIPT)
292 eb58f9b1 Guido Trotter
    script.write("else\n")
293 e8022bef Vitaly Kuznetsov
    script.write("  ifconfig $INTERFACE 0.0.0.0 up\n")
294 bef9c750 Guido Trotter
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
295 bef9c750 Guido Trotter
      script.write("  # Connect the interface to the bridge\n")
296 e8022bef Vitaly Kuznetsov
      script.write("  brctl addif $BRIDGE $INTERFACE\n")
297 bef9c750 Guido Trotter
    elif nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_ROUTED:
298 94c2ed34 Guido Trotter
      if not nic.ip:
299 94c2ed34 Guido Trotter
        raise errors.HypervisorError("nic/%d is routed, but has no ip." % seq)
300 bef9c750 Guido Trotter
      script.write("  # Route traffic targeted at the IP to the interface\n")
301 7c60f7a2 Guido Trotter
      if nic.nicparams[constants.NIC_LINK]:
302 e8022bef Vitaly Kuznetsov
        script.write("  while ip rule del dev $INTERFACE; do :; done\n")
303 e8022bef Vitaly Kuznetsov
        script.write("  ip rule add dev $INTERFACE table $LINK\n")
304 e8022bef Vitaly Kuznetsov
        script.write("  ip route replace $IP table $LINK proto static"
305 d63218ce Guido Trotter
                     " dev $INTERFACE\n")
306 7c60f7a2 Guido Trotter
      else:
307 e8022bef Vitaly Kuznetsov
        script.write("  ip route replace $IP proto static"
308 8866ec86 Guido Trotter
                     " dev $INTERFACE\n")
309 e014f1d0 Guido Trotter
      interface_v4_conf = "/proc/sys/net/ipv4/conf/$INTERFACE"
310 e014f1d0 Guido Trotter
      interface_v6_conf = "/proc/sys/net/ipv6/conf/$INTERFACE"
311 e014f1d0 Guido Trotter
      script.write("  if [ -d %s ]; then\n" % interface_v4_conf)
312 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/proxy_arp\n" % interface_v4_conf)
313 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/forwarding\n" % interface_v4_conf)
314 e014f1d0 Guido Trotter
      script.write("  fi\n")
315 e014f1d0 Guido Trotter
      script.write("  if [ -d %s ]; then\n" % interface_v6_conf)
316 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/proxy_ndp\n" % interface_v6_conf)
317 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/forwarding\n" % interface_v6_conf)
318 e014f1d0 Guido Trotter
      script.write("  fi\n")
319 eb58f9b1 Guido Trotter
    script.write("fi\n\n")
320 eb58f9b1 Guido Trotter
    # As much as we'd like to put this in our _ROOT_DIR, that will happen to be
321 eb58f9b1 Guido Trotter
    # mounted noexec sometimes, so we'll have to find another place.
322 eb58f9b1 Guido Trotter
    (tmpfd, tmpfile_name) = tempfile.mkstemp()
323 eb58f9b1 Guido Trotter
    tmpfile = os.fdopen(tmpfd, 'w')
324 d73ef63f Michael Hanselmann
    try:
325 d73ef63f Michael Hanselmann
      tmpfile.write(script.getvalue())
326 d73ef63f Michael Hanselmann
    finally:
327 d73ef63f Michael Hanselmann
      tmpfile.close()
328 eb58f9b1 Guido Trotter
    os.chmod(tmpfile_name, 0755)
329 eb58f9b1 Guido Trotter
    return tmpfile_name
330 eb58f9b1 Guido Trotter
331 eb58f9b1 Guido Trotter
  def ListInstances(self):
332 eb58f9b1 Guido Trotter
    """Get the list of running instances.
333 eb58f9b1 Guido Trotter

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

337 eb58f9b1 Guido Trotter
    """
338 eb58f9b1 Guido Trotter
    result = []
339 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
340 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
341 eb58f9b1 Guido Trotter
        result.append(name)
342 eb58f9b1 Guido Trotter
    return result
343 eb58f9b1 Guido Trotter
344 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
345 eb58f9b1 Guido Trotter
    """Get instance properties.
346 eb58f9b1 Guido Trotter

347 4fbb3c60 Guido Trotter
    @type instance_name: string
348 c41eea6e Iustin Pop
    @param instance_name: the instance name
349 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
350 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
351 eb58f9b1 Guido Trotter

352 eb58f9b1 Guido Trotter
    """
353 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
354 1f8b3a27 Guido Trotter
    if not alive:
355 eb58f9b1 Guido Trotter
      return None
356 eb58f9b1 Guido Trotter
357 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
358 eb58f9b1 Guido Trotter
    stat = "---b-"
359 eb58f9b1 Guido Trotter
    times = "0"
360 eb58f9b1 Guido Trotter
361 eb58f9b1 Guido Trotter
    return (instance_name, pid, memory, vcpus, stat, times)
362 eb58f9b1 Guido Trotter
363 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
364 eb58f9b1 Guido Trotter
    """Get properties of all instances.
365 eb58f9b1 Guido Trotter

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

368 eb58f9b1 Guido Trotter
    """
369 eb58f9b1 Guido Trotter
    data = []
370 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
371 263b8de6 Guido Trotter
      try:
372 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
373 263b8de6 Guido Trotter
      except errors.HypervisorError:
374 263b8de6 Guido Trotter
        continue
375 263b8de6 Guido Trotter
      if info:
376 263b8de6 Guido Trotter
        data.append(info)
377 eb58f9b1 Guido Trotter
    return data
378 eb58f9b1 Guido Trotter
379 07813a9e Iustin Pop
  def _GenerateKVMRuntime(self, instance, block_devices):
380 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
381 eb58f9b1 Guido Trotter

382 eb58f9b1 Guido Trotter
    """
383 98ec75d6 Iustin Pop
    pidfile  = self._InstancePidFile(instance.name)
384 eb58f9b1 Guido Trotter
    kvm = constants.KVM_PATH
385 eb58f9b1 Guido Trotter
    kvm_cmd = [kvm]
386 c6a39fc2 Guido Trotter
    # used just by the vnc server, if enabled
387 c6a39fc2 Guido Trotter
    kvm_cmd.extend(['-name', instance.name])
388 8b3fd458 Iustin Pop
    kvm_cmd.extend(['-m', instance.beparams[constants.BE_MEMORY]])
389 8b3fd458 Iustin Pop
    kvm_cmd.extend(['-smp', instance.beparams[constants.BE_VCPUS]])
390 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-pidfile', pidfile])
391 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-daemonize'])
392 6b5605e8 Iustin Pop
    if not instance.hvparams[constants.HV_ACPI]:
393 eb58f9b1 Guido Trotter
      kvm_cmd.extend(['-no-acpi'])
394 eb58f9b1 Guido Trotter
395 a985b417 Iustin Pop
    hvp = instance.hvparams
396 835528af Iustin Pop
    boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
397 835528af Iustin Pop
    boot_cdrom = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_CDROM
398 835528af Iustin Pop
    boot_network = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_NETWORK
399 8745c3d7 Guido Trotter
400 7ba594c0 Guido Trotter
    if hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_ENABLED:
401 7ba594c0 Guido Trotter
      kvm_cmd.extend(["-enable-kvm"])
402 7ba594c0 Guido Trotter
    elif hvp[constants.HV_KVM_FLAG] == constants.HT_KVM_DISABLED:
403 7ba594c0 Guido Trotter
      kvm_cmd.extend(["-disable-kvm"])
404 7ba594c0 Guido Trotter
405 8745c3d7 Guido Trotter
    if boot_network:
406 8745c3d7 Guido Trotter
      kvm_cmd.extend(['-boot', 'n'])
407 1213604d Guido Trotter
408 a985b417 Iustin Pop
    disk_type = hvp[constants.HV_DISK_TYPE]
409 1213604d Guido Trotter
    if disk_type == constants.HT_DISK_PARAVIRTUAL:
410 1213604d Guido Trotter
      if_val = ',if=virtio'
411 1213604d Guido Trotter
    else:
412 1213604d Guido Trotter
      if_val = ',if=%s' % disk_type
413 19572932 Iustin Pop
    # Cache mode
414 19572932 Iustin Pop
    disk_cache = hvp[constants.HV_DISK_CACHE]
415 19572932 Iustin Pop
    if disk_cache != constants.HT_CACHE_DEFAULT:
416 19572932 Iustin Pop
      cache_val = ",cache=%s" % disk_cache
417 19572932 Iustin Pop
    else:
418 19572932 Iustin Pop
      cache_val = ""
419 069cfbf1 Iustin Pop
    for cfdev, dev_path in block_devices:
420 d34b16d7 Iustin Pop
      if cfdev.mode != constants.DISK_RDWR:
421 d34b16d7 Iustin Pop
        raise errors.HypervisorError("Instance has read-only disks which"
422 d34b16d7 Iustin Pop
                                     " are not supported by KVM")
423 eb58f9b1 Guido Trotter
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
424 66d5dbef Guido Trotter
      if boot_disk:
425 9dd363eb Guido Trotter
        kvm_cmd.extend(['-boot', 'c'])
426 eb58f9b1 Guido Trotter
        boot_val = ',boot=on'
427 8745c3d7 Guido Trotter
        # We only boot from the first disk
428 66d5dbef Guido Trotter
        boot_disk = False
429 eb58f9b1 Guido Trotter
      else:
430 eb58f9b1 Guido Trotter
        boot_val = ''
431 eb58f9b1 Guido Trotter
432 19572932 Iustin Pop
      drive_val = 'file=%s,format=raw%s%s%s' % (dev_path, if_val, boot_val,
433 19572932 Iustin Pop
                                                cache_val)
434 eb58f9b1 Guido Trotter
      kvm_cmd.extend(['-drive', drive_val])
435 eb58f9b1 Guido Trotter
436 a985b417 Iustin Pop
    iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
437 66d5dbef Guido Trotter
    if iso_image:
438 9dd363eb Guido Trotter
      options = ',format=raw,media=cdrom'
439 66d5dbef Guido Trotter
      if boot_cdrom:
440 9dd363eb Guido Trotter
        kvm_cmd.extend(['-boot', 'd'])
441 66d5dbef Guido Trotter
        options = '%s,boot=on' % options
442 9dd363eb Guido Trotter
      else:
443 9dd363eb Guido Trotter
        options = '%s,if=virtio' % options
444 66d5dbef Guido Trotter
      drive_val = 'file=%s%s' % (iso_image, options)
445 66d5dbef Guido Trotter
      kvm_cmd.extend(['-drive', drive_val])
446 66d5dbef Guido Trotter
447 a985b417 Iustin Pop
    kernel_path = hvp[constants.HV_KERNEL_PATH]
448 df5ab9f0 Guido Trotter
    if kernel_path:
449 df5ab9f0 Guido Trotter
      kvm_cmd.extend(['-kernel', kernel_path])
450 a985b417 Iustin Pop
      initrd_path = hvp[constants.HV_INITRD_PATH]
451 df5ab9f0 Guido Trotter
      if initrd_path:
452 df5ab9f0 Guido Trotter
        kvm_cmd.extend(['-initrd', initrd_path])
453 07813a9e Iustin Pop
      root_append = ['root=%s' % hvp[constants.HV_ROOT_PATH],
454 07813a9e Iustin Pop
                     hvp[constants.HV_KERNEL_ARGS]]
455 07813a9e Iustin Pop
      if hvp[constants.HV_SERIAL_CONSOLE]:
456 07813a9e Iustin Pop
        root_append.append('console=ttyS0,38400')
457 07813a9e Iustin Pop
      kvm_cmd.extend(['-append', ' '.join(root_append)])
458 eb58f9b1 Guido Trotter
459 a985b417 Iustin Pop
    mouse_type = hvp[constants.HV_USB_MOUSE]
460 11344a50 Guido Trotter
    if mouse_type:
461 11344a50 Guido Trotter
      kvm_cmd.extend(['-usb'])
462 11344a50 Guido Trotter
      kvm_cmd.extend(['-usbdevice', mouse_type])
463 11344a50 Guido Trotter
464 a985b417 Iustin Pop
    vnc_bind_address = hvp[constants.HV_VNC_BIND_ADDRESS]
465 8470c8db Guido Trotter
    if vnc_bind_address:
466 8447f52b Guido Trotter
      if utils.IsValidIP(vnc_bind_address):
467 377d74c9 Guido Trotter
        if instance.network_port > constants.VNC_BASE_PORT:
468 377d74c9 Guido Trotter
          display = instance.network_port - constants.VNC_BASE_PORT
469 8447f52b Guido Trotter
          if vnc_bind_address == '0.0.0.0':
470 8447f52b Guido Trotter
            vnc_arg = ':%d' % (display)
471 8447f52b Guido Trotter
          else:
472 19498d6c Guido Trotter
            vnc_arg = '%s:%d' % (vnc_bind_address, display)
473 8470c8db Guido Trotter
        else:
474 8447f52b Guido Trotter
          logging.error("Network port is not a valid VNC display (%d < %d)."
475 07b8a2b5 Iustin Pop
                        " Not starting VNC", instance.network_port,
476 07b8a2b5 Iustin Pop
                        constants.VNC_BASE_PORT)
477 8447f52b Guido Trotter
          vnc_arg = 'none'
478 8b2d1013 Guido Trotter
479 8b2d1013 Guido Trotter
        # Only allow tls and other option when not binding to a file, for now.
480 8b2d1013 Guido Trotter
        # kvm/qemu gets confused otherwise about the filename to use.
481 8b2d1013 Guido Trotter
        vnc_append = ''
482 a985b417 Iustin Pop
        if hvp[constants.HV_VNC_TLS]:
483 8b2d1013 Guido Trotter
          vnc_append = '%s,tls' % vnc_append
484 a985b417 Iustin Pop
          if hvp[constants.HV_VNC_X509_VERIFY]:
485 8b2d1013 Guido Trotter
            vnc_append = '%s,x509verify=%s' % (vnc_append,
486 a985b417 Iustin Pop
                                               hvp[constants.HV_VNC_X509])
487 a985b417 Iustin Pop
          elif hvp[constants.HV_VNC_X509]:
488 8b2d1013 Guido Trotter
            vnc_append = '%s,x509=%s' % (vnc_append,
489 a985b417 Iustin Pop
                                         hvp[constants.HV_VNC_X509])
490 6e6bb8d5 Guido Trotter
        if hvp[constants.HV_VNC_PASSWORD_FILE]:
491 6e6bb8d5 Guido Trotter
          vnc_append = '%s,password' % vnc_append
492 6e6bb8d5 Guido Trotter
493 8b2d1013 Guido Trotter
        vnc_arg = '%s%s' % (vnc_arg, vnc_append)
494 8b2d1013 Guido Trotter
495 8470c8db Guido Trotter
      else:
496 8b2d1013 Guido Trotter
        vnc_arg = 'unix:%s/%s.vnc' % (vnc_bind_address, instance.name)
497 8b2d1013 Guido Trotter
498 8447f52b Guido Trotter
      kvm_cmd.extend(['-vnc', vnc_arg])
499 8470c8db Guido Trotter
    else:
500 8470c8db Guido Trotter
      kvm_cmd.extend(['-nographic'])
501 8470c8db Guido Trotter
502 69b99987 Michael Hanselmann
    monitor_dev = ("unix:%s,server,nowait" %
503 69b99987 Michael Hanselmann
                   self._InstanceMonitor(instance.name))
504 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-monitor', monitor_dev])
505 a985b417 Iustin Pop
    if hvp[constants.HV_SERIAL_CONSOLE]:
506 a985b417 Iustin Pop
      serial_dev = ('unix:%s,server,nowait' %
507 a985b417 Iustin Pop
                    self._InstanceSerial(instance.name))
508 a2faf9ee Guido Trotter
      kvm_cmd.extend(['-serial', serial_dev])
509 a2faf9ee Guido Trotter
    else:
510 a2faf9ee Guido Trotter
      kvm_cmd.extend(['-serial', 'none'])
511 eb58f9b1 Guido Trotter
512 6b970cef Jun Futagawa
    if hvp[constants.HV_USE_LOCALTIME]:
513 6b970cef Jun Futagawa
      kvm_cmd.extend(['-localtime'])
514 6b970cef Jun Futagawa
515 ee5f20b0 Guido Trotter
    # Save the current instance nics, but defer their expansion as parameters,
516 ee5f20b0 Guido Trotter
    # as we'll need to generate executable temp files for them.
517 ee5f20b0 Guido Trotter
    kvm_nics = instance.nics
518 a985b417 Iustin Pop
    hvparams = hvp
519 ee5f20b0 Guido Trotter
520 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
521 ee5f20b0 Guido Trotter
522 38e250ba Guido Trotter
  def _WriteKVMRuntime(self, instance_name, data):
523 38e250ba Guido Trotter
    """Write an instance's KVM runtime
524 38e250ba Guido Trotter

525 38e250ba Guido Trotter
    """
526 38e250ba Guido Trotter
    try:
527 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
528 38e250ba Guido Trotter
                      data=data)
529 90c024f6 Guido Trotter
    except EnvironmentError, err:
530 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
531 38e250ba Guido Trotter
532 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
533 38e250ba Guido Trotter
    """Read an instance's KVM runtime
534 38e250ba Guido Trotter

535 38e250ba Guido Trotter
    """
536 38e250ba Guido Trotter
    try:
537 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
538 90c024f6 Guido Trotter
    except EnvironmentError, err:
539 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
540 38e250ba Guido Trotter
    return file_content
541 38e250ba Guido Trotter
542 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
543 38e250ba Guido Trotter
    """Save an instance's KVM runtime
544 38e250ba Guido Trotter

545 38e250ba Guido Trotter
    """
546 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
547 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
548 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
549 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
550 38e250ba Guido Trotter
551 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
552 38e250ba Guido Trotter
    """Load an instance's KVM runtime
553 38e250ba Guido Trotter

554 38e250ba Guido Trotter
    """
555 30e42c4e Guido Trotter
    if not serialized_runtime:
556 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
557 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
558 c2672466 Guido Trotter
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
559 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
560 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
561 38e250ba Guido Trotter
562 30e42c4e Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
563 ee5f20b0 Guido Trotter
    """Execute a KVM cmd, after completing it with some last minute data
564 ee5f20b0 Guido Trotter

565 30e42c4e Guido Trotter
    @type incoming: tuple of strings
566 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
567 30e42c4e Guido Trotter

568 ee5f20b0 Guido Trotter
    """
569 6e6bb8d5 Guido Trotter
    hvp = instance.hvparams
570 5905901c Iustin Pop
    name = instance.name
571 5905901c Iustin Pop
    self._CheckDown(name)
572 ee5f20b0 Guido Trotter
573 ee5f20b0 Guido Trotter
    temp_files = []
574 ee5f20b0 Guido Trotter
575 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
576 ee5f20b0 Guido Trotter
577 cef34868 Guido Trotter
    security_model = hvp[constants.HV_SECURITY_MODEL]
578 cef34868 Guido Trotter
    if security_model == constants.HT_SM_USER:
579 cef34868 Guido Trotter
      kvm_cmd.extend(["-runas", hvp[constants.HV_SECURITY_DOMAIN]])
580 cef34868 Guido Trotter
581 ee5f20b0 Guido Trotter
    if not kvm_nics:
582 ee5f20b0 Guido Trotter
      kvm_cmd.extend(['-net', 'none'])
583 ee5f20b0 Guido Trotter
    else:
584 37f88dc6 Guido Trotter
      nic_type = hvparams[constants.HV_NIC_TYPE]
585 37f88dc6 Guido Trotter
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
586 37f88dc6 Guido Trotter
        nic_model = "model=virtio"
587 37f88dc6 Guido Trotter
      else:
588 37f88dc6 Guido Trotter
        nic_model = "model=%s" % nic_type
589 37f88dc6 Guido Trotter
590 ee5f20b0 Guido Trotter
      for nic_seq, nic in enumerate(kvm_nics):
591 760570a8 Timothy Kuhlman
        nic_val = "nic,vlan=%s,macaddr=%s,%s" % (nic_seq, nic.mac, nic_model)
592 ee5f20b0 Guido Trotter
        script = self._WriteNetScript(instance, nic_seq, nic)
593 ee5f20b0 Guido Trotter
        kvm_cmd.extend(['-net', nic_val])
594 760570a8 Timothy Kuhlman
        kvm_cmd.extend(['-net', 'tap,vlan=%s,script=%s' % (nic_seq, script)])
595 ee5f20b0 Guido Trotter
        temp_files.append(script)
596 ee5f20b0 Guido Trotter
597 30e42c4e Guido Trotter
    if incoming:
598 30e42c4e Guido Trotter
      target, port = incoming
599 30e42c4e Guido Trotter
      kvm_cmd.extend(['-incoming', 'tcp:%s:%s' % (target, port)])
600 30e42c4e Guido Trotter
601 6e6bb8d5 Guido Trotter
    vnc_pwd_file = hvp[constants.HV_VNC_PASSWORD_FILE]
602 6e6bb8d5 Guido Trotter
    vnc_pwd = None
603 6e6bb8d5 Guido Trotter
    if vnc_pwd_file:
604 6e6bb8d5 Guido Trotter
      try:
605 6e6bb8d5 Guido Trotter
        vnc_pwd = utils.ReadFile(vnc_pwd_file)
606 6e6bb8d5 Guido Trotter
      except EnvironmentError, err:
607 6e6bb8d5 Guido Trotter
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
608 6e6bb8d5 Guido Trotter
                                     % (vnc_pwd_file, err))
609 6e6bb8d5 Guido Trotter
610 eb58f9b1 Guido Trotter
    result = utils.RunCmd(kvm_cmd)
611 eb58f9b1 Guido Trotter
    if result.failed:
612 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
613 5905901c Iustin Pop
                                   (name, result.fail_reason, result.output))
614 eb58f9b1 Guido Trotter
615 5905901c Iustin Pop
    if not self._InstancePidAlive(name)[2]:
616 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s" % name)
617 eb58f9b1 Guido Trotter
618 6e6bb8d5 Guido Trotter
    if vnc_pwd:
619 6e6bb8d5 Guido Trotter
      change_cmd = 'change vnc password %s' % vnc_pwd
620 6e6bb8d5 Guido Trotter
      self._CallMonitorCommand(instance.name, change_cmd)
621 6e6bb8d5 Guido Trotter
622 08137f9e Iustin Pop
    for filename in temp_files:
623 08137f9e Iustin Pop
      utils.RemoveFile(filename)
624 eb58f9b1 Guido Trotter
625 07813a9e Iustin Pop
  def StartInstance(self, instance, block_devices):
626 ee5f20b0 Guido Trotter
    """Start an instance.
627 ee5f20b0 Guido Trotter

628 ee5f20b0 Guido Trotter
    """
629 5905901c Iustin Pop
    self._CheckDown(instance.name)
630 07813a9e Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices)
631 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
632 ee5f20b0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
633 ee5f20b0 Guido Trotter
634 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
635 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
636 6567aff3 Guido Trotter

637 6567aff3 Guido Trotter
    """
638 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
639 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
640 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
641 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
642 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
643 6567aff3 Guido Trotter
    if result.failed:
644 6567aff3 Guido Trotter
      msg = ("Failed to send command '%s' to instance %s."
645 6567aff3 Guido Trotter
             " output: %s, error: %s, fail_reason: %s" %
646 9798fcae Guido Trotter
             (command, instance_name,
647 9798fcae Guido Trotter
              result.stdout, result.stderr, result.fail_reason))
648 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
649 6567aff3 Guido Trotter
650 6567aff3 Guido Trotter
    return result
651 6567aff3 Guido Trotter
652 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
653 eb58f9b1 Guido Trotter
    """Stop an instance.
654 eb58f9b1 Guido Trotter

655 eb58f9b1 Guido Trotter
    """
656 bbcf7ad0 Iustin Pop
    if name is not None and not force:
657 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
658 bbcf7ad0 Iustin Pop
    if name is None:
659 bbcf7ad0 Iustin Pop
      name = instance.name
660 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
661 bbcf7ad0 Iustin Pop
    else:
662 bbcf7ad0 Iustin Pop
      acpi = False
663 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
664 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
665 bbcf7ad0 Iustin Pop
      if force or not acpi:
666 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
667 eb58f9b1 Guido Trotter
      else:
668 bbcf7ad0 Iustin Pop
        self._CallMonitorCommand(name, 'system_powerdown')
669 eb58f9b1 Guido Trotter
670 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
671 8904b35c Guido Trotter
    """Cleanup after a stopped instance
672 8904b35c Guido Trotter

673 8904b35c Guido Trotter
    """
674 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
675 8904b35c Guido Trotter
    if pid > 0 and alive:
676 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
677 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
678 eb58f9b1 Guido Trotter
679 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
680 eb58f9b1 Guido Trotter
    """Reboot an instance.
681 eb58f9b1 Guido Trotter

682 eb58f9b1 Guido Trotter
    """
683 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
684 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
685 eb58f9b1 Guido Trotter
    # to shutdown and restart.
686 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
687 1f8b3a27 Guido Trotter
    if not alive:
688 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
689 78411c60 Iustin Pop
                                   " not running" % instance.name)
690 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
691 f02881e0 Guido Trotter
    # ...first load it...
692 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
693 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
694 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
695 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
696 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
697 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
698 f02881e0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
699 eb58f9b1 Guido Trotter
700 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
701 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
702 30e42c4e Guido Trotter

703 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
704 30e42c4e Guido Trotter
    @param instance: instance to be migrated
705 30e42c4e Guido Trotter
    @rtype: string
706 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
707 30e42c4e Guido Trotter

708 30e42c4e Guido Trotter
    """
709 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
710 30e42c4e Guido Trotter
711 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
712 30e42c4e Guido Trotter
    """Prepare to accept an instance.
713 30e42c4e Guido Trotter

714 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
715 30e42c4e Guido Trotter
    @param instance: instance to be accepted
716 30e42c4e Guido Trotter
    @type info: string
717 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
718 30e42c4e Guido Trotter
    @type target: string
719 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
720 30e42c4e Guido Trotter

721 30e42c4e Guido Trotter
    """
722 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
723 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
724 30e42c4e Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
725 30e42c4e Guido Trotter
726 30e42c4e Guido Trotter
  def FinalizeMigration(self, instance, info, success):
727 30e42c4e Guido Trotter
    """Finalize an instance migration.
728 30e42c4e Guido Trotter

729 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
730 30e42c4e Guido Trotter

731 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
732 30e42c4e Guido Trotter
    @param instance: instance whose migration is being aborted
733 30e42c4e Guido Trotter

734 30e42c4e Guido Trotter
    """
735 30e42c4e Guido Trotter
    if success:
736 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
737 30e42c4e Guido Trotter
    else:
738 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
739 30e42c4e Guido Trotter
740 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
741 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
742 30e42c4e Guido Trotter

743 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
744 30e42c4e Guido Trotter
    currently running.
745 30e42c4e Guido Trotter

746 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
747 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
748 30e42c4e Guido Trotter
    @type target: string
749 30e42c4e Guido Trotter
    @param target: ip address of the target node
750 30e42c4e Guido Trotter
    @type live: boolean
751 30e42c4e Guido Trotter
    @param live: perform a live migration
752 30e42c4e Guido Trotter

753 30e42c4e Guido Trotter
    """
754 58d38b02 Iustin Pop
    instance_name = instance.name
755 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
756 30e42c4e Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
757 30e42c4e Guido Trotter
    if not alive:
758 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
759 30e42c4e Guido Trotter
760 50716be0 Iustin Pop
    if not utils.TcpPing(target, port, live_port_needed=True):
761 50716be0 Iustin Pop
      raise errors.HypervisorError("Remote host %s not listening on port"
762 50716be0 Iustin Pop
                                   " %s, cannot migrate" % (target, port))
763 50716be0 Iustin Pop
764 30e42c4e Guido Trotter
    if not live:
765 30e42c4e Guido Trotter
      self._CallMonitorCommand(instance_name, 'stop')
766 30e42c4e Guido Trotter
767 641ae041 Iustin Pop
    migrate_command = 'migrate -d tcp:%s:%s' % (target, port)
768 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
769 30e42c4e Guido Trotter
770 30e42c4e Guido Trotter
    info_command = 'info migrate'
771 30e42c4e Guido Trotter
    done = False
772 c4e388a5 Guido Trotter
    broken_answers = 0
773 30e42c4e Guido Trotter
    while not done:
774 30e42c4e Guido Trotter
      result = self._CallMonitorCommand(instance_name, info_command)
775 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
776 30e42c4e Guido Trotter
      if not match:
777 c4e388a5 Guido Trotter
        broken_answers += 1
778 c4e388a5 Guido Trotter
        if not result.stdout:
779 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
780 c4e388a5 Guido Trotter
        else:
781 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
782 c4e388a5 Guido Trotter
                          result.stdout)
783 c4e388a5 Guido Trotter
        time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
784 30e42c4e Guido Trotter
      else:
785 30e42c4e Guido Trotter
        status = match.group(1)
786 30e42c4e Guido Trotter
        if status == 'completed':
787 30e42c4e Guido Trotter
          done = True
788 30e42c4e Guido Trotter
        elif status == 'active':
789 c4e388a5 Guido Trotter
          # reset the broken answers count
790 c4e388a5 Guido Trotter
          broken_answers = 0
791 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
792 c087266c Guido Trotter
        elif status == 'failed' or status == 'cancelled':
793 c087266c Guido Trotter
          if not live:
794 c087266c Guido Trotter
            self._CallMonitorCommand(instance_name, 'cont')
795 c087266c Guido Trotter
          raise errors.HypervisorError("Migration %s at the kvm level" %
796 c087266c Guido Trotter
                                       status)
797 30e42c4e Guido Trotter
        else:
798 c4e388a5 Guido Trotter
          logging.warning("KVM: unknown migration status '%s'", status)
799 c4e388a5 Guido Trotter
          broken_answers += 1
800 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
801 c4e388a5 Guido Trotter
      if broken_answers >= self._MIGRATION_INFO_MAX_BAD_ANSWERS:
802 c4e388a5 Guido Trotter
        raise errors.HypervisorError("Too many 'info migrate' broken answers")
803 30e42c4e Guido Trotter
804 30e42c4e Guido Trotter
    utils.KillProcess(pid)
805 7b381438 Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
806 30e42c4e Guido Trotter
807 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
808 eb58f9b1 Guido Trotter
    """Return information about the node.
809 eb58f9b1 Guido Trotter

810 572e52bf Iustin Pop
    This is just a wrapper over the base GetLinuxNodeInfo method.
811 572e52bf Iustin Pop

812 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
813 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
814 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
815 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
816 eb58f9b1 Guido Trotter

817 eb58f9b1 Guido Trotter
    """
818 572e52bf Iustin Pop
    return self.GetLinuxNodeInfo()
819 eb58f9b1 Guido Trotter
820 637ce7f9 Guido Trotter
  @classmethod
821 5431b2e4 Guido Trotter
  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
822 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
823 eb58f9b1 Guido Trotter

824 eb58f9b1 Guido Trotter
    """
825 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
826 86d6bc2a Guido Trotter
      shell_command = ("%s STDIO,%s UNIX-CONNECT:%s" %
827 86d6bc2a Guido Trotter
                       (constants.SOCAT_PATH, cls._SocatUnixConsoleParams(),
828 a2faf9ee Guido Trotter
                        utils.ShellQuote(cls._InstanceSerial(instance.name))))
829 a2faf9ee Guido Trotter
    else:
830 a2faf9ee Guido Trotter
      shell_command = "echo 'No serial shell for instance %s'" % instance.name
831 3be34f57 Guido Trotter
832 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
833 3be34f57 Guido Trotter
    if vnc_bind_address:
834 377d74c9 Guido Trotter
      if instance.network_port > constants.VNC_BASE_PORT:
835 377d74c9 Guido Trotter
        display = instance.network_port - constants.VNC_BASE_PORT
836 3be34f57 Guido Trotter
        vnc_command = ("echo 'Instance has VNC listening on %s:%d"
837 3be34f57 Guido Trotter
                       " (display: %d)'" % (vnc_bind_address,
838 3be34f57 Guido Trotter
                                            instance.network_port,
839 3be34f57 Guido Trotter
                                            display))
840 3be34f57 Guido Trotter
        shell_command = "%s; %s" % (vnc_command, shell_command)
841 3be34f57 Guido Trotter
842 a2faf9ee Guido Trotter
    return shell_command
843 eb58f9b1 Guido Trotter
844 eb58f9b1 Guido Trotter
  def Verify(self):
845 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
846 eb58f9b1 Guido Trotter

847 eb58f9b1 Guido Trotter
    Check that the binary exists.
848 eb58f9b1 Guido Trotter

849 eb58f9b1 Guido Trotter
    """
850 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
851 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
852 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
853 14aa53cb Guido Trotter
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
854 14aa53cb Guido Trotter
855 6b5605e8 Iustin Pop
856 6b5605e8 Iustin Pop
  @classmethod
857 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
858 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
859 6b5605e8 Iustin Pop

860 6b5605e8 Iustin Pop
    @type hvparams:  dict
861 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
862 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
863 6b5605e8 Iustin Pop

864 6b5605e8 Iustin Pop
    """
865 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
866 6b5605e8 Iustin Pop
867 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
868 df5ab9f0 Guido Trotter
    if kernel_path:
869 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
870 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
871 205ab586 Iustin Pop
                                     " if a kernel is defined")
872 6b5605e8 Iustin Pop
873 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
874 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
875 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
876 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
877 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
878 66d5dbef Guido Trotter
879 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
880 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
881 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
882 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
883 835528af Iustin Pop
                                   " ISO path")
884 f5118ade Iustin Pop
885 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
886 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
887 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
888 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
889 d19d94db Guido Trotter
                                     " must be specified")
890 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
891 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
892 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
893 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
894 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
895 d19d94db Guido Trotter
    if security_model == constants.HT_SM_POOL:
896 d19d94db Guido Trotter
      raise errors.HypervisorError("Security model pool is not supported yet")
897 d19d94db Guido Trotter
898 d19d94db Guido Trotter
  @classmethod
899 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
900 d19d94db Guido Trotter
    """Check the given parameters for validity.
901 d19d94db Guido Trotter

902 d19d94db Guido Trotter
    @type hvparams:  dict
903 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
904 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
905 d19d94db Guido Trotter

906 d19d94db Guido Trotter
    """
907 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
908 d19d94db Guido Trotter
909 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
910 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
911 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
912 d19d94db Guido Trotter
      try:
913 1feb39ec Guido Trotter
        pwd.getpwnam(username)
914 d19d94db Guido Trotter
      except KeyError:
915 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
916 d19d94db Guido Trotter
                                     % username)
917 d19d94db Guido Trotter
918 f5118ade Iustin Pop
  @classmethod
919 f5118ade Iustin Pop
  def PowercycleNode(cls):
920 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
921 f5118ade Iustin Pop

922 f5118ade Iustin Pop
    """
923 f5118ade Iustin Pop
    cls.LinuxPowercycle()