Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_kvm.py @ 5661b908

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 08137f9e Iustin Pop
    for mydir in self._DIRS:
61 08137f9e Iustin Pop
      if not os.path.exists(mydir):
62 08137f9e Iustin Pop
        os.mkdir(mydir)
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 c41eea6e Iustin Pop
    We can do this by listing our live instances directory and
109 c41eea6e Iustin Pop
    checking whether 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 08137f9e Iustin Pop
      filename = "%s/%s" % (self._PIDS_DIR, name)
115 08137f9e Iustin Pop
      if utils.IsProcessAlive(utils.ReadPidFile(filename)):
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 c41eea6e Iustin Pop
    @param instance_name: the instance name
123 c41eea6e Iustin Pop

124 c41eea6e Iustin Pop
    @return: tuple (name, id, memory, vcpus, stat, times)
125 eb58f9b1 Guido Trotter

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

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

163 eb58f9b1 Guido Trotter
    """
164 eb58f9b1 Guido Trotter
    data = []
165 eb58f9b1 Guido Trotter
    for name in os.listdir(self._PIDS_DIR):
166 08137f9e Iustin Pop
      filename = "%s/%s" % (self._PIDS_DIR, name)
167 08137f9e Iustin Pop
      if utils.IsProcessAlive(utils.ReadPidFile(filename)):
168 eb58f9b1 Guido Trotter
        data.append(self.GetInstanceInfo(name))
169 eb58f9b1 Guido Trotter
170 eb58f9b1 Guido Trotter
    return data
171 eb58f9b1 Guido Trotter
172 eb58f9b1 Guido Trotter
  def StartInstance(self, instance, block_devices, extra_args):
173 eb58f9b1 Guido Trotter
    """Start an instance.
174 eb58f9b1 Guido Trotter

175 eb58f9b1 Guido Trotter
    """
176 eb58f9b1 Guido Trotter
    temp_files = []
177 eb58f9b1 Guido Trotter
    pidfile = self._PIDS_DIR + "/%s" % instance.name
178 eb58f9b1 Guido Trotter
    if utils.IsProcessAlive(utils.ReadPidFile(pidfile)):
179 eb58f9b1 Guido Trotter
      raise errors.HypervisorError("Failed to start instance %s: %s" %
180 eb58f9b1 Guido Trotter
                                   (instance.name, "already running"))
181 eb58f9b1 Guido Trotter
182 eb58f9b1 Guido Trotter
    kvm = constants.KVM_PATH
183 eb58f9b1 Guido Trotter
    kvm_cmd = [kvm]
184 8b3fd458 Iustin Pop
    kvm_cmd.extend(['-m', instance.beparams[constants.BE_MEMORY]])
185 8b3fd458 Iustin Pop
    kvm_cmd.extend(['-smp', instance.beparams[constants.BE_VCPUS]])
186 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-pidfile', pidfile])
187 eb58f9b1 Guido Trotter
    # used just by the vnc server, if enabled
188 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-name', instance.name])
189 eb58f9b1 Guido Trotter
    kvm_cmd.extend(['-daemonize'])
190 6b5605e8 Iustin Pop
    if not instance.hvparams[constants.HV_ACPI]:
191 eb58f9b1 Guido Trotter
      kvm_cmd.extend(['-no-acpi'])
192 eb58f9b1 Guido Trotter
    if not instance.nics:
193 eb58f9b1 Guido Trotter
      kvm_cmd.extend(['-net', 'none'])
194 eb58f9b1 Guido Trotter
    else:
195 eb58f9b1 Guido Trotter
      nic_seq = 0
196 eb58f9b1 Guido Trotter
      for nic in instance.nics:
197 eb58f9b1 Guido Trotter
        script = self._WriteNetScript(instance, nic_seq, nic)
198 eb58f9b1 Guido Trotter
        # FIXME: handle other models
199 eb58f9b1 Guido Trotter
        nic_val = "nic,macaddr=%s,model=virtio" % nic.mac
200 eb58f9b1 Guido Trotter
        kvm_cmd.extend(['-net', nic_val])
201 eb58f9b1 Guido Trotter
        kvm_cmd.extend(['-net', 'tap,script=%s' % script])
202 eb58f9b1 Guido Trotter
        temp_files.append(script)
203 eb58f9b1 Guido Trotter
        nic_seq += 1
204 eb58f9b1 Guido Trotter
205 eb58f9b1 Guido Trotter
    boot_drive = True
206 eb58f9b1 Guido Trotter
    for cfdev, rldev in block_devices:
207 eb58f9b1 Guido Trotter
      # TODO: handle FD_LOOP and FD_BLKTAP (?)
208 eb58f9b1 Guido Trotter
      if boot_drive:
209 eb58f9b1 Guido Trotter
        boot_val = ',boot=on'
210 d47d3d38 Guido Trotter
        boot_drive = False
211 eb58f9b1 Guido Trotter
      else:
212 eb58f9b1 Guido Trotter
        boot_val = ''
213 eb58f9b1 Guido Trotter
214 d47d3d38 Guido Trotter
      # TODO: handle different if= types
215 d47d3d38 Guido Trotter
      if_val = ',if=virtio'
216 d47d3d38 Guido Trotter
217 d47d3d38 Guido Trotter
      drive_val = 'file=%s,format=raw%s%s' % (rldev.dev_path, if_val, boot_val)
218 eb58f9b1 Guido Trotter
      kvm_cmd.extend(['-drive', drive_val])
219 eb58f9b1 Guido Trotter
220 8a74a9b9 Guido Trotter
    kvm_cmd.extend(['-kernel', instance.hvparams[constants.HV_KERNEL_PATH]])
221 8a74a9b9 Guido Trotter
222 8a74a9b9 Guido Trotter
    initrd_path = instance.hvparams[constants.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 08137f9e Iustin Pop
    for filename in temp_files:
253 08137f9e Iustin Pop
      utils.RemoveFile(filename)
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 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
291 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
292 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
293 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
294 eb58f9b1 Guido Trotter

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

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

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

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

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

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

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

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

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