Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 6c2549d6

History | View | Annotate | Download (36.9 kB)

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

24 eb58f9b1 Guido Trotter
"""
25 eb58f9b1 Guido Trotter
26 547a63b7 Balazs Lecz
import errno
27 eb58f9b1 Guido Trotter
import os
28 eb58f9b1 Guido Trotter
import os.path
29 eb58f9b1 Guido Trotter
import re
30 eb58f9b1 Guido Trotter
import tempfile
31 6567aff3 Guido Trotter
import time
32 30e42c4e Guido Trotter
import logging
33 d19d94db Guido Trotter
import pwd
34 eb58f9b1 Guido Trotter
from cStringIO import StringIO
35 eb58f9b1 Guido Trotter
36 eb58f9b1 Guido Trotter
from ganeti import utils
37 eb58f9b1 Guido Trotter
from ganeti import constants
38 eb58f9b1 Guido Trotter
from ganeti import errors
39 38e250ba Guido Trotter
from ganeti import serializer
40 38e250ba Guido Trotter
from ganeti import objects
41 76431533 Guido Trotter
from ganeti import uidpool
42 76431533 Guido Trotter
from ganeti import ssconf
43 eb58f9b1 Guido Trotter
from ganeti.hypervisor import hv_base
44 eb58f9b1 Guido Trotter
45 eb58f9b1 Guido Trotter
46 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
47 c4469f75 Guido Trotter
  """KVM hypervisor interface"""
48 d271c6fd Iustin Pop
  CAN_MIGRATE = True
49 eb58f9b1 Guido Trotter
50 eb58f9b1 Guido Trotter
  _ROOT_DIR = constants.RUN_GANETI_DIR + "/kvm-hypervisor"
51 a1d79fc6 Guido Trotter
  _PIDS_DIR = _ROOT_DIR + "/pid" # contains live instances pids
52 7548396c Guido Trotter
  _UIDS_DIR = _ROOT_DIR + "/uid" # contains instances reserved uids
53 a1d79fc6 Guido Trotter
  _CTRL_DIR = _ROOT_DIR + "/ctrl" # contains instances control sockets
54 a1d79fc6 Guido Trotter
  _CONF_DIR = _ROOT_DIR + "/conf" # contains instances startup data
55 547a63b7 Balazs Lecz
  # KVM instances with chroot enabled are started in empty chroot directories.
56 547a63b7 Balazs Lecz
  _CHROOT_DIR = _ROOT_DIR + "/chroot" # for empty chroot directories
57 547a63b7 Balazs Lecz
  # After an instance is stopped, its chroot directory is removed.
58 547a63b7 Balazs Lecz
  # If the chroot directory is not empty, it can't be removed.
59 547a63b7 Balazs Lecz
  # A non-empty chroot directory indicates a possible security incident.
60 547a63b7 Balazs Lecz
  # To support forensics, the non-empty chroot directory is quarantined in
61 547a63b7 Balazs Lecz
  # a separate directory, called 'chroot-quarantine'.
62 547a63b7 Balazs Lecz
  _CHROOT_QUARANTINE_DIR = _ROOT_DIR + "/chroot-quarantine"
63 547a63b7 Balazs Lecz
  _DIRS = [_ROOT_DIR, _PIDS_DIR, _UIDS_DIR, _CTRL_DIR, _CONF_DIR,
64 547a63b7 Balazs Lecz
           _CHROOT_DIR, _CHROOT_QUARANTINE_DIR]
65 eb58f9b1 Guido Trotter
66 205ab586 Iustin Pop
  PARAMETERS = {
67 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK,
68 205ab586 Iustin Pop
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
69 205ab586 Iustin Pop
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
70 205ab586 Iustin Pop
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
71 205ab586 Iustin Pop
    constants.HV_ACPI: hv_base.NO_CHECK,
72 205ab586 Iustin Pop
    constants.HV_SERIAL_CONSOLE: hv_base.NO_CHECK,
73 d73ef63f Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS:
74 d73ef63f Michael Hanselmann
      (False, lambda x: (utils.IsValidIP(x) or utils.IsNormAbsPath(x)),
75 d73ef63f Michael Hanselmann
       "the VNC bind address must be either a valid IP address or an absolute"
76 d73ef63f Michael Hanselmann
       " pathname", None, None),
77 205ab586 Iustin Pop
    constants.HV_VNC_TLS: hv_base.NO_CHECK,
78 205ab586 Iustin Pop
    constants.HV_VNC_X509: hv_base.OPT_DIR_CHECK,
79 205ab586 Iustin Pop
    constants.HV_VNC_X509_VERIFY: hv_base.NO_CHECK,
80 6e6bb8d5 Guido Trotter
    constants.HV_VNC_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
81 205ab586 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
82 d73ef63f Michael Hanselmann
    constants.HV_BOOT_ORDER:
83 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
84 d73ef63f Michael Hanselmann
    constants.HV_NIC_TYPE:
85 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_NIC_TYPES),
86 d73ef63f Michael Hanselmann
    constants.HV_DISK_TYPE:
87 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_DISK_TYPES),
88 d73ef63f Michael Hanselmann
    constants.HV_USB_MOUSE:
89 d73ef63f Michael Hanselmann
      hv_base.ParamInSet(False, constants.HT_KVM_VALID_MOUSE_TYPES),
90 78411c60 Iustin Pop
    constants.HV_MIGRATION_PORT: hv_base.NET_PORT_CHECK,
91 e43d4f9f Apollon Oikonomopoulos
    constants.HV_MIGRATION_BANDWIDTH: hv_base.NO_CHECK,
92 e43d4f9f Apollon Oikonomopoulos
    constants.HV_MIGRATION_DOWNTIME: hv_base.NO_CHECK,
93 6b970cef Jun Futagawa
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
94 19572932 Iustin Pop
    constants.HV_DISK_CACHE:
95 19572932 Iustin Pop
      hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
96 d19d94db Guido Trotter
    constants.HV_SECURITY_MODEL:
97 d19d94db Guido Trotter
      hv_base.ParamInSet(True, constants.HT_KVM_VALID_SM_TYPES),
98 d19d94db Guido Trotter
    constants.HV_SECURITY_DOMAIN: hv_base.NO_CHECK,
99 7ba594c0 Guido Trotter
    constants.HV_KVM_FLAG:
100 7ba594c0 Guido Trotter
      hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES),
101 fbe27e2b Guido Trotter
    constants.HV_VHOST_NET: hv_base.NO_CHECK,
102 547a63b7 Balazs Lecz
    constants.HV_KVM_USE_CHROOT: hv_base.NO_CHECK,
103 205ab586 Iustin Pop
    }
104 6b5605e8 Iustin Pop
105 30e42c4e Guido Trotter
  _MIGRATION_STATUS_RE = re.compile('Migration\s+status:\s+(\w+)',
106 30e42c4e Guido Trotter
                                    re.M | re.I)
107 c4e388a5 Guido Trotter
  _MIGRATION_INFO_MAX_BAD_ANSWERS = 5
108 c4e388a5 Guido Trotter
  _MIGRATION_INFO_RETRY_DELAY = 2
109 30e42c4e Guido Trotter
110 5420ffc9 Guido Trotter
  _KVM_NETWORK_SCRIPT = constants.SYSCONFDIR + "/ganeti/kvm-vif-bridge"
111 5420ffc9 Guido Trotter
112 64bfbc08 Guido Trotter
  ANCILLARY_FILES = [
113 64bfbc08 Guido Trotter
    _KVM_NETWORK_SCRIPT,
114 64bfbc08 Guido Trotter
    ]
115 64bfbc08 Guido Trotter
116 eb58f9b1 Guido Trotter
  def __init__(self):
117 eb58f9b1 Guido Trotter
    hv_base.BaseHypervisor.__init__(self)
118 eb58f9b1 Guido Trotter
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
119 eb58f9b1 Guido Trotter
    # in a tmpfs filesystem or has been otherwise wiped out.
120 29921401 Iustin Pop
    dirs = [(dname, constants.RUN_DIRS_MODE) for dname in self._DIRS]
121 9afb67fe Guido Trotter
    utils.EnsureDirs(dirs)
122 eb58f9b1 Guido Trotter
123 30786fc9 Iustin Pop
  @classmethod
124 30786fc9 Iustin Pop
  def _InstancePidFile(cls, instance_name):
125 98ec75d6 Iustin Pop
    """Returns the instance pidfile.
126 98ec75d6 Iustin Pop

127 98ec75d6 Iustin Pop
    """
128 30786fc9 Iustin Pop
    return utils.PathJoin(cls._PIDS_DIR, instance_name)
129 98ec75d6 Iustin Pop
130 263b8de6 Guido Trotter
  @classmethod
131 7548396c Guido Trotter
  def _InstanceUidFile(cls, instance_name):
132 7548396c Guido Trotter
    """Returns the instance uidfile.
133 7548396c Guido Trotter

134 7548396c Guido Trotter
    """
135 7548396c Guido Trotter
    return utils.PathJoin(cls._UIDS_DIR, instance_name)
136 7548396c Guido Trotter
137 7548396c Guido Trotter
  @classmethod
138 263b8de6 Guido Trotter
  def _InstancePidInfo(cls, pid):
139 263b8de6 Guido Trotter
    """Check pid file for instance information.
140 263b8de6 Guido Trotter

141 263b8de6 Guido Trotter
    Check that a pid file is associated with an instance, and retrieve
142 263b8de6 Guido Trotter
    information from its command line.
143 263b8de6 Guido Trotter

144 263b8de6 Guido Trotter
    @type pid: string or int
145 263b8de6 Guido Trotter
    @param pid: process id of the instance to check
146 263b8de6 Guido Trotter
    @rtype: tuple
147 263b8de6 Guido Trotter
    @return: (instance_name, memory, vcpus)
148 263b8de6 Guido Trotter
    @raise errors.HypervisorError: when an instance cannot be found
149 263b8de6 Guido Trotter

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

185 263b8de6 Guido Trotter
    @type instance_name: string
186 263b8de6 Guido Trotter
    @param instance_name: instance name
187 263b8de6 Guido Trotter
    @rtype: tuple
188 263b8de6 Guido Trotter
    @return: (pid file name, pid, liveness)
189 1f8b3a27 Guido Trotter

190 1f8b3a27 Guido Trotter
    """
191 98ec75d6 Iustin Pop
    pidfile = self._InstancePidFile(instance_name)
192 1f8b3a27 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
193 263b8de6 Guido Trotter
194 263b8de6 Guido Trotter
    alive = False
195 263b8de6 Guido Trotter
    try:
196 263b8de6 Guido Trotter
      cmd_instance = self._InstancePidInfo(pid)[0]
197 263b8de6 Guido Trotter
      alive = (cmd_instance == instance_name)
198 263b8de6 Guido Trotter
    except errors.HypervisorError:
199 263b8de6 Guido Trotter
      pass
200 1f8b3a27 Guido Trotter
201 1f8b3a27 Guido Trotter
    return (pidfile, pid, alive)
202 1f8b3a27 Guido Trotter
203 5905901c Iustin Pop
  def _CheckDown(self, instance_name):
204 5905901c Iustin Pop
    """Raises an error unless the given instance is down.
205 5905901c Iustin Pop

206 5905901c Iustin Pop
    """
207 5905901c Iustin Pop
    alive = self._InstancePidAlive(instance_name)[2]
208 5905901c Iustin Pop
    if alive:
209 5905901c Iustin Pop
      raise errors.HypervisorError("Failed to start instance %s: %s" %
210 5905901c Iustin Pop
                                   (instance_name, "already running"))
211 5905901c Iustin Pop
212 0df4d98a Guido Trotter
  @classmethod
213 0df4d98a Guido Trotter
  def _InstanceMonitor(cls, instance_name):
214 c4fbefc8 Guido Trotter
    """Returns the instance monitor socket name
215 c4fbefc8 Guido Trotter

216 c4fbefc8 Guido Trotter
    """
217 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.monitor" % instance_name)
218 c4fbefc8 Guido Trotter
219 0df4d98a Guido Trotter
  @classmethod
220 0df4d98a Guido Trotter
  def _InstanceSerial(cls, instance_name):
221 c4fbefc8 Guido Trotter
    """Returns the instance serial socket name
222 c4fbefc8 Guido Trotter

223 c4fbefc8 Guido Trotter
    """
224 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CTRL_DIR, "%s.serial" % instance_name)
225 c4fbefc8 Guido Trotter
226 86d6bc2a Guido Trotter
  @staticmethod
227 86d6bc2a Guido Trotter
  def _SocatUnixConsoleParams():
228 86d6bc2a Guido Trotter
    """Returns the correct parameters for socat
229 86d6bc2a Guido Trotter

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

232 86d6bc2a Guido Trotter
    """
233 fe5b0c42 Michael Hanselmann
    if constants.SOCAT_USE_ESCAPE:
234 86d6bc2a Guido Trotter
      return "raw,echo=0,escape=%s" % constants.SOCAT_ESCAPE_CODE
235 86d6bc2a Guido Trotter
    else:
236 86d6bc2a Guido Trotter
      return "echo=0,icanon=0"
237 86d6bc2a Guido Trotter
238 0df4d98a Guido Trotter
  @classmethod
239 0df4d98a Guido Trotter
  def _InstanceKVMRuntime(cls, instance_name):
240 38e250ba Guido Trotter
    """Returns the instance KVM runtime filename
241 38e250ba Guido Trotter

242 38e250ba Guido Trotter
    """
243 30786fc9 Iustin Pop
    return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name)
244 38e250ba Guido Trotter
245 7e66c35b Guido Trotter
  @classmethod
246 547a63b7 Balazs Lecz
  def _InstanceChrootDir(cls, instance_name):
247 547a63b7 Balazs Lecz
    """Returns the name of the KVM chroot dir of the instance
248 547a63b7 Balazs Lecz

249 547a63b7 Balazs Lecz
    """
250 547a63b7 Balazs Lecz
    return utils.PathJoin(cls._CHROOT_DIR, instance_name)
251 547a63b7 Balazs Lecz
252 547a63b7 Balazs Lecz
  @classmethod
253 7548396c Guido Trotter
  def _TryReadUidFile(cls, uid_file):
254 7548396c Guido Trotter
    """Try to read a uid file
255 7548396c Guido Trotter

256 7548396c Guido Trotter
    """
257 7548396c Guido Trotter
    if os.path.exists(uid_file):
258 7548396c Guido Trotter
      try:
259 682f7601 Guido Trotter
        uid = int(utils.ReadOneLineFile(uid_file))
260 aa0b600b Guido Trotter
        return uid
261 7548396c Guido Trotter
      except EnvironmentError:
262 7548396c Guido Trotter
        logging.warning("Can't read uid file", exc_info=True)
263 7548396c Guido Trotter
      except (TypeError, ValueError):
264 7548396c Guido Trotter
        logging.warning("Can't parse uid file contents", exc_info=True)
265 aa0b600b Guido Trotter
    return None
266 7548396c Guido Trotter
267 7548396c Guido Trotter
  @classmethod
268 7e66c35b Guido Trotter
  def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name):
269 547a63b7 Balazs Lecz
    """Removes an instance's rutime sockets/files/dirs.
270 7e66c35b Guido Trotter

271 7e66c35b Guido Trotter
    """
272 7e66c35b Guido Trotter
    utils.RemoveFile(pidfile)
273 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceMonitor(instance_name))
274 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceSerial(instance_name))
275 7e66c35b Guido Trotter
    utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
276 7548396c Guido Trotter
    uid_file = cls._InstanceUidFile(instance_name)
277 7548396c Guido Trotter
    uid = cls._TryReadUidFile(uid_file)
278 7548396c Guido Trotter
    utils.RemoveFile(uid_file)
279 7548396c Guido Trotter
    if uid is not None:
280 7548396c Guido Trotter
      uidpool.ReleaseUid(uid)
281 547a63b7 Balazs Lecz
    try:
282 547a63b7 Balazs Lecz
      chroot_dir = cls._InstanceChrootDir(instance_name)
283 547a63b7 Balazs Lecz
      utils.RemoveDir(chroot_dir)
284 547a63b7 Balazs Lecz
    except OSError, err:
285 547a63b7 Balazs Lecz
      if err.errno == errno.ENOTEMPTY:
286 547a63b7 Balazs Lecz
        # The chroot directory is expected to be empty, but it isn't.
287 547a63b7 Balazs Lecz
        new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR,
288 547a63b7 Balazs Lecz
                                          prefix="%s-%s-" %
289 547a63b7 Balazs Lecz
                                          (instance_name,
290 547a63b7 Balazs Lecz
                                           utils.TimestampForFilename()))
291 547a63b7 Balazs Lecz
        logging.warning("The chroot directory of instance %s can not be"
292 547a63b7 Balazs Lecz
                        " removed as it is not empty. Moving it to the"
293 547a63b7 Balazs Lecz
                        " quarantine instead. Please investigate the"
294 547a63b7 Balazs Lecz
                        " contents (%s) and clean up manually",
295 547a63b7 Balazs Lecz
                        instance_name, new_chroot_dir)
296 547a63b7 Balazs Lecz
        utils.RenameFile(chroot_dir, new_chroot_dir)
297 547a63b7 Balazs Lecz
      else:
298 547a63b7 Balazs Lecz
        raise
299 7e66c35b Guido Trotter
300 eb58f9b1 Guido Trotter
  def _WriteNetScript(self, instance, seq, nic):
301 eb58f9b1 Guido Trotter
    """Write a script to connect a net interface to the proper bridge.
302 eb58f9b1 Guido Trotter

303 eb58f9b1 Guido Trotter
    This can be used by any qemu-type hypervisor.
304 eb58f9b1 Guido Trotter

305 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
306 eb58f9b1 Guido Trotter
    @type instance: instance object
307 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
308 eb58f9b1 Guido Trotter
    @type seq: int
309 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
310 eb58f9b1 Guido Trotter
    @type nic: nic object
311 eb58f9b1 Guido Trotter
    @return: netscript file name
312 eb58f9b1 Guido Trotter
    @rtype: string
313 eb58f9b1 Guido Trotter

314 eb58f9b1 Guido Trotter
    """
315 eb58f9b1 Guido Trotter
    script = StringIO()
316 eb58f9b1 Guido Trotter
    script.write("#!/bin/sh\n")
317 eb58f9b1 Guido Trotter
    script.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
318 e8022bef Vitaly Kuznetsov
    script.write("PATH=$PATH:/sbin:/usr/sbin\n")
319 eb58f9b1 Guido Trotter
    script.write("export INSTANCE=%s\n" % instance.name)
320 eb58f9b1 Guido Trotter
    script.write("export MAC=%s\n" % nic.mac)
321 bef9c750 Guido Trotter
    if nic.ip:
322 bef9c750 Guido Trotter
      script.write("export IP=%s\n" % nic.ip)
323 bef9c750 Guido Trotter
    script.write("export MODE=%s\n" % nic.nicparams[constants.NIC_MODE])
324 bef9c750 Guido Trotter
    if nic.nicparams[constants.NIC_LINK]:
325 bef9c750 Guido Trotter
      script.write("export LINK=%s\n" % nic.nicparams[constants.NIC_LINK])
326 bef9c750 Guido Trotter
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
327 bef9c750 Guido Trotter
      script.write("export BRIDGE=%s\n" % nic.nicparams[constants.NIC_LINK])
328 eb58f9b1 Guido Trotter
    script.write("export INTERFACE=$1\n")
329 1cc831ea Guido Trotter
    if instance.tags:
330 1cc831ea Guido Trotter
      script.write("export TAGS=\"%s\"\n" % " ".join(instance.tags))
331 eb58f9b1 Guido Trotter
    # TODO: make this configurable at ./configure time
332 5420ffc9 Guido Trotter
    script.write("if [ -x '%s' ]; then\n" % self._KVM_NETWORK_SCRIPT)
333 eb58f9b1 Guido Trotter
    script.write("  # Execute the user-specific vif file\n")
334 5420ffc9 Guido Trotter
    script.write("  %s\n" % self._KVM_NETWORK_SCRIPT)
335 eb58f9b1 Guido Trotter
    script.write("else\n")
336 e8022bef Vitaly Kuznetsov
    script.write("  ifconfig $INTERFACE 0.0.0.0 up\n")
337 bef9c750 Guido Trotter
    if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
338 bef9c750 Guido Trotter
      script.write("  # Connect the interface to the bridge\n")
339 e8022bef Vitaly Kuznetsov
      script.write("  brctl addif $BRIDGE $INTERFACE\n")
340 bef9c750 Guido Trotter
    elif nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_ROUTED:
341 94c2ed34 Guido Trotter
      if not nic.ip:
342 94c2ed34 Guido Trotter
        raise errors.HypervisorError("nic/%d is routed, but has no ip." % seq)
343 bef9c750 Guido Trotter
      script.write("  # Route traffic targeted at the IP to the interface\n")
344 7c60f7a2 Guido Trotter
      if nic.nicparams[constants.NIC_LINK]:
345 e8022bef Vitaly Kuznetsov
        script.write("  while ip rule del dev $INTERFACE; do :; done\n")
346 e8022bef Vitaly Kuznetsov
        script.write("  ip rule add dev $INTERFACE table $LINK\n")
347 e8022bef Vitaly Kuznetsov
        script.write("  ip route replace $IP table $LINK proto static"
348 d63218ce Guido Trotter
                     " dev $INTERFACE\n")
349 7c60f7a2 Guido Trotter
      else:
350 e8022bef Vitaly Kuznetsov
        script.write("  ip route replace $IP proto static"
351 8866ec86 Guido Trotter
                     " dev $INTERFACE\n")
352 e014f1d0 Guido Trotter
      interface_v4_conf = "/proc/sys/net/ipv4/conf/$INTERFACE"
353 e014f1d0 Guido Trotter
      interface_v6_conf = "/proc/sys/net/ipv6/conf/$INTERFACE"
354 e014f1d0 Guido Trotter
      script.write("  if [ -d %s ]; then\n" % interface_v4_conf)
355 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/proxy_arp\n" % interface_v4_conf)
356 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/forwarding\n" % interface_v4_conf)
357 e014f1d0 Guido Trotter
      script.write("  fi\n")
358 e014f1d0 Guido Trotter
      script.write("  if [ -d %s ]; then\n" % interface_v6_conf)
359 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/proxy_ndp\n" % interface_v6_conf)
360 e014f1d0 Guido Trotter
      script.write("    echo 1 > %s/forwarding\n" % interface_v6_conf)
361 e014f1d0 Guido Trotter
      script.write("  fi\n")
362 eb58f9b1 Guido Trotter
    script.write("fi\n\n")
363 eb58f9b1 Guido Trotter
    # As much as we'd like to put this in our _ROOT_DIR, that will happen to be
364 eb58f9b1 Guido Trotter
    # mounted noexec sometimes, so we'll have to find another place.
365 eb58f9b1 Guido Trotter
    (tmpfd, tmpfile_name) = tempfile.mkstemp()
366 eb58f9b1 Guido Trotter
    tmpfile = os.fdopen(tmpfd, 'w')
367 d73ef63f Michael Hanselmann
    try:
368 d73ef63f Michael Hanselmann
      tmpfile.write(script.getvalue())
369 d73ef63f Michael Hanselmann
    finally:
370 d73ef63f Michael Hanselmann
      tmpfile.close()
371 eb58f9b1 Guido Trotter
    os.chmod(tmpfile_name, 0755)
372 eb58f9b1 Guido Trotter
    return tmpfile_name
373 eb58f9b1 Guido Trotter
374 eb58f9b1 Guido Trotter
  def ListInstances(self):
375 eb58f9b1 Guido Trotter
    """Get the list of running instances.
376 eb58f9b1 Guido Trotter

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

380 eb58f9b1 Guido Trotter
    """
381 eb58f9b1 Guido Trotter
    result = []
382 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
383 263b8de6 Guido Trotter
      if self._InstancePidAlive(name)[2]:
384 eb58f9b1 Guido Trotter
        result.append(name)
385 eb58f9b1 Guido Trotter
    return result
386 eb58f9b1 Guido Trotter
387 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
388 eb58f9b1 Guido Trotter
    """Get instance properties.
389 eb58f9b1 Guido Trotter

390 4fbb3c60 Guido Trotter
    @type instance_name: string
391 c41eea6e Iustin Pop
    @param instance_name: the instance name
392 4fbb3c60 Guido Trotter
    @rtype: tuple of strings
393 4fbb3c60 Guido Trotter
    @return: (name, id, memory, vcpus, stat, times)
394 eb58f9b1 Guido Trotter

395 eb58f9b1 Guido Trotter
    """
396 1122eb25 Iustin Pop
    _, pid, alive = self._InstancePidAlive(instance_name)
397 1f8b3a27 Guido Trotter
    if not alive:
398 eb58f9b1 Guido Trotter
      return None
399 eb58f9b1 Guido Trotter
400 263b8de6 Guido Trotter
    _, memory, vcpus = self._InstancePidInfo(pid)
401 eb58f9b1 Guido Trotter
    stat = "---b-"
402 eb58f9b1 Guido Trotter
    times = "0"
403 eb58f9b1 Guido Trotter
404 eb58f9b1 Guido Trotter
    return (instance_name, pid, memory, vcpus, stat, times)
405 eb58f9b1 Guido Trotter
406 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
407 eb58f9b1 Guido Trotter
    """Get properties of all instances.
408 eb58f9b1 Guido Trotter

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

411 eb58f9b1 Guido Trotter
    """
412 eb58f9b1 Guido Trotter
    data = []
413 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
414 263b8de6 Guido Trotter
      try:
415 263b8de6 Guido Trotter
        info = self.GetInstanceInfo(name)
416 263b8de6 Guido Trotter
      except errors.HypervisorError:
417 263b8de6 Guido Trotter
        continue
418 263b8de6 Guido Trotter
      if info:
419 263b8de6 Guido Trotter
        data.append(info)
420 eb58f9b1 Guido Trotter
    return data
421 eb58f9b1 Guido Trotter
422 07813a9e Iustin Pop
  def _GenerateKVMRuntime(self, instance, block_devices):
423 ee5f20b0 Guido Trotter
    """Generate KVM information to start an instance.
424 eb58f9b1 Guido Trotter

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

583 38e250ba Guido Trotter
    """
584 38e250ba Guido Trotter
    try:
585 38e250ba Guido Trotter
      utils.WriteFile(self._InstanceKVMRuntime(instance_name),
586 38e250ba Guido Trotter
                      data=data)
587 90c024f6 Guido Trotter
    except EnvironmentError, err:
588 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to save KVM runtime file: %s" % err)
589 38e250ba Guido Trotter
590 38e250ba Guido Trotter
  def _ReadKVMRuntime(self, instance_name):
591 38e250ba Guido Trotter
    """Read an instance's KVM runtime
592 38e250ba Guido Trotter

593 38e250ba Guido Trotter
    """
594 38e250ba Guido Trotter
    try:
595 38e250ba Guido Trotter
      file_content = utils.ReadFile(self._InstanceKVMRuntime(instance_name))
596 90c024f6 Guido Trotter
    except EnvironmentError, err:
597 38e250ba Guido Trotter
      raise errors.HypervisorError("Failed to load KVM runtime file: %s" % err)
598 38e250ba Guido Trotter
    return file_content
599 38e250ba Guido Trotter
600 38e250ba Guido Trotter
  def _SaveKVMRuntime(self, instance, kvm_runtime):
601 38e250ba Guido Trotter
    """Save an instance's KVM runtime
602 38e250ba Guido Trotter

603 38e250ba Guido Trotter
    """
604 c2672466 Guido Trotter
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
605 38e250ba Guido Trotter
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
606 c2672466 Guido Trotter
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
607 38e250ba Guido Trotter
    self._WriteKVMRuntime(instance.name, serialized_form)
608 38e250ba Guido Trotter
609 30e42c4e Guido Trotter
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
610 38e250ba Guido Trotter
    """Load an instance's KVM runtime
611 38e250ba Guido Trotter

612 38e250ba Guido Trotter
    """
613 30e42c4e Guido Trotter
    if not serialized_runtime:
614 30e42c4e Guido Trotter
      serialized_runtime = self._ReadKVMRuntime(instance.name)
615 30e42c4e Guido Trotter
    loaded_runtime = serializer.Load(serialized_runtime)
616 c2672466 Guido Trotter
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
617 38e250ba Guido Trotter
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
618 c2672466 Guido Trotter
    return (kvm_cmd, kvm_nics, hvparams)
619 38e250ba Guido Trotter
620 76431533 Guido Trotter
  def _RunKVMCmd(self, name, kvm_cmd):
621 76431533 Guido Trotter
    """Run the KVM cmd and check for errors
622 76431533 Guido Trotter

623 76431533 Guido Trotter
    @type name: string
624 76431533 Guido Trotter
    @param name: instance name
625 76431533 Guido Trotter
    @type kvm_cmd: list of strings
626 76431533 Guido Trotter
    @param kvm_cmd: runcmd input for kvm
627 76431533 Guido Trotter

628 76431533 Guido Trotter
    """
629 76431533 Guido Trotter
    result = utils.RunCmd(kvm_cmd)
630 76431533 Guido Trotter
    if result.failed:
631 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
632 76431533 Guido Trotter
                                   (name, result.fail_reason, result.output))
633 76431533 Guido Trotter
    if not self._InstancePidAlive(name)[2]:
634 76431533 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s" % name)
635 76431533 Guido Trotter
636 30e42c4e Guido Trotter
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, incoming=None):
637 ee5f20b0 Guido Trotter
    """Execute a KVM cmd, after completing it with some last minute data
638 ee5f20b0 Guido Trotter

639 30e42c4e Guido Trotter
    @type incoming: tuple of strings
640 30e42c4e Guido Trotter
    @param incoming: (target_host_ip, port)
641 30e42c4e Guido Trotter

642 ee5f20b0 Guido Trotter
    """
643 297e6e53 Guido Trotter
    # Small _ExecuteKVMRuntime hv parameters programming howto:
644 297e6e53 Guido Trotter
    #  - conf_hvp contains the parameters as configured on ganeti. they might
645 297e6e53 Guido Trotter
    #    have changed since the instance started; only use them if the change
646 297e6e53 Guido Trotter
    #    won't affect the inside of the instance (which hasn't been rebooted).
647 297e6e53 Guido Trotter
    #  - up_hvp contains the parameters as they were when the instance was
648 297e6e53 Guido Trotter
    #    started, plus any new parameter which has been added between ganeti
649 297e6e53 Guido Trotter
    #    versions: it is paramount that those default to a value which won't
650 297e6e53 Guido Trotter
    #    affect the inside of the instance as well.
651 297e6e53 Guido Trotter
    conf_hvp = instance.hvparams
652 5905901c Iustin Pop
    name = instance.name
653 5905901c Iustin Pop
    self._CheckDown(name)
654 ee5f20b0 Guido Trotter
655 ee5f20b0 Guido Trotter
    temp_files = []
656 ee5f20b0 Guido Trotter
657 297e6e53 Guido Trotter
    kvm_cmd, kvm_nics, up_hvp = kvm_runtime
658 297e6e53 Guido Trotter
    up_hvp = objects.FillDict(conf_hvp, up_hvp)
659 ee5f20b0 Guido Trotter
660 297e6e53 Guido Trotter
    # We know it's safe to run as a different user upon migration, so we'll use
661 297e6e53 Guido Trotter
    # the latest conf, from conf_hvp.
662 297e6e53 Guido Trotter
    security_model = conf_hvp[constants.HV_SECURITY_MODEL]
663 cef34868 Guido Trotter
    if security_model == constants.HT_SM_USER:
664 297e6e53 Guido Trotter
      kvm_cmd.extend(["-runas", conf_hvp[constants.HV_SECURITY_DOMAIN]])
665 cef34868 Guido Trotter
666 297e6e53 Guido Trotter
    # We have reasons to believe changing something like the nic driver/type
667 297e6e53 Guido Trotter
    # upon migration won't exactly fly with the instance kernel, so for nic
668 297e6e53 Guido Trotter
    # related parameters we'll use up_hvp
669 ee5f20b0 Guido Trotter
    if not kvm_nics:
670 fbe27e2b Guido Trotter
      kvm_cmd.extend(["-net", "none"])
671 ee5f20b0 Guido Trotter
    else:
672 fbe27e2b Guido Trotter
      tap_extra = ""
673 297e6e53 Guido Trotter
      nic_type = up_hvp[constants.HV_NIC_TYPE]
674 37f88dc6 Guido Trotter
      if nic_type == constants.HT_NIC_PARAVIRTUAL:
675 37f88dc6 Guido Trotter
        nic_model = "model=virtio"
676 297e6e53 Guido Trotter
        if up_hvp[constants.HV_VHOST_NET]:
677 fbe27e2b Guido Trotter
          tap_extra = ",vhost=on"
678 37f88dc6 Guido Trotter
      else:
679 37f88dc6 Guido Trotter
        nic_model = "model=%s" % nic_type
680 37f88dc6 Guido Trotter
681 ee5f20b0 Guido Trotter
      for nic_seq, nic in enumerate(kvm_nics):
682 760570a8 Timothy Kuhlman
        nic_val = "nic,vlan=%s,macaddr=%s,%s" % (nic_seq, nic.mac, nic_model)
683 ee5f20b0 Guido Trotter
        script = self._WriteNetScript(instance, nic_seq, nic)
684 fbe27e2b Guido Trotter
        tap_val = "tap,vlan=%s,script=%s%s" % (nic_seq, script, tap_extra)
685 fbe27e2b Guido Trotter
        kvm_cmd.extend(["-net", nic_val])
686 fbe27e2b Guido Trotter
        kvm_cmd.extend(["-net", tap_val])
687 ee5f20b0 Guido Trotter
        temp_files.append(script)
688 ee5f20b0 Guido Trotter
689 30e42c4e Guido Trotter
    if incoming:
690 30e42c4e Guido Trotter
      target, port = incoming
691 30e42c4e Guido Trotter
      kvm_cmd.extend(['-incoming', 'tcp:%s:%s' % (target, port)])
692 30e42c4e Guido Trotter
693 297e6e53 Guido Trotter
    # Changing the vnc password doesn't bother the guest that much. At most it
694 297e6e53 Guido Trotter
    # will surprise people who connect to it. Whether positively or negatively
695 297e6e53 Guido Trotter
    # it's debatable.
696 297e6e53 Guido Trotter
    vnc_pwd_file = conf_hvp[constants.HV_VNC_PASSWORD_FILE]
697 6e6bb8d5 Guido Trotter
    vnc_pwd = None
698 6e6bb8d5 Guido Trotter
    if vnc_pwd_file:
699 6e6bb8d5 Guido Trotter
      try:
700 682f7601 Guido Trotter
        vnc_pwd = utils.ReadOneLineFile(vnc_pwd_file, strict=True)
701 6e6bb8d5 Guido Trotter
      except EnvironmentError, err:
702 6e6bb8d5 Guido Trotter
        raise errors.HypervisorError("Failed to open VNC password file %s: %s"
703 6e6bb8d5 Guido Trotter
                                     % (vnc_pwd_file, err))
704 6e6bb8d5 Guido Trotter
705 297e6e53 Guido Trotter
    if conf_hvp[constants.HV_KVM_USE_CHROOT]:
706 547a63b7 Balazs Lecz
      utils.EnsureDirs([(self._InstanceChrootDir(name),
707 547a63b7 Balazs Lecz
                         constants.SECURE_DIR_MODE)])
708 547a63b7 Balazs Lecz
709 76431533 Guido Trotter
    if security_model == constants.HT_SM_POOL:
710 76431533 Guido Trotter
      ss = ssconf.SimpleStore()
711 76431533 Guido Trotter
      uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n")
712 76431533 Guido Trotter
      all_uids = set(uidpool.ExpandUidPool(uid_pool))
713 76431533 Guido Trotter
      uid = uidpool.RequestUnusedUid(all_uids)
714 76431533 Guido Trotter
      try:
715 76431533 Guido Trotter
        username = pwd.getpwuid(uid.GetUid()).pw_name
716 76431533 Guido Trotter
        kvm_cmd.extend(["-runas", username])
717 76431533 Guido Trotter
        self._RunKVMCmd(name, kvm_cmd)
718 76431533 Guido Trotter
      except:
719 76431533 Guido Trotter
        uidpool.ReleaseUid(uid)
720 76431533 Guido Trotter
        raise
721 76431533 Guido Trotter
      else:
722 76431533 Guido Trotter
        uid.Unlock()
723 76431533 Guido Trotter
        utils.WriteFile(self._InstanceUidFile(name), data=str(uid))
724 76431533 Guido Trotter
    else:
725 76431533 Guido Trotter
      self._RunKVMCmd(name, kvm_cmd)
726 eb58f9b1 Guido Trotter
727 6e6bb8d5 Guido Trotter
    if vnc_pwd:
728 6e6bb8d5 Guido Trotter
      change_cmd = 'change vnc password %s' % vnc_pwd
729 6e6bb8d5 Guido Trotter
      self._CallMonitorCommand(instance.name, change_cmd)
730 6e6bb8d5 Guido Trotter
731 08137f9e Iustin Pop
    for filename in temp_files:
732 08137f9e Iustin Pop
      utils.RemoveFile(filename)
733 eb58f9b1 Guido Trotter
734 07813a9e Iustin Pop
  def StartInstance(self, instance, block_devices):
735 ee5f20b0 Guido Trotter
    """Start an instance.
736 ee5f20b0 Guido Trotter

737 ee5f20b0 Guido Trotter
    """
738 5905901c Iustin Pop
    self._CheckDown(instance.name)
739 07813a9e Iustin Pop
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices)
740 38e250ba Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
741 ee5f20b0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
742 ee5f20b0 Guido Trotter
743 6567aff3 Guido Trotter
  def _CallMonitorCommand(self, instance_name, command):
744 6567aff3 Guido Trotter
    """Invoke a command on the instance monitor.
745 6567aff3 Guido Trotter

746 6567aff3 Guido Trotter
    """
747 6567aff3 Guido Trotter
    socat = ("echo %s | %s STDIO UNIX-CONNECT:%s" %
748 6567aff3 Guido Trotter
             (utils.ShellQuote(command),
749 6567aff3 Guido Trotter
              constants.SOCAT_PATH,
750 6567aff3 Guido Trotter
              utils.ShellQuote(self._InstanceMonitor(instance_name))))
751 6567aff3 Guido Trotter
    result = utils.RunCmd(socat)
752 6567aff3 Guido Trotter
    if result.failed:
753 6567aff3 Guido Trotter
      msg = ("Failed to send command '%s' to instance %s."
754 6567aff3 Guido Trotter
             " output: %s, error: %s, fail_reason: %s" %
755 9798fcae Guido Trotter
             (command, instance_name,
756 9798fcae Guido Trotter
              result.stdout, result.stderr, result.fail_reason))
757 6567aff3 Guido Trotter
      raise errors.HypervisorError(msg)
758 6567aff3 Guido Trotter
759 6567aff3 Guido Trotter
    return result
760 6567aff3 Guido Trotter
761 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
762 eb58f9b1 Guido Trotter
    """Stop an instance.
763 eb58f9b1 Guido Trotter

764 eb58f9b1 Guido Trotter
    """
765 bbcf7ad0 Iustin Pop
    if name is not None and not force:
766 bbcf7ad0 Iustin Pop
      raise errors.HypervisorError("Cannot shutdown cleanly by name only")
767 bbcf7ad0 Iustin Pop
    if name is None:
768 bbcf7ad0 Iustin Pop
      name = instance.name
769 bbcf7ad0 Iustin Pop
      acpi = instance.hvparams[constants.HV_ACPI]
770 bbcf7ad0 Iustin Pop
    else:
771 bbcf7ad0 Iustin Pop
      acpi = False
772 8904b35c Guido Trotter
    _, pid, alive = self._InstancePidAlive(name)
773 1f8b3a27 Guido Trotter
    if pid > 0 and alive:
774 bbcf7ad0 Iustin Pop
      if force or not acpi:
775 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
776 eb58f9b1 Guido Trotter
      else:
777 bbcf7ad0 Iustin Pop
        self._CallMonitorCommand(name, 'system_powerdown')
778 eb58f9b1 Guido Trotter
779 8904b35c Guido Trotter
  def CleanupInstance(self, instance_name):
780 8904b35c Guido Trotter
    """Cleanup after a stopped instance
781 8904b35c Guido Trotter

782 8904b35c Guido Trotter
    """
783 8904b35c Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
784 8904b35c Guido Trotter
    if pid > 0 and alive:
785 8904b35c Guido Trotter
      raise errors.HypervisorError("Cannot cleanup a live instance")
786 8904b35c Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
787 eb58f9b1 Guido Trotter
788 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
789 eb58f9b1 Guido Trotter
    """Reboot an instance.
790 eb58f9b1 Guido Trotter

791 eb58f9b1 Guido Trotter
    """
792 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
793 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
794 eb58f9b1 Guido Trotter
    # to shutdown and restart.
795 1122eb25 Iustin Pop
    _, _, alive = self._InstancePidAlive(instance.name)
796 1f8b3a27 Guido Trotter
    if not alive:
797 78411c60 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s:"
798 78411c60 Iustin Pop
                                   " not running" % instance.name)
799 f02881e0 Guido Trotter
    # StopInstance will delete the saved KVM runtime so:
800 f02881e0 Guido Trotter
    # ...first load it...
801 f02881e0 Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance)
802 f02881e0 Guido Trotter
    # ...now we can safely call StopInstance...
803 f02881e0 Guido Trotter
    if not self.StopInstance(instance):
804 f02881e0 Guido Trotter
      self.StopInstance(instance, force=True)
805 f02881e0 Guido Trotter
    # ...and finally we can save it again, and execute it...
806 f02881e0 Guido Trotter
    self._SaveKVMRuntime(instance, kvm_runtime)
807 f02881e0 Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime)
808 eb58f9b1 Guido Trotter
809 30e42c4e Guido Trotter
  def MigrationInfo(self, instance):
810 30e42c4e Guido Trotter
    """Get instance information to perform a migration.
811 30e42c4e Guido Trotter

812 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
813 30e42c4e Guido Trotter
    @param instance: instance to be migrated
814 30e42c4e Guido Trotter
    @rtype: string
815 30e42c4e Guido Trotter
    @return: content of the KVM runtime file
816 30e42c4e Guido Trotter

817 30e42c4e Guido Trotter
    """
818 30e42c4e Guido Trotter
    return self._ReadKVMRuntime(instance.name)
819 30e42c4e Guido Trotter
820 30e42c4e Guido Trotter
  def AcceptInstance(self, instance, info, target):
821 30e42c4e Guido Trotter
    """Prepare to accept an instance.
822 30e42c4e Guido Trotter

823 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
824 30e42c4e Guido Trotter
    @param instance: instance to be accepted
825 30e42c4e Guido Trotter
    @type info: string
826 30e42c4e Guido Trotter
    @param info: content of the KVM runtime file on the source node
827 30e42c4e Guido Trotter
    @type target: string
828 30e42c4e Guido Trotter
    @param target: target host (usually ip), on this node
829 30e42c4e Guido Trotter

830 30e42c4e Guido Trotter
    """
831 30e42c4e Guido Trotter
    kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
832 641ae041 Iustin Pop
    incoming_address = (target, instance.hvparams[constants.HV_MIGRATION_PORT])
833 30e42c4e Guido Trotter
    self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
834 30e42c4e Guido Trotter
835 30e42c4e Guido Trotter
  def FinalizeMigration(self, instance, info, success):
836 30e42c4e Guido Trotter
    """Finalize an instance migration.
837 30e42c4e Guido Trotter

838 30e42c4e Guido Trotter
    Stop the incoming mode KVM.
839 30e42c4e Guido Trotter

840 30e42c4e Guido Trotter
    @type instance: L{objects.Instance}
841 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
842 30e42c4e Guido Trotter

843 30e42c4e Guido Trotter
    """
844 30e42c4e Guido Trotter
    if success:
845 30e42c4e Guido Trotter
      self._WriteKVMRuntime(instance.name, info)
846 30e42c4e Guido Trotter
    else:
847 30e42c4e Guido Trotter
      self.StopInstance(instance, force=True)
848 30e42c4e Guido Trotter
849 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
850 30e42c4e Guido Trotter
    """Migrate an instance to a target node.
851 30e42c4e Guido Trotter

852 30e42c4e Guido Trotter
    The migration will not be attempted if the instance is not
853 30e42c4e Guido Trotter
    currently running.
854 30e42c4e Guido Trotter

855 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
856 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
857 30e42c4e Guido Trotter
    @type target: string
858 30e42c4e Guido Trotter
    @param target: ip address of the target node
859 30e42c4e Guido Trotter
    @type live: boolean
860 30e42c4e Guido Trotter
    @param live: perform a live migration
861 30e42c4e Guido Trotter

862 30e42c4e Guido Trotter
    """
863 58d38b02 Iustin Pop
    instance_name = instance.name
864 50716be0 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
865 30e42c4e Guido Trotter
    pidfile, pid, alive = self._InstancePidAlive(instance_name)
866 30e42c4e Guido Trotter
    if not alive:
867 30e42c4e Guido Trotter
      raise errors.HypervisorError("Instance not running, cannot migrate")
868 30e42c4e Guido Trotter
869 50716be0 Iustin Pop
    if not utils.TcpPing(target, port, live_port_needed=True):
870 50716be0 Iustin Pop
      raise errors.HypervisorError("Remote host %s not listening on port"
871 50716be0 Iustin Pop
                                   " %s, cannot migrate" % (target, port))
872 50716be0 Iustin Pop
873 30e42c4e Guido Trotter
    if not live:
874 30e42c4e Guido Trotter
      self._CallMonitorCommand(instance_name, 'stop')
875 30e42c4e Guido Trotter
876 e43d4f9f Apollon Oikonomopoulos
    migrate_command = ('migrate_set_speed %dm' %
877 e43d4f9f Apollon Oikonomopoulos
        instance.hvparams[constants.HV_MIGRATION_BANDWIDTH])
878 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
879 e43d4f9f Apollon Oikonomopoulos
880 e43d4f9f Apollon Oikonomopoulos
    migrate_command = ('migrate_set_downtime %dms' %
881 e43d4f9f Apollon Oikonomopoulos
        instance.hvparams[constants.HV_MIGRATION_DOWNTIME])
882 e43d4f9f Apollon Oikonomopoulos
    self._CallMonitorCommand(instance_name, migrate_command)
883 e43d4f9f Apollon Oikonomopoulos
884 641ae041 Iustin Pop
    migrate_command = 'migrate -d tcp:%s:%s' % (target, port)
885 30e42c4e Guido Trotter
    self._CallMonitorCommand(instance_name, migrate_command)
886 30e42c4e Guido Trotter
887 30e42c4e Guido Trotter
    info_command = 'info migrate'
888 30e42c4e Guido Trotter
    done = False
889 c4e388a5 Guido Trotter
    broken_answers = 0
890 30e42c4e Guido Trotter
    while not done:
891 30e42c4e Guido Trotter
      result = self._CallMonitorCommand(instance_name, info_command)
892 30e42c4e Guido Trotter
      match = self._MIGRATION_STATUS_RE.search(result.stdout)
893 30e42c4e Guido Trotter
      if not match:
894 c4e388a5 Guido Trotter
        broken_answers += 1
895 c4e388a5 Guido Trotter
        if not result.stdout:
896 c4e388a5 Guido Trotter
          logging.info("KVM: empty 'info migrate' result")
897 c4e388a5 Guido Trotter
        else:
898 e4dd2299 Guido Trotter
          logging.warning("KVM: unknown 'info migrate' result: %s",
899 c4e388a5 Guido Trotter
                          result.stdout)
900 c4e388a5 Guido Trotter
        time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
901 30e42c4e Guido Trotter
      else:
902 30e42c4e Guido Trotter
        status = match.group(1)
903 30e42c4e Guido Trotter
        if status == 'completed':
904 30e42c4e Guido Trotter
          done = True
905 30e42c4e Guido Trotter
        elif status == 'active':
906 c4e388a5 Guido Trotter
          # reset the broken answers count
907 c4e388a5 Guido Trotter
          broken_answers = 0
908 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
909 c087266c Guido Trotter
        elif status == 'failed' or status == 'cancelled':
910 c087266c Guido Trotter
          if not live:
911 c087266c Guido Trotter
            self._CallMonitorCommand(instance_name, 'cont')
912 c087266c Guido Trotter
          raise errors.HypervisorError("Migration %s at the kvm level" %
913 c087266c Guido Trotter
                                       status)
914 30e42c4e Guido Trotter
        else:
915 c4e388a5 Guido Trotter
          logging.warning("KVM: unknown migration status '%s'", status)
916 c4e388a5 Guido Trotter
          broken_answers += 1
917 c4e388a5 Guido Trotter
          time.sleep(self._MIGRATION_INFO_RETRY_DELAY)
918 c4e388a5 Guido Trotter
      if broken_answers >= self._MIGRATION_INFO_MAX_BAD_ANSWERS:
919 c4e388a5 Guido Trotter
        raise errors.HypervisorError("Too many 'info migrate' broken answers")
920 30e42c4e Guido Trotter
921 30e42c4e Guido Trotter
    utils.KillProcess(pid)
922 7b381438 Guido Trotter
    self._RemoveInstanceRuntimeFiles(pidfile, instance_name)
923 30e42c4e Guido Trotter
924 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
925 eb58f9b1 Guido Trotter
    """Return information about the node.
926 eb58f9b1 Guido Trotter

927 572e52bf Iustin Pop
    This is just a wrapper over the base GetLinuxNodeInfo method.
928 572e52bf Iustin Pop

929 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
930 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
931 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
932 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
933 eb58f9b1 Guido Trotter

934 eb58f9b1 Guido Trotter
    """
935 572e52bf Iustin Pop
    return self.GetLinuxNodeInfo()
936 eb58f9b1 Guido Trotter
937 637ce7f9 Guido Trotter
  @classmethod
938 5431b2e4 Guido Trotter
  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
939 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
940 eb58f9b1 Guido Trotter

941 eb58f9b1 Guido Trotter
    """
942 a2faf9ee Guido Trotter
    if hvparams[constants.HV_SERIAL_CONSOLE]:
943 86d6bc2a Guido Trotter
      shell_command = ("%s STDIO,%s UNIX-CONNECT:%s" %
944 86d6bc2a Guido Trotter
                       (constants.SOCAT_PATH, cls._SocatUnixConsoleParams(),
945 a2faf9ee Guido Trotter
                        utils.ShellQuote(cls._InstanceSerial(instance.name))))
946 a2faf9ee Guido Trotter
    else:
947 a2faf9ee Guido Trotter
      shell_command = "echo 'No serial shell for instance %s'" % instance.name
948 3be34f57 Guido Trotter
949 3be34f57 Guido Trotter
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
950 3be34f57 Guido Trotter
    if vnc_bind_address:
951 377d74c9 Guido Trotter
      if instance.network_port > constants.VNC_BASE_PORT:
952 377d74c9 Guido Trotter
        display = instance.network_port - constants.VNC_BASE_PORT
953 3be34f57 Guido Trotter
        vnc_command = ("echo 'Instance has VNC listening on %s:%d"
954 3be34f57 Guido Trotter
                       " (display: %d)'" % (vnc_bind_address,
955 3be34f57 Guido Trotter
                                            instance.network_port,
956 3be34f57 Guido Trotter
                                            display))
957 3be34f57 Guido Trotter
        shell_command = "%s; %s" % (vnc_command, shell_command)
958 3be34f57 Guido Trotter
959 a2faf9ee Guido Trotter
    return shell_command
960 eb58f9b1 Guido Trotter
961 eb58f9b1 Guido Trotter
  def Verify(self):
962 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
963 eb58f9b1 Guido Trotter

964 eb58f9b1 Guido Trotter
    Check that the binary exists.
965 eb58f9b1 Guido Trotter

966 eb58f9b1 Guido Trotter
    """
967 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
968 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
969 14aa53cb Guido Trotter
    if not os.path.exists(constants.SOCAT_PATH):
970 14aa53cb Guido Trotter
      return "The socat binary ('%s') does not exist." % constants.SOCAT_PATH
971 14aa53cb Guido Trotter
972 6b5605e8 Iustin Pop
973 6b5605e8 Iustin Pop
  @classmethod
974 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
975 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
976 6b5605e8 Iustin Pop

977 6b5605e8 Iustin Pop
    @type hvparams:  dict
978 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
979 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
980 6b5605e8 Iustin Pop

981 6b5605e8 Iustin Pop
    """
982 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
983 6b5605e8 Iustin Pop
984 df5ab9f0 Guido Trotter
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
985 df5ab9f0 Guido Trotter
    if kernel_path:
986 df5ab9f0 Guido Trotter
      if not hvparams[constants.HV_ROOT_PATH]:
987 205ab586 Iustin Pop
        raise errors.HypervisorError("Need a root partition for the instance,"
988 205ab586 Iustin Pop
                                     " if a kernel is defined")
989 6b5605e8 Iustin Pop
990 205ab586 Iustin Pop
    if (hvparams[constants.HV_VNC_X509_VERIFY] and
991 205ab586 Iustin Pop
        not hvparams[constants.HV_VNC_X509]):
992 205ab586 Iustin Pop
      raise errors.HypervisorError("%s must be defined, if %s is" %
993 205ab586 Iustin Pop
                                   (constants.HV_VNC_X509,
994 205ab586 Iustin Pop
                                    constants.HV_VNC_X509_VERIFY))
995 66d5dbef Guido Trotter
996 66d5dbef Guido Trotter
    boot_order = hvparams[constants.HV_BOOT_ORDER]
997 205ab586 Iustin Pop
    if (boot_order == constants.HT_BO_CDROM and
998 205ab586 Iustin Pop
        not hvparams[constants.HV_CDROM_IMAGE_PATH]):
999 835528af Iustin Pop
      raise errors.HypervisorError("Cannot boot from cdrom without an"
1000 835528af Iustin Pop
                                   " ISO path")
1001 f5118ade Iustin Pop
1002 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
1003 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
1004 d19d94db Guido Trotter
      if not hvparams[constants.HV_SECURITY_DOMAIN]:
1005 d19d94db Guido Trotter
        raise errors.HypervisorError("A security domain (user to run kvm as)"
1006 d19d94db Guido Trotter
                                     " must be specified")
1007 d19d94db Guido Trotter
    elif (security_model == constants.HT_SM_NONE or
1008 d19d94db Guido Trotter
          security_model == constants.HT_SM_POOL):
1009 d19d94db Guido Trotter
      if hvparams[constants.HV_SECURITY_DOMAIN]:
1010 d19d94db Guido Trotter
        raise errors.HypervisorError("Cannot have a security domain when the"
1011 d19d94db Guido Trotter
                                     " security model is 'none' or 'pool'")
1012 d19d94db Guido Trotter
1013 d19d94db Guido Trotter
  @classmethod
1014 d19d94db Guido Trotter
  def ValidateParameters(cls, hvparams):
1015 d19d94db Guido Trotter
    """Check the given parameters for validity.
1016 d19d94db Guido Trotter

1017 d19d94db Guido Trotter
    @type hvparams:  dict
1018 d19d94db Guido Trotter
    @param hvparams: dictionary with parameter names/value
1019 d19d94db Guido Trotter
    @raise errors.HypervisorError: when a parameter is not valid
1020 d19d94db Guido Trotter

1021 d19d94db Guido Trotter
    """
1022 d19d94db Guido Trotter
    super(KVMHypervisor, cls).ValidateParameters(hvparams)
1023 d19d94db Guido Trotter
1024 d19d94db Guido Trotter
    security_model = hvparams[constants.HV_SECURITY_MODEL]
1025 d19d94db Guido Trotter
    if security_model == constants.HT_SM_USER:
1026 d19d94db Guido Trotter
      username = hvparams[constants.HV_SECURITY_DOMAIN]
1027 d19d94db Guido Trotter
      try:
1028 1feb39ec Guido Trotter
        pwd.getpwnam(username)
1029 d19d94db Guido Trotter
      except KeyError:
1030 d19d94db Guido Trotter
        raise errors.HypervisorError("Unknown security domain user %s"
1031 d19d94db Guido Trotter
                                     % username)
1032 d19d94db Guido Trotter
1033 f5118ade Iustin Pop
  @classmethod
1034 f5118ade Iustin Pop
  def PowercycleNode(cls):
1035 f5118ade Iustin Pop
    """KVM powercycle, just a wrapper over Linux powercycle.
1036 f5118ade Iustin Pop

1037 f5118ade Iustin Pop
    """
1038 f5118ade Iustin Pop
    cls.LinuxPowercycle()