Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 5b062a58

History | View | Annotate | Download (32.8 kB)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

559 38e250ba Guido Trotter
    """
560 30e42c4e Guido Trotter
    if not serialized_runtime:
561 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
562 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
563 c2672466 Guido Trotter
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
564 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
565 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
566 38e250ba Guido Trotter
567 76431533 Guido Trotter
  def _RunKVMCmd(self, name, kvm_cmd):
568 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
569 76431533 Guido Trotter

570 76431533 Guido Trotter
    @type name: string
571 76431533 Guido Trotter
    @param name: instance name
572 76431533 Guido Trotter
    @type kvm_cmd: list of strings
573 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
574 76431533 Guido Trotter

575 76431533 Guido Trotter
    """
576 76431533 Guido Trotter
    result = utils.RunCmd(kvm_cmd)
577 76431533 Guido Trotter
    if result.failed:
578 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
579 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
580 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
581 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
582 76431533 Guido Trotter
583 30e42c4e Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
584 ee5f20b0 Guido Trotter
    """Execute a KVM cmd, after completing it with some last minute data
585 ee5f20b0 Guido Trotter

586 30e42c4e Guido Trotter
    @type incoming: tuple of strings
587 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
588 30e42c4e Guido Trotter

589 ee5f20b0 Guido Trotter
    """
590 6e6bb8d5 Guido Trotter
    hvp = instance.hvparams
591 5905901c Iustin Pop
    name = instance.name
592 5905901c Iustin Pop
    self._CheckDown(name)
593 ee5f20b0 Guido Trotter
594 ee5f20b0 Guido Trotter
    temp_files = []
595 ee5f20b0 Guido Trotter
596 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
597 ee5f20b0 Guido Trotter
598 cef34868 Guido Trotter
    security_model = hvp[constants.HV_SECURITY_MODEL]
599 cef34868 Guido Trotter
    if security_model == constants.HT_SM_USER:
600 cef34868 Guido Trotter
      kvm_cmd.extend(["-runas", hvp[constants.HV_SECURITY_DOMAIN]])
601 cef34868 Guido Trotter
602 ee5f20b0 Guido Trotter
    if not kvm_nics:
603 ee5f20b0 Guido Trotter
      kvm_cmd.extend(['-net', 'none'])
604 ee5f20b0 Guido Trotter
    else:
605 37f88dc6 Guido Trotter
      nic_type = hvparams[constants.HV_NIC_TYPE]
606 37f88dc6 Guido Trotter
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
607 37f88dc6 Guido Trotter
        nic_model = "model=virtio"
608 37f88dc6 Guido Trotter
      else:
609 37f88dc6 Guido Trotter
        nic_model = "model=%s" % nic_type
610 37f88dc6 Guido Trotter
611 ee5f20b0 Guido Trotter
      for nic_seq, nic in enumerate(kvm_nics):
612 760570a8 Timothy Kuhlman
        nic_val = "nic,vlan=%s,macaddr=%s,%s" % (nic_seq, nic.mac, nic_model)
613 ee5f20b0 Guido Trotter
        script = self._WriteNetScript(instance, nic_seq, nic)
614 ee5f20b0 Guido Trotter
        kvm_cmd.extend(['-net', nic_val])
615 760570a8 Timothy Kuhlman
        kvm_cmd.extend(['-net', 'tap,vlan=%s,script=%s' % (nic_seq, script)])
616 ee5f20b0 Guido Trotter
        temp_files.append(script)
617 ee5f20b0 Guido Trotter
618 30e42c4e Guido Trotter
    if incoming:
619 30e42c4e Guido Trotter
      target, port = incoming
620 30e42c4e Guido Trotter
      kvm_cmd.extend(['-incoming', 'tcp:%s:%s' % (target, port)])
621 30e42c4e Guido Trotter
622 6e6bb8d5 Guido Trotter
    vnc_pwd_file = hvp[constants.HV_VNC_PASSWORD_FILE]
623 6e6bb8d5 Guido Trotter
    vnc_pwd = None
624 6e6bb8d5 Guido Trotter
    if vnc_pwd_file:
625 6e6bb8d5 Guido Trotter
      try:
626 6e6bb8d5 Guido Trotter
        vnc_pwd = utils.ReadFile(vnc_pwd_file)
627 6e6bb8d5 Guido Trotter
      except EnvironmentError, err:
628 6e6bb8d5 Guido Trotter
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
629 6e6bb8d5 Guido Trotter
                                     % (vnc_pwd_file, err))
630 6e6bb8d5 Guido Trotter
631 76431533 Guido Trotter
    if security_model == constants.HT_SM_POOL:
632 76431533 Guido Trotter
      ss = ssconf.SimpleStore()
633 76431533 Guido Trotter
      uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
634 76431533 Guido Trotter
      all_uids = set(uidpool.ExpandUidPool(uid_pool))
635 76431533 Guido Trotter
      uid = uidpool.RequestUnusedUid(all_uids)
636 76431533 Guido Trotter
      try:
637 76431533 Guido Trotter
        username = pwd.getpwuid(uid.GetUid()).pw_name
638 76431533 Guido Trotter
        kvm_cmd.extend(["-runas", username])
639 76431533 Guido Trotter
        self._RunKVMCmd(name, kvm_cmd)
640 76431533 Guido Trotter
      except:
641 76431533 Guido Trotter
        uidpool.ReleaseUid(uid)
642 76431533 Guido Trotter
        raise
643 76431533 Guido Trotter
      else:
644 76431533 Guido Trotter
        uid.Unlock()
645 76431533 Guido Trotter
        utils.WriteFile(self._InstanceUidFile(name), data=str(uid))
646 76431533 Guido Trotter
    else:
647 76431533 Guido Trotter
      self._RunKVMCmd(name, kvm_cmd)
648 eb58f9b1 Guido Trotter
649 6e6bb8d5 Guido Trotter
    if vnc_pwd:
650 6e6bb8d5 Guido Trotter
      change_cmd = 'change vnc password %s' % vnc_pwd
651 6e6bb8d5 Guido Trotter
      self._CallMonitorCommand(instance.name, change_cmd)
652 6e6bb8d5 Guido Trotter
653 08137f9e Iustin Pop
    for filename in temp_files:
654 08137f9e Iustin Pop
      utils.RemoveFile(filename)
655 eb58f9b1 Guido Trotter
656 07813a9e Iustin Pop
  def StartInstance(self, instance, block_devices):
657 ee5f20b0 Guido Trotter
    """Start an instance.
658 ee5f20b0 Guido Trotter

659 ee5f20b0 Guido Trotter
    """
660 5905901c Iustin Pop
    self._CheckDown(instance.name)
661 07813a9e Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices)
662 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
663 ee5f20b0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
664 ee5f20b0 Guido Trotter
665 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
666 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
667 6567aff3 Guido Trotter

668 6567aff3 Guido Trotter
    """
669 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
670 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
671 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
672 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
673 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
674 6567aff3 Guido Trotter
    if result.failed:
675 6567aff3 Guido Trotter
      msg = ("Failed to send command '%s' to instance %s."
676 6567aff3 Guido Trotter
             " output: %s, error: %s, fail_reason: %s" %
677 9798fcae Guido Trotter
             (command, instance_name,
678 9798fcae Guido Trotter
              result.stdout, result.stderr, result.fail_reason))
679 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
680 6567aff3 Guido Trotter
681 6567aff3 Guido Trotter
    return result
682 6567aff3 Guido Trotter
683 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
684 eb58f9b1 Guido Trotter
    """Stop an instance.
685 eb58f9b1 Guido Trotter

686 eb58f9b1 Guido Trotter
    """
687 bbcf7ad0 Iustin Pop
    if name is not None and not force:
688 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
689 bbcf7ad0 Iustin Pop
    if name is None:
690 bbcf7ad0 Iustin Pop
      name = instance.name
691 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
692 bbcf7ad0 Iustin Pop
    else:
693 bbcf7ad0 Iustin Pop
      acpi = False
694 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
695 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
696 bbcf7ad0 Iustin Pop
      if force or not acpi:
697 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
698 eb58f9b1 Guido Trotter
      else:
699 bbcf7ad0 Iustin Pop
        self._CallMonitorCommand(name, 'system_powerdown')
700 eb58f9b1 Guido Trotter
701 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
702 8904b35c Guido Trotter
    """Cleanup after a stopped instance
703 8904b35c Guido Trotter

704 8904b35c Guido Trotter
    """
705 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
706 8904b35c Guido Trotter
    if pid > 0 and alive:
707 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
708 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
709 eb58f9b1 Guido Trotter
710 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
711 eb58f9b1 Guido Trotter
    """Reboot an instance.
712 eb58f9b1 Guido Trotter

713 eb58f9b1 Guido Trotter
    """
714 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
715 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
716 eb58f9b1 Guido Trotter
    # to shutdown and restart.
717 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
718 1f8b3a27 Guido Trotter
    if not alive:
719 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
720 78411c60 Iustin Pop
                                   " not running" % instance.name)
721 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
722 f02881e0 Guido Trotter
    # ...first load it...
723 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
724 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
725 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
726 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
727 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
728 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
729 f02881e0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
730 eb58f9b1 Guido Trotter
731 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
732 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
733 30e42c4e Guido Trotter

734 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
735 30e42c4e Guido Trotter
    @param instance: instance to be migrated
736 30e42c4e Guido Trotter
    @rtype: string
737 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
738 30e42c4e Guido Trotter

739 30e42c4e Guido Trotter
    """
740 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
741 30e42c4e Guido Trotter
742 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
743 30e42c4e Guido Trotter
    """Prepare to accept an instance.
744 30e42c4e Guido Trotter

745 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
746 30e42c4e Guido Trotter
    @param instance: instance to be accepted
747 30e42c4e Guido Trotter
    @type info: string
748 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
749 30e42c4e Guido Trotter
    @type target: string
750 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
751 30e42c4e Guido Trotter

752 30e42c4e Guido Trotter
    """
753 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
754 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
755 30e42c4e Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
756 30e42c4e Guido Trotter
757 30e42c4e Guido Trotter
  def FinalizeMigration(self, instance, info, success):
758 30e42c4e Guido Trotter
    """Finalize an instance migration.
759 30e42c4e Guido Trotter

760 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
761 30e42c4e Guido Trotter

762 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
763 30e42c4e Guido Trotter
    @param instance: instance whose migration is being aborted
764 30e42c4e Guido Trotter

765 30e42c4e Guido Trotter
    """
766 30e42c4e Guido Trotter
    if success:
767 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
768 30e42c4e Guido Trotter
    else:
769 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
770 30e42c4e Guido Trotter
771 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
772 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
773 30e42c4e Guido Trotter

774 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
775 30e42c4e Guido Trotter
    currently running.
776 30e42c4e Guido Trotter

777 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
778 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
779 30e42c4e Guido Trotter
    @type target: string
780 30e42c4e Guido Trotter
    @param target: ip address of the target node
781 30e42c4e Guido Trotter
    @type live: boolean
782 30e42c4e Guido Trotter
    @param live: perform a live migration
783 30e42c4e Guido Trotter

784 30e42c4e Guido Trotter
    """
785 58d38b02 Iustin Pop
    instance_name = instance.name
786 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
787 30e42c4e Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
788 30e42c4e Guido Trotter
    if not alive:
789 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
790 30e42c4e Guido Trotter
791 50716be0 Iustin Pop
    if not utils.TcpPing(target, port, live_port_needed=True):
792 50716be0 Iustin Pop
      raise errors.HypervisorError("Remote host %s not listening on port"
793 50716be0 Iustin Pop
                                   " %s, cannot migrate" % (target, port))
794 50716be0 Iustin Pop
795 30e42c4e Guido Trotter
    if not live:
796 30e42c4e Guido Trotter
      self._CallMonitorCommand(instance_name, 'stop')
797 30e42c4e Guido Trotter
798 641ae041 Iustin Pop
    migrate_command = 'migrate -d tcp:%s:%s' % (target, port)
799 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
800 30e42c4e Guido Trotter
801 30e42c4e Guido Trotter
    info_command = 'info migrate'
802 30e42c4e Guido Trotter
    done = False
803 c4e388a5 Guido Trotter
    broken_answers = 0
804 30e42c4e Guido Trotter
    while not done:
805 30e42c4e Guido Trotter
      result = self._CallMonitorCommand(instance_name, info_command)
806 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
807 30e42c4e Guido Trotter
      if not match:
808 c4e388a5 Guido Trotter
        broken_answers += 1
809 c4e388a5 Guido Trotter
        if not result.stdout:
810 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
811 c4e388a5 Guido Trotter
        else:
812 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
813 c4e388a5 Guido Trotter
                          result.stdout)
814 c4e388a5 Guido Trotter
        time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
815 30e42c4e Guido Trotter
      else:
816 30e42c4e Guido Trotter
        status = match.group(1)
817 30e42c4e Guido Trotter
        if status == 'completed':
818 30e42c4e Guido Trotter
          done = True
819 30e42c4e Guido Trotter
        elif status == 'active':
820 c4e388a5 Guido Trotter
          # reset the broken answers count
821 c4e388a5 Guido Trotter
          broken_answers = 0
822 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
823 c087266c Guido Trotter
        elif status == 'failed' or status == 'cancelled':
824 c087266c Guido Trotter
          if not live:
825 c087266c Guido Trotter
            self._CallMonitorCommand(instance_name, 'cont')
826 c087266c Guido Trotter
          raise errors.HypervisorError("Migration %s at the kvm level" %
827 c087266c Guido Trotter
                                       status)
828 30e42c4e Guido Trotter
        else:
829 c4e388a5 Guido Trotter
          logging.warning("KVM: unknown migration status '%s'", status)
830 c4e388a5 Guido Trotter
          broken_answers += 1
831 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
832 c4e388a5 Guido Trotter
      if broken_answers >= self._MIGRATION_INFO_MAX_BAD_ANSWERS:
833 c4e388a5 Guido Trotter
        raise errors.HypervisorError("Too many 'info migrate' broken answers")
834 30e42c4e Guido Trotter
835 30e42c4e Guido Trotter
    utils.KillProcess(pid)
836 7b381438 Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
837 30e42c4e Guido Trotter
838 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
839 eb58f9b1 Guido Trotter
    """Return information about the node.
840 eb58f9b1 Guido Trotter

841 572e52bf Iustin Pop
    This is just a wrapper over the base GetLinuxNodeInfo method.
842 572e52bf Iustin Pop

843 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
844 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
845 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
846 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
847 eb58f9b1 Guido Trotter

848 eb58f9b1 Guido Trotter
    """
849 572e52bf Iustin Pop
    return self.GetLinuxNodeInfo()
850 eb58f9b1 Guido Trotter
851 637ce7f9 Guido Trotter
  @classmethod
852 5431b2e4 Guido Trotter
  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
853 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
854 eb58f9b1 Guido Trotter

855 eb58f9b1 Guido Trotter
    """
856 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
857 86d6bc2a Guido Trotter
      shell_command = ("%s STDIO,%s UNIX-CONNECT:%s" %
858 86d6bc2a Guido Trotter
                       (constants.SOCAT_PATH, cls._SocatUnixConsoleParams(),
859 a2faf9ee Guido Trotter
                        utils.ShellQuote(cls._InstanceSerial(instance.name))))
860 a2faf9ee Guido Trotter
    else:
861 a2faf9ee Guido Trotter
      shell_command = "echo 'No serial shell for instance %s'" % instance.name
862 3be34f57 Guido Trotter
863 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
864 3be34f57 Guido Trotter
    if vnc_bind_address:
865 377d74c9 Guido Trotter
      if instance.network_port > constants.VNC_BASE_PORT:
866 377d74c9 Guido Trotter
        display = instance.network_port - constants.VNC_BASE_PORT
867 3be34f57 Guido Trotter
        vnc_command = ("echo 'Instance has VNC listening on %s:%d"
868 3be34f57 Guido Trotter
                       " (display: %d)'" % (vnc_bind_address,
869 3be34f57 Guido Trotter
                                            instance.network_port,
870 3be34f57 Guido Trotter
                                            display))
871 3be34f57 Guido Trotter
        shell_command = "%s; %s" % (vnc_command, shell_command)
872 3be34f57 Guido Trotter
873 a2faf9ee Guido Trotter
    return shell_command
874 eb58f9b1 Guido Trotter
875 eb58f9b1 Guido Trotter
  def Verify(self):
876 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
877 eb58f9b1 Guido Trotter

878 eb58f9b1 Guido Trotter
    Check that the binary exists.
879 eb58f9b1 Guido Trotter

880 eb58f9b1 Guido Trotter
    """
881 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
882 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
883 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
884 14aa53cb Guido Trotter
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
885 14aa53cb Guido Trotter
886 6b5605e8 Iustin Pop
887 6b5605e8 Iustin Pop
  @classmethod
888 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
889 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
890 6b5605e8 Iustin Pop

891 6b5605e8 Iustin Pop
    @type hvparams:  dict
892 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
893 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
894 6b5605e8 Iustin Pop

895 6b5605e8 Iustin Pop
    """
896 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
897 6b5605e8 Iustin Pop
898 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
899 df5ab9f0 Guido Trotter
    if kernel_path:
900 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
901 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
902 205ab586 Iustin Pop
                                     " if a kernel is defined")
903 6b5605e8 Iustin Pop
904 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
905 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
906 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
907 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
908 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
909 66d5dbef Guido Trotter
910 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
911 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
912 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
913 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
914 835528af Iustin Pop
                                   " ISO path")
915 f5118ade Iustin Pop
916 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
917 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
918 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
919 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
920 d19d94db Guido Trotter
                                     " must be specified")
921 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
922 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
923 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
924 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
925 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
926 d19d94db Guido Trotter
927 d19d94db Guido Trotter
  @classmethod
928 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
929 d19d94db Guido Trotter
    """Check the given parameters for validity.
930 d19d94db Guido Trotter

931 d19d94db Guido Trotter
    @type hvparams:  dict
932 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
933 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
934 d19d94db Guido Trotter

935 d19d94db Guido Trotter
    """
936 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
937 d19d94db Guido Trotter
938 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
939 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
940 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
941 d19d94db Guido Trotter
      try:
942 1feb39ec Guido Trotter
        pwd.getpwnam(username)
943 d19d94db Guido Trotter
      except KeyError:
944 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
945 d19d94db Guido Trotter
                                     % username)
946 d19d94db Guido Trotter
947 f5118ade Iustin Pop
  @classmethod
948 f5118ade Iustin Pop
  def PowercycleNode(cls):
949 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
950 f5118ade Iustin Pop

951 f5118ade Iustin Pop
    """
952 f5118ade Iustin Pop
    cls.LinuxPowercycle()