Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ b9bddb6b

History | View | Annotate | Download (11.9 kB)

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

24 eb58f9b1 Guido Trotter
"""
25 eb58f9b1 Guido Trotter
26 eb58f9b1 Guido Trotter
import os
27 eb58f9b1 Guido Trotter
import os.path
28 eb58f9b1 Guido Trotter
import re
29 eb58f9b1 Guido Trotter
import tempfile
30 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 eb58f9b1 Guido Trotter
  def __init__(self):
51 eb58f9b1 Guido Trotter
    hv_base.BaseHypervisor.__init__(self)
52 eb58f9b1 Guido Trotter
    # Let's make sure the directories we need exist, even if the RUN_DIR lives
53 eb58f9b1 Guido Trotter
    # in a tmpfs filesystem or has been otherwise wiped out.
54 eb58f9b1 Guido Trotter
    for dir in self._DIRS:
55 eb58f9b1 Guido Trotter
      if not os.path.exists(dir):
56 eb58f9b1 Guido Trotter
        os.mkdir(dir)
57 eb58f9b1 Guido Trotter
58 eb58f9b1 Guido Trotter
  def _WriteNetScript(self, instance, seq, nic):
59 eb58f9b1 Guido Trotter
    """Write a script to connect a net interface to the proper bridge.
60 eb58f9b1 Guido Trotter

61 eb58f9b1 Guido Trotter
    This can be used by any qemu-type hypervisor.
62 eb58f9b1 Guido Trotter

63 eb58f9b1 Guido Trotter
    @param instance: instance we're acting on
64 eb58f9b1 Guido Trotter
    @type instance: instance object
65 eb58f9b1 Guido Trotter
    @param seq: nic sequence number
66 eb58f9b1 Guido Trotter
    @type seq: int
67 eb58f9b1 Guido Trotter
    @param nic: nic we're acting on
68 eb58f9b1 Guido Trotter
    @type nic: nic object
69 eb58f9b1 Guido Trotter
    @return: netscript file name
70 eb58f9b1 Guido Trotter
    @rtype: string
71 eb58f9b1 Guido Trotter

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

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

105 eb58f9b1 Guido Trotter
    """
106 eb58f9b1 Guido Trotter
    result = []
107 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
108 eb58f9b1 Guido Trotter
      file = "%s/%s" % (self._PIDS_DIR, name)
109 eb58f9b1 Guido Trotter
      if utils.IsProcessAlive(utils.ReadPidFile(file)):
110 eb58f9b1 Guido Trotter
        result.append(name)
111 eb58f9b1 Guido Trotter
    return result
112 eb58f9b1 Guido Trotter
113 eb58f9b1 Guido Trotter
  def GetInstanceInfo(self, instance_name):
114 eb58f9b1 Guido Trotter
    """Get instance properties.
115 eb58f9b1 Guido Trotter

116 eb58f9b1 Guido Trotter
    Args:
117 eb58f9b1 Guido Trotter
      instance_name: the instance name
118 eb58f9b1 Guido Trotter

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

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

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

277 eb58f9b1 Guido Trotter
    """
278 eb58f9b1 Guido Trotter
    pid_file = self._PIDS_DIR + "/%s" % instance.name
279 eb58f9b1 Guido Trotter
    pid = utils.ReadPidFile(pid_file)
280 eb58f9b1 Guido Trotter
    if pid > 0 and utils.IsProcessAlive(pid):
281 eb58f9b1 Guido Trotter
      if force or not instance.hvm_acpi:
282 eb58f9b1 Guido Trotter
        utils.KillProcess(pid)
283 eb58f9b1 Guido Trotter
      else:
284 eb58f9b1 Guido Trotter
        # This only works if the instance os has acpi support
285 eb58f9b1 Guido Trotter
        monitor_socket = '%s/%s.monitor'  % (self._CTRL_DIR, instance.name)
286 eb58f9b1 Guido Trotter
        socat = 'socat -u STDIN UNIX-CONNECT:%s' % monitor_socket
287 eb58f9b1 Guido Trotter
        command = "echo 'system_powerdown' | %s" % socat
288 eb58f9b1 Guido Trotter
        result = utils.RunCmd(command)
289 eb58f9b1 Guido Trotter
        if result.failed:
290 eb58f9b1 Guido Trotter
          raise errors.HypervisorError("Failed to stop instance %s: %s" %
291 eb58f9b1 Guido Trotter
                                       (instance.name, result.fail_reason))
292 eb58f9b1 Guido Trotter
293 eb58f9b1 Guido Trotter
    if not utils.IsProcessAlive(pid):
294 eb58f9b1 Guido Trotter
      utils.RemoveFile(pid_file)
295 eb58f9b1 Guido Trotter
296 eb58f9b1 Guido Trotter
  def RebootInstance(self, instance):
297 eb58f9b1 Guido Trotter
    """Reboot an instance.
298 eb58f9b1 Guido Trotter

299 eb58f9b1 Guido Trotter
    """
300 eb58f9b1 Guido Trotter
    # For some reason if we do a 'send-key ctrl-alt-delete' to the control
301 eb58f9b1 Guido Trotter
    # socket the instance will stop, but now power up again. So we'll resort
302 eb58f9b1 Guido Trotter
    # to shutdown and restart.
303 eb58f9b1 Guido Trotter
    self.StopInstance(instance)
304 eb58f9b1 Guido Trotter
    self.StartInstance(instance)
305 eb58f9b1 Guido Trotter
306 eb58f9b1 Guido Trotter
  def GetNodeInfo(self):
307 eb58f9b1 Guido Trotter
    """Return information about the node.
308 eb58f9b1 Guido Trotter

309 eb58f9b1 Guido Trotter
    The return value is a dict, which has to have the following items:
310 eb58f9b1 Guido Trotter
      (all values in MiB)
311 eb58f9b1 Guido Trotter
      - memory_total: the total memory size on the node
312 eb58f9b1 Guido Trotter
      - memory_free: the available memory on the node for instances
313 eb58f9b1 Guido Trotter
      - memory_dom0: the memory used by the node itself, if available
314 eb58f9b1 Guido Trotter

315 eb58f9b1 Guido Trotter
    """
316 eb58f9b1 Guido Trotter
    # global ram usage from the xm info command
317 eb58f9b1 Guido Trotter
    # memory                 : 3583
318 eb58f9b1 Guido Trotter
    # free_memory            : 747
319 eb58f9b1 Guido Trotter
    # note: in xen 3, memory has changed to total_memory
320 eb58f9b1 Guido Trotter
    try:
321 eb58f9b1 Guido Trotter
      fh = file("/proc/meminfo")
322 eb58f9b1 Guido Trotter
      try:
323 eb58f9b1 Guido Trotter
        data = fh.readlines()
324 eb58f9b1 Guido Trotter
      finally:
325 eb58f9b1 Guido Trotter
        fh.close()
326 eb58f9b1 Guido Trotter
    except IOError, err:
327 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to list node info: %s" % err)
328 eb58f9b1 Guido Trotter
329 eb58f9b1 Guido Trotter
    result = {}
330 eb58f9b1 Guido Trotter
    sum_free = 0
331 eb58f9b1 Guido Trotter
    for line in data:
332 eb58f9b1 Guido Trotter
      splitfields = line.split(":", 1)
333 eb58f9b1 Guido Trotter
334 eb58f9b1 Guido Trotter
      if len(splitfields) > 1:
335 eb58f9b1 Guido Trotter
        key = splitfields[0].strip()
336 eb58f9b1 Guido Trotter
        val = splitfields[1].strip()
337 eb58f9b1 Guido Trotter
        if key == 'MemTotal':
338 eb58f9b1 Guido Trotter
          result['memory_total'] = int(val.split()[0])/1024
339 eb58f9b1 Guido Trotter
        elif key in ('MemFree', 'Buffers', 'Cached'):
340 eb58f9b1 Guido Trotter
          sum_free += int(val.split()[0])/1024
341 eb58f9b1 Guido Trotter
        elif key == 'Active':
342 eb58f9b1 Guido Trotter
          result['memory_dom0'] = int(val.split()[0])/1024
343 eb58f9b1 Guido Trotter
    result['memory_free'] = sum_free
344 eb58f9b1 Guido Trotter
345 eb58f9b1 Guido Trotter
    cpu_total = 0
346 eb58f9b1 Guido Trotter
    try:
347 eb58f9b1 Guido Trotter
      fh = open("/proc/cpuinfo")
348 eb58f9b1 Guido Trotter
      try:
349 eb58f9b1 Guido Trotter
        cpu_total = len(re.findall("(?m)^processor\s*:\s*[0-9]+\s*$",
350 eb58f9b1 Guido Trotter
                                   fh.read()))
351 eb58f9b1 Guido Trotter
      finally:
352 eb58f9b1 Guido Trotter
        fh.close()
353 eb58f9b1 Guido Trotter
    except EnvironmentError, err:
354 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to list node info: %s" % err)
355 eb58f9b1 Guido Trotter
    result['cpu_total'] = cpu_total
356 eb58f9b1 Guido Trotter
357 eb58f9b1 Guido Trotter
    return result
358 eb58f9b1 Guido Trotter
359 eb58f9b1 Guido Trotter
  @staticmethod
360 eb58f9b1 Guido Trotter
  def GetShellCommandForConsole(instance):
361 eb58f9b1 Guido Trotter
    """Return a command for connecting to the console of an instance.
362 eb58f9b1 Guido Trotter

363 eb58f9b1 Guido Trotter
    """
364 eb58f9b1 Guido Trotter
    # TODO: we can either try the serial socket or suggest vnc
365 eb58f9b1 Guido Trotter
    return "echo Console not available for the kvm hypervisor yet"
366 eb58f9b1 Guido Trotter
367 eb58f9b1 Guido Trotter
  def Verify(self):
368 eb58f9b1 Guido Trotter
    """Verify the hypervisor.
369 eb58f9b1 Guido Trotter

370 eb58f9b1 Guido Trotter
    Check that the binary exists.
371 eb58f9b1 Guido Trotter

372 eb58f9b1 Guido Trotter
    """
373 eb58f9b1 Guido Trotter
    if not os.path.exists(constants.KVM_PATH):
374 eb58f9b1 Guido Trotter
      return "The kvm binary ('%s') does not exist." % constants.KVM_PATH