Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 47387b1e

History | View | Annotate | Download (12.7 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 eb58f9b1 Guido Trotter
from cStringIO import StringIO
31 eb58f9b1 Guido Trotter
32 eb58f9b1 Guido Trotter
from ganeti import utils
33 eb58f9b1 Guido Trotter
from ganeti import constants
34 eb58f9b1 Guido Trotter
from ganeti import errors
35 eb58f9b1 Guido Trotter
from ganeti.hypervisor import hv_base
36 eb58f9b1 Guido Trotter
37 eb58f9b1 Guido Trotter
38 eb58f9b1 Guido Trotter
class KVMHypervisor(hv_base.BaseHypervisor):
39 eb58f9b1 Guido Trotter
  """Fake hypervisor interface.
40 eb58f9b1 Guido Trotter

41 eb58f9b1 Guido Trotter
  This can be used for testing the ganeti code without having to have
42 eb58f9b1 Guido Trotter
  a real virtualisation software installed.
43 eb58f9b1 Guido Trotter

44 eb58f9b1 Guido Trotter
  """
45 eb58f9b1 Guido Trotter
  _ROOT_DIR = constants.RUN_GANETI_DIR + "/kvm-hypervisor"
46 eb58f9b1 Guido Trotter
  _PIDS_DIR = _ROOT_DIR + "/pid"
47 eb58f9b1 Guido Trotter
  _CTRL_DIR = _ROOT_DIR + "/ctrl"
48 eb58f9b1 Guido Trotter
  _DIRS = [_ROOT_DIR, _PIDS_DIR, _CTRL_DIR]
49 eb58f9b1 Guido Trotter
50 6b5605e8 Iustin Pop
  PARAMETERS = [
51 6b5605e8 Iustin Pop
    constants.HV_KERNEL_PATH,
52 6b5605e8 Iustin Pop
    constants.HV_INITRD_PATH,
53 6b5605e8 Iustin Pop
    constants.HV_ACPI,
54 6b5605e8 Iustin Pop
    ]
55 6b5605e8 Iustin Pop
56 eb58f9b1 Guido Trotter
  def __init__(self):
57 eb58f9b1 Guido Trotter
    hv_base.BaseHypervisor.__init__(self)
58 eb58f9b1 Guido Trotter
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
59 eb58f9b1 Guido Trotter
    # in a tmpfs filesystem or has been otherwise wiped out.
60 eb58f9b1 Guido Trotter
    for dir in self._DIRS:
61 eb58f9b1 Guido Trotter
      if not os.path.exists(dir):
62 eb58f9b1 Guido Trotter
        os.mkdir(dir)
63 eb58f9b1 Guido Trotter
64 eb58f9b1 Guido Trotter
  def _WriteNetScript(self, instance, seq, nic):
65 eb58f9b1 Guido Trotter
    """Write a script to connect a net interface to the proper bridge.
66 eb58f9b1 Guido Trotter

67 eb58f9b1 Guido Trotter
    This can be used by any qemu-type hypervisor.
68 eb58f9b1 Guido Trotter

69 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
70 eb58f9b1 Guido Trotter
    @type instance: instance object
71 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
72 eb58f9b1 Guido Trotter
    @type seq: int
73 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
74 eb58f9b1 Guido Trotter
    @type nic: nic object
75 eb58f9b1 Guido Trotter
    @return: netscript file name
76 eb58f9b1 Guido Trotter
    @rtype: string
77 eb58f9b1 Guido Trotter

78 eb58f9b1 Guido Trotter
    """
79 eb58f9b1 Guido Trotter
    script = StringIO()
80 eb58f9b1 Guido Trotter
    script.write("#!/bin/sh\n")
81 eb58f9b1 Guido Trotter
    script.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
82 eb58f9b1 Guido Trotter
    script.write("export INSTANCE=%s\n" % instance.name)
83 eb58f9b1 Guido Trotter
    script.write("export MAC=%s\n" % nic.mac)
84 eb58f9b1 Guido Trotter
    script.write("export IP=%s\n" % nic.ip)
85 eb58f9b1 Guido Trotter
    script.write("export BRIDGE=%s\n" % nic.bridge)
86 eb58f9b1 Guido Trotter
    script.write("export INTERFACE=$1\n")
87 eb58f9b1 Guido Trotter
    # TODO: make this configurable at ./configure time
88 eb58f9b1 Guido Trotter
    script.write("if [ -x /etc/ganeti/kvm-vif-bridge ]; then\n")
89 eb58f9b1 Guido Trotter
    script.write("  # Execute the user-specific vif file\n")
90 eb58f9b1 Guido Trotter
    script.write("  /etc/ganeti/kvm-vif-bridge\n")
91 eb58f9b1 Guido Trotter
    script.write("else\n")
92 eb58f9b1 Guido Trotter
    script.write("  # Connect the interface to the bridge\n")
93 eb58f9b1 Guido Trotter
    script.write("  /sbin/ifconfig $INTERFACE 0.0.0.0 up\n")
94 eb58f9b1 Guido Trotter
    script.write("  /usr/sbin/brctl addif $BRIDGE $INTERFACE\n")
95 eb58f9b1 Guido Trotter
    script.write("fi\n\n")
96 eb58f9b1 Guido Trotter
    # As much as we'd like to put this in our _ROOT_DIR, that will happen to be
97 eb58f9b1 Guido Trotter
    # mounted noexec sometimes, so we'll have to find another place.
98 eb58f9b1 Guido Trotter
    (tmpfd, tmpfile_name) = tempfile.mkstemp()
99 eb58f9b1 Guido Trotter
    tmpfile = os.fdopen(tmpfd, 'w')
100 eb58f9b1 Guido Trotter
    tmpfile.write(script.getvalue())
101 eb58f9b1 Guido Trotter
    tmpfile.close()
102 eb58f9b1 Guido Trotter
    os.chmod(tmpfile_name, 0755)
103 eb58f9b1 Guido Trotter
    return tmpfile_name
104 eb58f9b1 Guido Trotter
105 eb58f9b1 Guido Trotter
  def ListInstances(self):
106 eb58f9b1 Guido Trotter
    """Get the list of running instances.
107 eb58f9b1 Guido Trotter

108 eb58f9b1 Guido Trotter
    We can do this by listing our live instances directory and checking whether
109 eb58f9b1 Guido Trotter
    the associated kvm process is still alive.
110 eb58f9b1 Guido Trotter

111 eb58f9b1 Guido Trotter
    """
112 eb58f9b1 Guido Trotter
    result = []
113 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
114 eb58f9b1 Guido Trotter
      file = "%s/%s" % (self._PIDS_DIR, name)
115 eb58f9b1 Guido Trotter
      if utils.IsProcessAlive(utils.ReadPidFile(file)):
116 eb58f9b1 Guido Trotter
        result.append(name)
117 eb58f9b1 Guido Trotter
    return result
118 eb58f9b1 Guido Trotter
119 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
120 eb58f9b1 Guido Trotter
    """Get instance properties.
121 eb58f9b1 Guido Trotter

122 eb58f9b1 Guido Trotter
    Args:
123 eb58f9b1 Guido Trotter
      instance_name: the instance name
124 eb58f9b1 Guido Trotter

125 eb58f9b1 Guido Trotter
    Returns:
126 eb58f9b1 Guido Trotter
      (name, id, memory, vcpus, stat, times)
127 eb58f9b1 Guido Trotter
    """
128 eb58f9b1 Guido Trotter
    pidfile = "%s/%s" % (self._PIDS_DIR, instance_name)
129 eb58f9b1 Guido Trotter
    pid = utils.ReadPidFile(pidfile)
130 eb58f9b1 Guido Trotter
    if not utils.IsProcessAlive(pid):
131 eb58f9b1 Guido Trotter
      return None
132 eb58f9b1 Guido Trotter
133 eb58f9b1 Guido Trotter
    cmdline_file = "/proc/%s/cmdline" % pid
134 eb58f9b1 Guido Trotter
    try:
135 eb58f9b1 Guido Trotter
      fh = open(cmdline_file, 'r')
136 eb58f9b1 Guido Trotter
      try:
137 eb58f9b1 Guido Trotter
        cmdline = fh.read()
138 eb58f9b1 Guido Trotter
      finally:
139 eb58f9b1 Guido Trotter
        fh.close()
140 eb58f9b1 Guido Trotter
    except IOError, err:
141 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to list instance %s: %s" %
142 eb58f9b1 Guido Trotter
                                   (instance_name, err))
143 eb58f9b1 Guido Trotter
144 eb58f9b1 Guido Trotter
    memory = 0
145 eb58f9b1 Guido Trotter
    vcpus = 0
146 eb58f9b1 Guido Trotter
    stat = "---b-"
147 eb58f9b1 Guido Trotter
    times = "0"
148 eb58f9b1 Guido Trotter
149 eb58f9b1 Guido Trotter
    arg_list = cmdline.split('\x00')
150 eb58f9b1 Guido Trotter
    while arg_list:
151 eb58f9b1 Guido Trotter
      arg =  arg_list.pop(0)
152 eb58f9b1 Guido Trotter
      if arg == '-m':
153 eb58f9b1 Guido Trotter
        memory = arg_list.pop(0)
154 eb58f9b1 Guido Trotter
      elif arg == '-smp':
155 eb58f9b1 Guido Trotter
        vcpus = arg_list.pop(0)
156 eb58f9b1 Guido Trotter
157 eb58f9b1 Guido Trotter
    return (instance_name, pid, memory, vcpus, stat, times)
158 eb58f9b1 Guido Trotter
159 eb58f9b1 Guido Trotter
  def GetAllInstancesInfo(self):
160 eb58f9b1 Guido Trotter
    """Get properties of all instances.
161 eb58f9b1 Guido Trotter

162 eb58f9b1 Guido Trotter
    Returns:
163 eb58f9b1 Guido Trotter
      [(name, id, memory, vcpus, stat, times),...]
164 eb58f9b1 Guido Trotter
    """
165 eb58f9b1 Guido Trotter
    data = []
166 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
167 eb58f9b1 Guido Trotter
      file = "%s/%s" % (self._PIDS_DIR, name)
168 eb58f9b1 Guido Trotter
      if utils.IsProcessAlive(utils.ReadPidFile(file)):
169 eb58f9b1 Guido Trotter
        data.append(self.GetInstanceInfo(name))
170 eb58f9b1 Guido Trotter
171 eb58f9b1 Guido Trotter
    return data
172 eb58f9b1 Guido Trotter
173 eb58f9b1 Guido Trotter
  def StartInstance(self, instance, block_devices, extra_args):
174 eb58f9b1 Guido Trotter
    """Start an instance.
175 eb58f9b1 Guido Trotter

176 eb58f9b1 Guido Trotter
    """
177 eb58f9b1 Guido Trotter
    temp_files = []
178 eb58f9b1 Guido Trotter
    pidfile = self._PIDS_DIR + "/%s" % instance.name
179 eb58f9b1 Guido Trotter
    if utils.IsProcessAlive(utils.ReadPidFile(pidfile)):
180 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s" %
181 eb58f9b1 Guido Trotter
                                   (instance.name, "already running"))
182 eb58f9b1 Guido Trotter
183 eb58f9b1 Guido Trotter
    kvm = constants.KVM_PATH
184 eb58f9b1 Guido Trotter
    kvm_cmd = [kvm]
185 8b3fd458 Iustin Pop
    kvm_cmd.extend(['-m', instance.beparams[constants.BE_MEMORY]])
186 8b3fd458 Iustin Pop
    kvm_cmd.extend(['-smp', instance.beparams[constants.BE_VCPUS]])
187 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-pidfile', pidfile])
188 eb58f9b1 Guido Trotter
    # used just by the vnc server, if enabled
189 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-name', instance.name])
190 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-daemonize'])
191 6b5605e8 Iustin Pop
    if not instance.hvparams[constants.HV_ACPI]:
192 eb58f9b1 Guido Trotter
      kvm_cmd.extend(['-no-acpi'])
193 eb58f9b1 Guido Trotter
    if not instance.nics:
194 eb58f9b1 Guido Trotter
      kvm_cmd.extend(['-net', 'none'])
195 eb58f9b1 Guido Trotter
    else:
196 eb58f9b1 Guido Trotter
      nic_seq = 0
197 eb58f9b1 Guido Trotter
      for nic in instance.nics:
198 eb58f9b1 Guido Trotter
        script = self._WriteNetScript(instance, nic_seq, nic)
199 eb58f9b1 Guido Trotter
        # FIXME: handle other models
200 eb58f9b1 Guido Trotter
        nic_val = "nic,macaddr=%s,model=virtio" % nic.mac
201 eb58f9b1 Guido Trotter
        kvm_cmd.extend(['-net', nic_val])
202 eb58f9b1 Guido Trotter
        kvm_cmd.extend(['-net', 'tap,script=%s' % script])
203 eb58f9b1 Guido Trotter
        temp_files.append(script)
204 eb58f9b1 Guido Trotter
        nic_seq += 1
205 eb58f9b1 Guido Trotter
206 eb58f9b1 Guido Trotter
    boot_drive = True
207 eb58f9b1 Guido Trotter
    for cfdev, rldev in block_devices:
208 eb58f9b1 Guido Trotter
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
209 eb58f9b1 Guido Trotter
      if boot_drive:
210 eb58f9b1 Guido Trotter
        boot_val = ',boot=on'
211 d47d3d38 Guido Trotter
        boot_drive = False
212 eb58f9b1 Guido Trotter
      else:
213 eb58f9b1 Guido Trotter
        boot_val = ''
214 eb58f9b1 Guido Trotter
215 d47d3d38 Guido Trotter
      # TODO: handle different if= types
216 d47d3d38 Guido Trotter
      if_val = ',if=virtio'
217 d47d3d38 Guido Trotter
218 d47d3d38 Guido Trotter
      drive_val = 'file=%s,format=raw%s%s' % (rldev.dev_path, if_val, boot_val)
219 eb58f9b1 Guido Trotter
      kvm_cmd.extend(['-drive', drive_val])
220 eb58f9b1 Guido Trotter
221 6b5605e8 Iustin Pop
    kvm_cmd.extend(['-kernel', instance.hvparams[HV_KERNEL_PATH]])
222 6b5605e8 Iustin Pop
    initrd_path = instance.hvparams[HV_INITRD_PATH]
223 eb58f9b1 Guido Trotter
    if initrd_path:
224 eb58f9b1 Guido Trotter
      kvm_cmd.extend(['-initrd', initrd_path])
225 eb58f9b1 Guido Trotter
226 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-append', 'console=ttyS0,38400 root=/dev/vda'])
227 eb58f9b1 Guido Trotter
228 eb58f9b1 Guido Trotter
    #"hvm_boot_order",
229 eb58f9b1 Guido Trotter
    #"hvm_cdrom_image_path",
230 eb58f9b1 Guido Trotter
231 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-nographic'])
232 eb58f9b1 Guido Trotter
    # FIXME: handle vnc, if needed
233 eb58f9b1 Guido Trotter
    # How do we decide whether to have it or not?? :(
234 eb58f9b1 Guido Trotter
    #"vnc_bind_address",
235 eb58f9b1 Guido Trotter
    #"network_port"
236 eb58f9b1 Guido Trotter
    base_control = '%s/%s' % (self._CTRL_DIR, instance.name)
237 eb58f9b1 Guido Trotter
    monitor_dev = 'unix:%s.monitor,server,nowait' % base_control
238 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-monitor', monitor_dev])
239 eb58f9b1 Guido Trotter
    serial_dev = 'unix:%s.serial,server,nowait' % base_control
240 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-serial', serial_dev])
241 eb58f9b1 Guido Trotter
242 eb58f9b1 Guido Trotter
    result = utils.RunCmd(kvm_cmd)
243 eb58f9b1 Guido Trotter
    if result.failed:
244 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
245 eb58f9b1 Guido Trotter
                                   (instance.name, result.fail_reason,
246 eb58f9b1 Guido Trotter
                                    result.output))
247 eb58f9b1 Guido Trotter
248 eb58f9b1 Guido Trotter
    if not utils.IsProcessAlive(utils.ReadPidFile(pidfile)):
249 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s" %
250 eb58f9b1 Guido Trotter
                                   (instance.name))
251 eb58f9b1 Guido Trotter
252 eb58f9b1 Guido Trotter
    for file in temp_files:
253 eb58f9b1 Guido Trotter
      utils.RemoveFile(file)
254 eb58f9b1 Guido Trotter
255 eb58f9b1 Guido Trotter
  def StopInstance(self, instance, force=False):
256 eb58f9b1 Guido Trotter
    """Stop an instance.
257 eb58f9b1 Guido Trotter

258 eb58f9b1 Guido Trotter
    """
259 eb58f9b1 Guido Trotter
    pid_file = self._PIDS_DIR + "/%s" % instance.name
260 eb58f9b1 Guido Trotter
    pid = utils.ReadPidFile(pid_file)
261 eb58f9b1 Guido Trotter
    if pid > 0 and utils.IsProcessAlive(pid):
262 6b5605e8 Iustin Pop
      if force or not instance.hvparams[constants.HV_ACPI]:
263 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
264 eb58f9b1 Guido Trotter
      else:
265 eb58f9b1 Guido Trotter
        # This only works if the instance os has acpi support
266 eb58f9b1 Guido Trotter
        monitor_socket = '%s/%s.monitor'  % (self._CTRL_DIR, instance.name)
267 eb58f9b1 Guido Trotter
        socat = 'socat -u STDIN UNIX-CONNECT:%s' % monitor_socket
268 eb58f9b1 Guido Trotter
        command = "echo 'system_powerdown' | %s" % socat
269 eb58f9b1 Guido Trotter
        result = utils.RunCmd(command)
270 eb58f9b1 Guido Trotter
        if result.failed:
271 eb58f9b1 Guido Trotter
          raise errors.HypervisorError("Failed to stop instance %s: %s" %
272 eb58f9b1 Guido Trotter
                                       (instance.name, result.fail_reason))
273 eb58f9b1 Guido Trotter
274 eb58f9b1 Guido Trotter
    if not utils.IsProcessAlive(pid):
275 eb58f9b1 Guido Trotter
      utils.RemoveFile(pid_file)
276 eb58f9b1 Guido Trotter
277 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
278 eb58f9b1 Guido Trotter
    """Reboot an instance.
279 eb58f9b1 Guido Trotter

280 eb58f9b1 Guido Trotter
    """
281 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
282 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
283 eb58f9b1 Guido Trotter
    # to shutdown and restart.
284 eb58f9b1 Guido Trotter
    self.StopInstance(instance)
285 eb58f9b1 Guido Trotter
    self.StartInstance(instance)
286 eb58f9b1 Guido Trotter
287 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
288 eb58f9b1 Guido Trotter
    """Return information about the node.
289 eb58f9b1 Guido Trotter

290 eb58f9b1 Guido Trotter
    The return value is a dict, which has to have the following items:
291 eb58f9b1 Guido Trotter
      (all values in MiB)
292 eb58f9b1 Guido Trotter
      - memory_total: the total memory size on the node
293 eb58f9b1 Guido Trotter
      - memory_free: the available memory on the node for instances
294 eb58f9b1 Guido Trotter
      - memory_dom0: the memory used by the node itself, if available
295 eb58f9b1 Guido Trotter

296 eb58f9b1 Guido Trotter
    """
297 eb58f9b1 Guido Trotter
    # global ram usage from the xm info command
298 eb58f9b1 Guido Trotter
    # memory                 : 3583
299 eb58f9b1 Guido Trotter
    # free_memory            : 747
300 eb58f9b1 Guido Trotter
    # note: in xen 3, memory has changed to total_memory
301 eb58f9b1 Guido Trotter
    try:
302 eb58f9b1 Guido Trotter
      fh = file("/proc/meminfo")
303 eb58f9b1 Guido Trotter
      try:
304 eb58f9b1 Guido Trotter
        data = fh.readlines()
305 eb58f9b1 Guido Trotter
      finally:
306 eb58f9b1 Guido Trotter
        fh.close()
307 eb58f9b1 Guido Trotter
    except IOError, err:
308 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to list node info: %s" % err)
309 eb58f9b1 Guido Trotter
310 eb58f9b1 Guido Trotter
    result = {}
311 eb58f9b1 Guido Trotter
    sum_free = 0
312 eb58f9b1 Guido Trotter
    for line in data:
313 eb58f9b1 Guido Trotter
      splitfields = line.split(":", 1)
314 eb58f9b1 Guido Trotter
315 eb58f9b1 Guido Trotter
      if len(splitfields) > 1:
316 eb58f9b1 Guido Trotter
        key = splitfields[0].strip()
317 eb58f9b1 Guido Trotter
        val = splitfields[1].strip()
318 eb58f9b1 Guido Trotter
        if key == 'MemTotal':
319 eb58f9b1 Guido Trotter
          result['memory_total'] = int(val.split()[0])/1024
320 eb58f9b1 Guido Trotter
        elif key in ('MemFree', 'Buffers', 'Cached'):
321 eb58f9b1 Guido Trotter
          sum_free += int(val.split()[0])/1024
322 eb58f9b1 Guido Trotter
        elif key == 'Active':
323 eb58f9b1 Guido Trotter
          result['memory_dom0'] = int(val.split()[0])/1024
324 eb58f9b1 Guido Trotter
    result['memory_free'] = sum_free
325 eb58f9b1 Guido Trotter
326 eb58f9b1 Guido Trotter
    cpu_total = 0
327 eb58f9b1 Guido Trotter
    try:
328 eb58f9b1 Guido Trotter
      fh = open("/proc/cpuinfo")
329 eb58f9b1 Guido Trotter
      try:
330 eb58f9b1 Guido Trotter
        cpu_total = len(re.findall("(?m)^processor\s*:\s*[0-9]+\s*$",
331 eb58f9b1 Guido Trotter
                                   fh.read()))
332 eb58f9b1 Guido Trotter
      finally:
333 eb58f9b1 Guido Trotter
        fh.close()
334 eb58f9b1 Guido Trotter
    except EnvironmentError, err:
335 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to list node info: %s" % err)
336 eb58f9b1 Guido Trotter
    result['cpu_total'] = cpu_total
337 eb58f9b1 Guido Trotter
338 eb58f9b1 Guido Trotter
    return result
339 eb58f9b1 Guido Trotter
340 eb58f9b1 Guido Trotter
  @staticmethod
341 eb58f9b1 Guido Trotter
  def GetShellCommandForConsole(instance):
342 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
343 eb58f9b1 Guido Trotter

344 eb58f9b1 Guido Trotter
    """
345 eb58f9b1 Guido Trotter
    # TODO: we can either try the serial socket or suggest vnc
346 eb58f9b1 Guido Trotter
    return "echo Console not available for the kvm hypervisor yet"
347 eb58f9b1 Guido Trotter
348 eb58f9b1 Guido Trotter
  def Verify(self):
349 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
350 eb58f9b1 Guido Trotter

351 eb58f9b1 Guido Trotter
    Check that the binary exists.
352 eb58f9b1 Guido Trotter

353 eb58f9b1 Guido Trotter
    """
354 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
355 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH
356 6b5605e8 Iustin Pop
357 6b5605e8 Iustin Pop
  @classmethod
358 6b5605e8 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
359 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
360 6b5605e8 Iustin Pop

361 6b5605e8 Iustin Pop
    For the KVM hypervisor, this only check the existence of the
362 6b5605e8 Iustin Pop
    kernel.
363 6b5605e8 Iustin Pop

364 6b5605e8 Iustin Pop
    @type hvparams:  dict
365 6b5605e8 Iustin Pop
    @param hvparams: dictionary with parameter names/value
366 6b5605e8 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
367 6b5605e8 Iustin Pop

368 6b5605e8 Iustin Pop
    """
369 47387b1e Guido Trotter
    super(KVMHypervisor, cls).CheckParameterSyntax(hvparams)
370 6b5605e8 Iustin Pop
371 6b5605e8 Iustin Pop
    if not hvparams[constants.HV_KERNEL_PATH]:
372 6b5605e8 Iustin Pop
      raise errors.HypervisorError("Need a kernel for the instance")
373 6b5605e8 Iustin Pop
374 6b5605e8 Iustin Pop
    if not os.path.isabs(hvparams[constants.HV_KERNEL_PATH]):
375 6b5605e8 Iustin Pop
      raise errors.HypervisorError("The kernel path must an absolute path")
376 6b5605e8 Iustin Pop
377 6b5605e8 Iustin Pop
    if hvparams[constants.HV_INITRD_PATH]:
378 6b5605e8 Iustin Pop
      if not os.path.isabs(hvparams[constants.HV_INITRD_PATH]):
379 6b5605e8 Iustin Pop
        raise errors.HypervisorError("The initrd path must an absolute path"
380 6b5605e8 Iustin Pop
                                     ", if defined")
381 6b5605e8 Iustin Pop
382 6b5605e8 Iustin Pop
  def ValidateParameters(self, hvparams):
383 6b5605e8 Iustin Pop
    """Check the given parameters for validity.
384 6b5605e8 Iustin Pop

385 6b5605e8 Iustin Pop
    For the KVM hypervisor, this checks the existence of the
386 6b5605e8 Iustin Pop
    kernel.
387 6b5605e8 Iustin Pop

388 6b5605e8 Iustin Pop
    """
389 47387b1e Guido Trotter
    super(KVMHypervisor, self).ValidateParameters(hvparams)
390 6b5605e8 Iustin Pop
391 6b5605e8 Iustin Pop
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
392 6b5605e8 Iustin Pop
    if not os.path.isfile(kernel_path):
393 6b5605e8 Iustin Pop
      raise errors.HypervisorError("Instance kernel '%s' not found or"
394 6b5605e8 Iustin Pop
                                   " not a file" % kernel_path)
395 6b5605e8 Iustin Pop
    initrd_path = hvparams[constants.HV_INITRD_PATH]
396 6b5605e8 Iustin Pop
    if initrd_path and not os.path.isfile(initrd_path):
397 6b5605e8 Iustin Pop
      raise errors.HypervisorError("Instance initrd '%s' not found or"
398 6b5605e8 Iustin Pop
                                   " not a file" % initrd_path)