Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 6396164f

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

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

123 7548396c Guido Trotter
    """
124 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
125 7548396c Guido Trotter
126 7548396c Guido Trotter
  @classmethod
127 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
128 263b8de6 Guido Trotter
    """Check pid file for instance information.
129 263b8de6 Guido Trotter

130 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
131 263b8de6 Guido Trotter
    information from its command line.
132 263b8de6 Guido Trotter

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

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

174 263b8de6 Guido Trotter
    @type instance_name: string
175 263b8de6 Guido Trotter
    @param instance_name: instance name
176 263b8de6 Guido Trotter
    @rtype: tuple
177 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
178 1f8b3a27 Guido Trotter

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

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

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

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

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

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

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

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

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

267 eb58f9b1 Guido Trotter
    This can be used by any qemu-type hypervisor.
268 eb58f9b1 Guido Trotter

269 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
270 eb58f9b1 Guido Trotter
    @type instance: instance object
271 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
272 eb58f9b1 Guido Trotter
    @type seq: int
273 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
274 eb58f9b1 Guido Trotter
    @type nic: nic object
275 eb58f9b1 Guido Trotter
    @return: netscript file name
276 eb58f9b1 Guido Trotter
    @rtype: string
277 eb58f9b1 Guido Trotter

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

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

344 eb58f9b1 Guido Trotter
    """
345 eb58f9b1 Guido Trotter
    result = []
346 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
347 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
348 eb58f9b1 Guido Trotter
        result.append(name)
349 eb58f9b1 Guido Trotter
    return result
350 eb58f9b1 Guido Trotter
351 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
352 eb58f9b1 Guido Trotter
    """Get instance properties.
353 eb58f9b1 Guido Trotter

354 4fbb3c60 Guido Trotter
    @type instance_name: string
355 c41eea6e Iustin Pop
    @param instance_name: the instance name
356 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
357 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
358 eb58f9b1 Guido Trotter

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

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

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

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

544 38e250ba Guido Trotter
    """
545 38e250ba Guido Trotter
    try:
546 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
547 38e250ba Guido Trotter
                      data=data)
548 90c024f6 Guido Trotter
    except EnvironmentError, err:
549 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
550 38e250ba Guido Trotter
551 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
552 38e250ba Guido Trotter
    """Read an instance's KVM runtime
553 38e250ba Guido Trotter

554 38e250ba Guido Trotter
    """
555 38e250ba Guido Trotter
    try:
556 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
557 90c024f6 Guido Trotter
    except EnvironmentError, err:
558 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
559 38e250ba Guido Trotter
    return file_content
560 38e250ba Guido Trotter
561 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
562 38e250ba Guido Trotter
    """Save an instance's KVM runtime
563 38e250ba Guido Trotter

564 38e250ba Guido Trotter
    """
565 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
566 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
567 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
568 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
569 38e250ba Guido Trotter
570 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
571 38e250ba Guido Trotter
    """Load an instance's KVM runtime
572 38e250ba Guido Trotter

573 38e250ba Guido Trotter
    """
574 30e42c4e Guido Trotter
    if not serialized_runtime:
575 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
576 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
577 c2672466 Guido Trotter
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
578 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
579 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
580 38e250ba Guido Trotter
581 76431533 Guido Trotter
  def _RunKVMCmd(self, name, kvm_cmd):
582 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
583 76431533 Guido Trotter

584 76431533 Guido Trotter
    @type name: string
585 76431533 Guido Trotter
    @param name: instance name
586 76431533 Guido Trotter
    @type kvm_cmd: list of strings
587 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
588 76431533 Guido Trotter

589 76431533 Guido Trotter
    """
590 76431533 Guido Trotter
    result = utils.RunCmd(kvm_cmd)
591 76431533 Guido Trotter
    if result.failed:
592 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
593 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
594 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
595 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
596 76431533 Guido Trotter
597 30e42c4e Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
598 ee5f20b0 Guido Trotter
    """Execute a KVM cmd, after completing it with some last minute data
599 ee5f20b0 Guido Trotter

600 30e42c4e Guido Trotter
    @type incoming: tuple of strings
601 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
602 30e42c4e Guido Trotter

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

677 ee5f20b0 Guido Trotter
    """
678 5905901c Iustin Pop
    self._CheckDown(instance.name)
679 07813a9e Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices)
680 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
681 ee5f20b0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
682 ee5f20b0 Guido Trotter
683 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
684 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
685 6567aff3 Guido Trotter

686 6567aff3 Guido Trotter
    """
687 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
688 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
689 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
690 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
691 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
692 6567aff3 Guido Trotter
    if result.failed:
693 6567aff3 Guido Trotter
      msg = ("Failed to send command '%s' to instance %s."
694 6567aff3 Guido Trotter
             " output: %s, error: %s, fail_reason: %s" %
695 9798fcae Guido Trotter
             (command, instance_name,
696 9798fcae Guido Trotter
              result.stdout, result.stderr, result.fail_reason))
697 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
698 6567aff3 Guido Trotter
699 6567aff3 Guido Trotter
    return result
700 6567aff3 Guido Trotter
701 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
702 eb58f9b1 Guido Trotter
    """Stop an instance.
703 eb58f9b1 Guido Trotter

704 eb58f9b1 Guido Trotter
    """
705 bbcf7ad0 Iustin Pop
    if name is not None and not force:
706 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
707 bbcf7ad0 Iustin Pop
    if name is None:
708 bbcf7ad0 Iustin Pop
      name = instance.name
709 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
710 bbcf7ad0 Iustin Pop
    else:
711 bbcf7ad0 Iustin Pop
      acpi = False
712 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
713 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
714 bbcf7ad0 Iustin Pop
      if force or not acpi:
715 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
716 eb58f9b1 Guido Trotter
      else:
717 bbcf7ad0 Iustin Pop
        self._CallMonitorCommand(name, 'system_powerdown')
718 eb58f9b1 Guido Trotter
719 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
720 8904b35c Guido Trotter
    """Cleanup after a stopped instance
721 8904b35c Guido Trotter

722 8904b35c Guido Trotter
    """
723 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
724 8904b35c Guido Trotter
    if pid > 0 and alive:
725 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
726 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
727 eb58f9b1 Guido Trotter
728 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
729 eb58f9b1 Guido Trotter
    """Reboot an instance.
730 eb58f9b1 Guido Trotter

731 eb58f9b1 Guido Trotter
    """
732 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
733 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
734 eb58f9b1 Guido Trotter
    # to shutdown and restart.
735 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
736 1f8b3a27 Guido Trotter
    if not alive:
737 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
738 78411c60 Iustin Pop
                                   " not running" % instance.name)
739 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
740 f02881e0 Guido Trotter
    # ...first load it...
741 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
742 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
743 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
744 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
745 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
746 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
747 f02881e0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
748 eb58f9b1 Guido Trotter
749 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
750 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
751 30e42c4e Guido Trotter

752 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
753 30e42c4e Guido Trotter
    @param instance: instance to be migrated
754 30e42c4e Guido Trotter
    @rtype: string
755 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
756 30e42c4e Guido Trotter

757 30e42c4e Guido Trotter
    """
758 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
759 30e42c4e Guido Trotter
760 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
761 30e42c4e Guido Trotter
    """Prepare to accept an instance.
762 30e42c4e Guido Trotter

763 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
764 30e42c4e Guido Trotter
    @param instance: instance to be accepted
765 30e42c4e Guido Trotter
    @type info: string
766 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
767 30e42c4e Guido Trotter
    @type target: string
768 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
769 30e42c4e Guido Trotter

770 30e42c4e Guido Trotter
    """
771 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
772 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
773 30e42c4e Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
774 30e42c4e Guido Trotter
775 30e42c4e Guido Trotter
  def FinalizeMigration(self, instance, info, success):
776 30e42c4e Guido Trotter
    """Finalize an instance migration.
777 30e42c4e Guido Trotter

778 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
779 30e42c4e Guido Trotter

780 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
781 30e42c4e Guido Trotter
    @param instance: instance whose migration is being aborted
782 30e42c4e Guido Trotter

783 30e42c4e Guido Trotter
    """
784 30e42c4e Guido Trotter
    if success:
785 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
786 30e42c4e Guido Trotter
    else:
787 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
788 30e42c4e Guido Trotter
789 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
790 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
791 30e42c4e Guido Trotter

792 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
793 30e42c4e Guido Trotter
    currently running.
794 30e42c4e Guido Trotter

795 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
796 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
797 30e42c4e Guido Trotter
    @type target: string
798 30e42c4e Guido Trotter
    @param target: ip address of the target node
799 30e42c4e Guido Trotter
    @type live: boolean
800 30e42c4e Guido Trotter
    @param live: perform a live migration
801 30e42c4e Guido Trotter

802 30e42c4e Guido Trotter
    """
803 58d38b02 Iustin Pop
    instance_name = instance.name
804 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
805 30e42c4e Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
806 30e42c4e Guido Trotter
    if not alive:
807 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
808 30e42c4e Guido Trotter
809 50716be0 Iustin Pop
    if not utils.TcpPing(target, port, live_port_needed=True):
810 50716be0 Iustin Pop
      raise errors.HypervisorError("Remote host %s not listening on port"
811 50716be0 Iustin Pop
                                   " %s, cannot migrate" % (target, port))
812 50716be0 Iustin Pop
813 30e42c4e Guido Trotter
    if not live:
814 30e42c4e Guido Trotter
      self._CallMonitorCommand(instance_name, 'stop')
815 30e42c4e Guido Trotter
816 e43d4f9f Apollon Oikonomopoulos
    migrate_command = ('migrate_set_speed %dm' %
817 e43d4f9f Apollon Oikonomopoulos
        instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
818 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
819 e43d4f9f Apollon Oikonomopoulos
820 e43d4f9f Apollon Oikonomopoulos
    migrate_command = ('migrate_set_downtime %dms' %
821 e43d4f9f Apollon Oikonomopoulos
        instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
822 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
823 e43d4f9f Apollon Oikonomopoulos
824 641ae041 Iustin Pop
    migrate_command = 'migrate -d tcp:%s:%s' % (target, port)
825 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
826 30e42c4e Guido Trotter
827 30e42c4e Guido Trotter
    info_command = 'info migrate'
828 30e42c4e Guido Trotter
    done = False
829 c4e388a5 Guido Trotter
    broken_answers = 0
830 30e42c4e Guido Trotter
    while not done:
831 30e42c4e Guido Trotter
      result = self._CallMonitorCommand(instance_name, info_command)
832 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
833 30e42c4e Guido Trotter
      if not match:
834 c4e388a5 Guido Trotter
        broken_answers += 1
835 c4e388a5 Guido Trotter
        if not result.stdout:
836 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
837 c4e388a5 Guido Trotter
        else:
838 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
839 c4e388a5 Guido Trotter
                          result.stdout)
840 c4e388a5 Guido Trotter
        time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
841 30e42c4e Guido Trotter
      else:
842 30e42c4e Guido Trotter
        status = match.group(1)
843 30e42c4e Guido Trotter
        if status == 'completed':
844 30e42c4e Guido Trotter
          done = True
845 30e42c4e Guido Trotter
        elif status == 'active':
846 c4e388a5 Guido Trotter
          # reset the broken answers count
847 c4e388a5 Guido Trotter
          broken_answers = 0
848 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
849 c087266c Guido Trotter
        elif status == 'failed' or status == 'cancelled':
850 c087266c Guido Trotter
          if not live:
851 c087266c Guido Trotter
            self._CallMonitorCommand(instance_name, 'cont')
852 c087266c Guido Trotter
          raise errors.HypervisorError("Migration %s at the kvm level" %
853 c087266c Guido Trotter
                                       status)
854 30e42c4e Guido Trotter
        else:
855 c4e388a5 Guido Trotter
          logging.warning("KVM: unknown migration status '%s'", status)
856 c4e388a5 Guido Trotter
          broken_answers += 1
857 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
858 c4e388a5 Guido Trotter
      if broken_answers >= self._MIGRATION_INFO_MAX_BAD_ANSWERS:
859 c4e388a5 Guido Trotter
        raise errors.HypervisorError("Too many 'info migrate' broken answers")
860 30e42c4e Guido Trotter
861 30e42c4e Guido Trotter
    utils.KillProcess(pid)
862 7b381438 Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
863 30e42c4e Guido Trotter
864 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
865 eb58f9b1 Guido Trotter
    """Return information about the node.
866 eb58f9b1 Guido Trotter

867 572e52bf Iustin Pop
    This is just a wrapper over the base GetLinuxNodeInfo method.
868 572e52bf Iustin Pop

869 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
870 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
871 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
872 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
873 eb58f9b1 Guido Trotter

874 eb58f9b1 Guido Trotter
    """
875 572e52bf Iustin Pop
    return self.GetLinuxNodeInfo()
876 eb58f9b1 Guido Trotter
877 637ce7f9 Guido Trotter
  @classmethod
878 5431b2e4 Guido Trotter
  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
879 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
880 eb58f9b1 Guido Trotter

881 eb58f9b1 Guido Trotter
    """
882 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
883 86d6bc2a Guido Trotter
      shell_command = ("%s STDIO,%s UNIX-CONNECT:%s" %
884 86d6bc2a Guido Trotter
                       (constants.SOCAT_PATH, cls._SocatUnixConsoleParams(),
885 a2faf9ee Guido Trotter
                        utils.ShellQuote(cls._InstanceSerial(instance.name))))
886 a2faf9ee Guido Trotter
    else:
887 a2faf9ee Guido Trotter
      shell_command = "echo 'No serial shell for instance %s'" % instance.name
888 3be34f57 Guido Trotter
889 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
890 3be34f57 Guido Trotter
    if vnc_bind_address:
891 377d74c9 Guido Trotter
      if instance.network_port > constants.VNC_BASE_PORT:
892 377d74c9 Guido Trotter
        display = instance.network_port - constants.VNC_BASE_PORT
893 3be34f57 Guido Trotter
        vnc_command = ("echo 'Instance has VNC listening on %s:%d"
894 3be34f57 Guido Trotter
                       " (display: %d)'" % (vnc_bind_address,
895 3be34f57 Guido Trotter
                                            instance.network_port,
896 3be34f57 Guido Trotter
                                            display))
897 3be34f57 Guido Trotter
        shell_command = "%s; %s" % (vnc_command, shell_command)
898 3be34f57 Guido Trotter
899 a2faf9ee Guido Trotter
    return shell_command
900 eb58f9b1 Guido Trotter
901 eb58f9b1 Guido Trotter
  def Verify(self):
902 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
903 eb58f9b1 Guido Trotter

904 eb58f9b1 Guido Trotter
    Check that the binary exists.
905 eb58f9b1 Guido Trotter

906 eb58f9b1 Guido Trotter
    """
907 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
908 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
909 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
910 14aa53cb Guido Trotter
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
911 14aa53cb Guido Trotter
912 6b5605e8 Iustin Pop
913 6b5605e8 Iustin Pop
  @classmethod
914 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
915 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
916 6b5605e8 Iustin Pop

917 6b5605e8 Iustin Pop
    @type hvparams:  dict
918 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
919 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
920 6b5605e8 Iustin Pop

921 6b5605e8 Iustin Pop
    """
922 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
923 6b5605e8 Iustin Pop
924 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
925 df5ab9f0 Guido Trotter
    if kernel_path:
926 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
927 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
928 205ab586 Iustin Pop
                                     " if a kernel is defined")
929 6b5605e8 Iustin Pop
930 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
931 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
932 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
933 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
934 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
935 66d5dbef Guido Trotter
936 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
937 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
938 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
939 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
940 835528af Iustin Pop
                                   " ISO path")
941 f5118ade Iustin Pop
942 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
943 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
944 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
945 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
946 d19d94db Guido Trotter
                                     " must be specified")
947 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
948 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
949 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
950 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
951 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
952 d19d94db Guido Trotter
953 d19d94db Guido Trotter
  @classmethod
954 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
955 d19d94db Guido Trotter
    """Check the given parameters for validity.
956 d19d94db Guido Trotter

957 d19d94db Guido Trotter
    @type hvparams:  dict
958 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
959 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
960 d19d94db Guido Trotter

961 d19d94db Guido Trotter
    """
962 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
963 d19d94db Guido Trotter
964 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
965 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
966 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
967 d19d94db Guido Trotter
      try:
968 1feb39ec Guido Trotter
        pwd.getpwnam(username)
969 d19d94db Guido Trotter
      except KeyError:
970 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
971 d19d94db Guido Trotter
                                     % username)
972 d19d94db Guido Trotter
973 f5118ade Iustin Pop
  @classmethod
974 f5118ade Iustin Pop
  def PowercycleNode(cls):
975 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
976 f5118ade Iustin Pop

977 f5118ade Iustin Pop
    """
978 f5118ade Iustin Pop
    cls.LinuxPowercycle()