Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor.py @ f00b46bc

History | View | Annotate | Download (14.2 kB)

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

24 a8083063 Iustin Pop
"""
25 a8083063 Iustin Pop
26 a8083063 Iustin Pop
import time
27 a8083063 Iustin Pop
import os
28 a8083063 Iustin Pop
from cStringIO import StringIO
29 a8083063 Iustin Pop
30 a8083063 Iustin Pop
from ganeti import utils
31 a8083063 Iustin Pop
from ganeti import logger
32 a8083063 Iustin Pop
from ganeti import ssconf
33 f00b46bc Michael Hanselmann
from ganeti import constants
34 a8083063 Iustin Pop
from ganeti.errors import HypervisorError
35 a8083063 Iustin Pop
36 a8083063 Iustin Pop
_HT_XEN30 = "xen-3.0"
37 a8083063 Iustin Pop
_HT_FAKE = "fake"
38 a8083063 Iustin Pop
39 a8083063 Iustin Pop
VALID_HTYPES = (_HT_XEN30, _HT_FAKE)
40 a8083063 Iustin Pop
41 a8083063 Iustin Pop
def GetHypervisor():
42 a8083063 Iustin Pop
  """Return a Hypervisor instance.
43 a8083063 Iustin Pop

44 a8083063 Iustin Pop
  This function parses the cluster hypervisor configuration file and
45 a8083063 Iustin Pop
  instantiates a class based on the value of this file.
46 a8083063 Iustin Pop

47 a8083063 Iustin Pop
  """
48 a8083063 Iustin Pop
  ht_kind = ssconf.SimpleStore().GetHypervisorType()
49 a8083063 Iustin Pop
  if ht_kind == _HT_XEN30:
50 a8083063 Iustin Pop
    cls = XenHypervisor
51 a8083063 Iustin Pop
  elif ht_kind == _HT_FAKE:
52 a8083063 Iustin Pop
    cls = FakeHypervisor
53 a8083063 Iustin Pop
  else:
54 3ecf6786 Iustin Pop
    raise HypervisorError("Unknown hypervisor type '%s'" % ht_kind)
55 a8083063 Iustin Pop
  return cls()
56 a8083063 Iustin Pop
57 a8083063 Iustin Pop
58 a8083063 Iustin Pop
class BaseHypervisor(object):
59 a8083063 Iustin Pop
  """Abstract virtualisation technology interface
60 a8083063 Iustin Pop

61 a8083063 Iustin Pop
  The goal is that all aspects of the virtualisation technology must
62 a8083063 Iustin Pop
  be abstracted away from the rest of code.
63 a8083063 Iustin Pop

64 a8083063 Iustin Pop
  """
65 a8083063 Iustin Pop
  def __init__(self):
66 a8083063 Iustin Pop
    pass
67 a8083063 Iustin Pop
68 a8083063 Iustin Pop
  def StartInstance(self, instance, block_devices, extra_args):
69 a8083063 Iustin Pop
    """Start an instance."""
70 a8083063 Iustin Pop
    raise NotImplementedError
71 a8083063 Iustin Pop
72 a8083063 Iustin Pop
  def StopInstance(self, instance, force=False):
73 a8083063 Iustin Pop
    """Stop an instance."""
74 a8083063 Iustin Pop
    raise NotImplementedError
75 a8083063 Iustin Pop
76 a8083063 Iustin Pop
  def ListInstances(self):
77 a8083063 Iustin Pop
    """Get the list of running instances."""
78 a8083063 Iustin Pop
    raise NotImplementedError
79 a8083063 Iustin Pop
80 a8083063 Iustin Pop
  def GetInstanceInfo(self, instance_name):
81 a8083063 Iustin Pop
    """Get instance properties.
82 a8083063 Iustin Pop

83 a8083063 Iustin Pop
    Args:
84 a8083063 Iustin Pop
      instance_name: the instance name
85 a8083063 Iustin Pop

86 a8083063 Iustin Pop
    Returns:
87 a8083063 Iustin Pop
      (name, id, memory, vcpus, state, times)
88 a8083063 Iustin Pop

89 a8083063 Iustin Pop
    """
90 a8083063 Iustin Pop
    raise NotImplementedError
91 a8083063 Iustin Pop
92 a8083063 Iustin Pop
  def GetAllInstancesInfo(self):
93 a8083063 Iustin Pop
    """Get properties of all instances.
94 a8083063 Iustin Pop

95 a8083063 Iustin Pop
    Returns:
96 a8083063 Iustin Pop
      [(name, id, memory, vcpus, stat, times),...]
97 a8083063 Iustin Pop
    """
98 a8083063 Iustin Pop
    raise NotImplementedError
99 a8083063 Iustin Pop
100 a8083063 Iustin Pop
  def GetNodeInfo(self):
101 a8083063 Iustin Pop
    """Return information about the node.
102 a8083063 Iustin Pop

103 a8083063 Iustin Pop
    The return value is a dict, which has to have the following items:
104 a8083063 Iustin Pop
      (all values in MiB)
105 a8083063 Iustin Pop
      - memory_total: the total memory size on the node
106 a8083063 Iustin Pop
      - memory_free: the available memory on the node for instances
107 a8083063 Iustin Pop
      - memory_dom0: the memory used by the node itself, if available
108 a8083063 Iustin Pop

109 a8083063 Iustin Pop
    """
110 a8083063 Iustin Pop
    raise NotImplementedError
111 a8083063 Iustin Pop
112 a8083063 Iustin Pop
  @staticmethod
113 a8083063 Iustin Pop
  def GetShellCommandForConsole(instance_name):
114 a8083063 Iustin Pop
    """Return a command for connecting to the console of an instance.
115 a8083063 Iustin Pop

116 a8083063 Iustin Pop
    """
117 a8083063 Iustin Pop
    raise NotImplementedError
118 a8083063 Iustin Pop
119 a8083063 Iustin Pop
  def Verify(self):
120 a8083063 Iustin Pop
    """Verify the hypervisor.
121 a8083063 Iustin Pop

122 a8083063 Iustin Pop
    """
123 a8083063 Iustin Pop
    raise NotImplementedError
124 a8083063 Iustin Pop
125 a8083063 Iustin Pop
126 a8083063 Iustin Pop
class XenHypervisor(BaseHypervisor):
127 a8083063 Iustin Pop
  """Xen hypervisor interface"""
128 a8083063 Iustin Pop
129 a8083063 Iustin Pop
  @staticmethod
130 a8083063 Iustin Pop
  def _WriteConfigFile(instance, block_devices, extra_args):
131 a8083063 Iustin Pop
    """Create a Xen 3.0 config file.
132 a8083063 Iustin Pop

133 a8083063 Iustin Pop
    """
134 a8083063 Iustin Pop
    config = StringIO()
135 a8083063 Iustin Pop
    config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
136 f00b46bc Michael Hanselmann
    config.write("kernel = '%s'\n" % constants.XEN_KERNEL)
137 f00b46bc Michael Hanselmann
    if os.path.exists(constants.XEN_INITRD):
138 f00b46bc Michael Hanselmann
      config.write("ramdisk = '%s'\n" % constants.XEN_INITRD)
139 a8083063 Iustin Pop
    config.write("memory = %d\n" % instance.memory)
140 a8083063 Iustin Pop
    config.write("vcpus = %d\n" % instance.vcpus)
141 a8083063 Iustin Pop
    config.write("name = '%s'\n" % instance.name)
142 a8083063 Iustin Pop
143 a8083063 Iustin Pop
    vif_data = []
144 a8083063 Iustin Pop
    for nic in instance.nics:
145 a8083063 Iustin Pop
      nic_str = "mac=%s, bridge=%s" % (nic.mac, nic.bridge)
146 a8083063 Iustin Pop
      ip = getattr(nic, "ip", None)
147 a8083063 Iustin Pop
      if ip is not None:
148 a8083063 Iustin Pop
        nic_str += ", ip=%s" % ip
149 a8083063 Iustin Pop
      vif_data.append("'%s'" % nic_str)
150 a8083063 Iustin Pop
151 a8083063 Iustin Pop
    config.write("vif = [%s]\n" % ",".join(vif_data))
152 a8083063 Iustin Pop
153 a8083063 Iustin Pop
    disk_data = ["'phy:%s,%s,w'" % (rldev.dev_path, cfdev.iv_name)
154 a8083063 Iustin Pop
                 for cfdev, rldev in block_devices]
155 a8083063 Iustin Pop
    config.write("disk = [%s]\n" % ",".join(disk_data))
156 a8083063 Iustin Pop
157 a8083063 Iustin Pop
    config.write("root = '/dev/sda ro'\n")
158 a8083063 Iustin Pop
    config.write("on_poweroff = 'destroy'\n")
159 a8083063 Iustin Pop
    config.write("on_reboot = 'restart'\n")
160 a8083063 Iustin Pop
    config.write("on_crash = 'restart'\n")
161 a8083063 Iustin Pop
    if extra_args:
162 a8083063 Iustin Pop
      config.write("extra = '%s'\n" % extra_args)
163 a8083063 Iustin Pop
    # just in case it exists
164 a8083063 Iustin Pop
    utils.RemoveFile("/etc/xen/auto/%s" % instance.name)
165 a8083063 Iustin Pop
    f = open("/etc/xen/%s" % instance.name, "w")
166 a8083063 Iustin Pop
    f.write(config.getvalue())
167 a8083063 Iustin Pop
    f.close()
168 a8083063 Iustin Pop
    return True
169 a8083063 Iustin Pop
170 a8083063 Iustin Pop
  @staticmethod
171 a8083063 Iustin Pop
  def _RemoveConfigFile(instance):
172 a8083063 Iustin Pop
    """Remove the xen configuration file.
173 a8083063 Iustin Pop

174 a8083063 Iustin Pop
    """
175 a8083063 Iustin Pop
    utils.RemoveFile("/etc/xen/%s" % instance.name)
176 a8083063 Iustin Pop
177 a8083063 Iustin Pop
  @staticmethod
178 a8083063 Iustin Pop
  def _GetXMList(include_node):
179 a8083063 Iustin Pop
    """Return the list of running instances.
180 a8083063 Iustin Pop

181 a8083063 Iustin Pop
    If the `include_node` argument is True, then we return information
182 a8083063 Iustin Pop
    for dom0 also, otherwise we filter that from the return value.
183 a8083063 Iustin Pop

184 a8083063 Iustin Pop
    The return value is a list of (name, id, memory, vcpus, state, time spent)
185 a8083063 Iustin Pop

186 a8083063 Iustin Pop
    """
187 a8083063 Iustin Pop
    for dummy in range(5):
188 a8083063 Iustin Pop
      result = utils.RunCmd(["xm", "list"])
189 a8083063 Iustin Pop
      if not result.failed:
190 a8083063 Iustin Pop
        break
191 a8083063 Iustin Pop
      logger.Error("xm list failed (%s): %s" % (result.fail_reason,
192 a8083063 Iustin Pop
                                                result.output))
193 a8083063 Iustin Pop
      time.sleep(1)
194 a8083063 Iustin Pop
195 a8083063 Iustin Pop
    if result.failed:
196 a8083063 Iustin Pop
      raise HypervisorError("xm list failed, retries exceeded (%s): %s" %
197 a8083063 Iustin Pop
                            (result.fail_reason, result.stderr))
198 a8083063 Iustin Pop
199 a8083063 Iustin Pop
    # skip over the heading and the domain 0 line (optional)
200 a8083063 Iustin Pop
    if include_node:
201 a8083063 Iustin Pop
      to_skip = 1
202 a8083063 Iustin Pop
    else:
203 a8083063 Iustin Pop
      to_skip = 2
204 a8083063 Iustin Pop
    lines = result.stdout.splitlines()[to_skip:]
205 a8083063 Iustin Pop
    result = []
206 a8083063 Iustin Pop
    for line in lines:
207 a8083063 Iustin Pop
      # The format of lines is:
208 a8083063 Iustin Pop
      # Name      ID Mem(MiB) VCPUs State  Time(s)
209 a8083063 Iustin Pop
      # Domain-0   0  3418     4 r-----    266.2
210 a8083063 Iustin Pop
      data = line.split()
211 a8083063 Iustin Pop
      if len(data) != 6:
212 a8083063 Iustin Pop
        raise HypervisorError("Can't parse output of xm list, line: %s" % line)
213 a8083063 Iustin Pop
      try:
214 a8083063 Iustin Pop
        data[1] = int(data[1])
215 a8083063 Iustin Pop
        data[2] = int(data[2])
216 a8083063 Iustin Pop
        data[3] = int(data[3])
217 a8083063 Iustin Pop
        data[5] = float(data[5])
218 a8083063 Iustin Pop
      except ValueError, err:
219 a8083063 Iustin Pop
        raise HypervisorError("Can't parse output of xm list,"
220 a8083063 Iustin Pop
                              " line: %s, error: %s" % (line, err))
221 a8083063 Iustin Pop
      result.append(data)
222 a8083063 Iustin Pop
    return result
223 a8083063 Iustin Pop
224 a8083063 Iustin Pop
  def ListInstances(self):
225 a8083063 Iustin Pop
    """Get the list of running instances.
226 a8083063 Iustin Pop

227 a8083063 Iustin Pop
    """
228 a8083063 Iustin Pop
    xm_list = self._GetXMList(False)
229 a8083063 Iustin Pop
    names = [info[0] for info in xm_list]
230 a8083063 Iustin Pop
    return names
231 a8083063 Iustin Pop
232 a8083063 Iustin Pop
  def GetInstanceInfo(self, instance_name):
233 a8083063 Iustin Pop
    """Get instance properties.
234 a8083063 Iustin Pop

235 a8083063 Iustin Pop
    Args:
236 a8083063 Iustin Pop
      instance_name: the instance name
237 a8083063 Iustin Pop

238 a8083063 Iustin Pop
    Returns:
239 a8083063 Iustin Pop
      (name, id, memory, vcpus, stat, times)
240 a8083063 Iustin Pop
    """
241 a8083063 Iustin Pop
    xm_list = self._GetXMList(instance_name=="Domain-0")
242 a8083063 Iustin Pop
    result = None
243 a8083063 Iustin Pop
    for data in xm_list:
244 a8083063 Iustin Pop
      if data[0] == instance_name:
245 a8083063 Iustin Pop
        result = data
246 a8083063 Iustin Pop
        break
247 a8083063 Iustin Pop
    return result
248 a8083063 Iustin Pop
249 a8083063 Iustin Pop
  def GetAllInstancesInfo(self):
250 a8083063 Iustin Pop
    """Get properties of all instances.
251 a8083063 Iustin Pop

252 a8083063 Iustin Pop
    Returns:
253 a8083063 Iustin Pop
      [(name, id, memory, vcpus, stat, times),...]
254 a8083063 Iustin Pop
    """
255 a8083063 Iustin Pop
    xm_list = self._GetXMList(False)
256 a8083063 Iustin Pop
    return xm_list
257 a8083063 Iustin Pop
258 a8083063 Iustin Pop
  def StartInstance(self, instance, block_devices, extra_args):
259 a8083063 Iustin Pop
    """Start an instance."""
260 a8083063 Iustin Pop
    self._WriteConfigFile(instance, block_devices, extra_args)
261 a8083063 Iustin Pop
    result = utils.RunCmd(["xm", "create", instance.name])
262 a8083063 Iustin Pop
263 a8083063 Iustin Pop
    if result.failed:
264 a8083063 Iustin Pop
      raise HypervisorError("Failed to start instance %s: %s" %
265 a8083063 Iustin Pop
                            (instance.name, result.fail_reason))
266 a8083063 Iustin Pop
267 a8083063 Iustin Pop
  def StopInstance(self, instance, force=False):
268 a8083063 Iustin Pop
    """Stop an instance."""
269 a8083063 Iustin Pop
    self._RemoveConfigFile(instance)
270 a8083063 Iustin Pop
    if force:
271 a8083063 Iustin Pop
      command = ["xm", "destroy", instance.name]
272 a8083063 Iustin Pop
    else:
273 a8083063 Iustin Pop
      command = ["xm", "shutdown", instance.name]
274 a8083063 Iustin Pop
    result = utils.RunCmd(command)
275 a8083063 Iustin Pop
276 a8083063 Iustin Pop
    if result.failed:
277 a8083063 Iustin Pop
      raise HypervisorError("Failed to stop instance %s: %s" %
278 a8083063 Iustin Pop
                            (instance.name, result.fail_reason))
279 a8083063 Iustin Pop
280 a8083063 Iustin Pop
  def GetNodeInfo(self):
281 a8083063 Iustin Pop
    """Return information about the node.
282 a8083063 Iustin Pop

283 a8083063 Iustin Pop
    The return value is a dict, which has to have the following items:
284 a8083063 Iustin Pop
      (all values in MiB)
285 a8083063 Iustin Pop
      - memory_total: the total memory size on the node
286 a8083063 Iustin Pop
      - memory_free: the available memory on the node for instances
287 a8083063 Iustin Pop
      - memory_dom0: the memory used by the node itself, if available
288 a8083063 Iustin Pop

289 a8083063 Iustin Pop
    """
290 a8083063 Iustin Pop
    # note: in xen 3, memory has changed to total_memory
291 a8083063 Iustin Pop
    result = utils.RunCmd(["xm", "info"])
292 a8083063 Iustin Pop
    if result.failed:
293 a8083063 Iustin Pop
      logger.Error("Can't run 'xm info': %s" % result.fail_reason)
294 a8083063 Iustin Pop
      return None
295 a8083063 Iustin Pop
296 a8083063 Iustin Pop
    xmoutput = result.stdout.splitlines()
297 a8083063 Iustin Pop
    result = {}
298 a8083063 Iustin Pop
    for line in xmoutput:
299 a8083063 Iustin Pop
      splitfields = line.split(":", 1)
300 a8083063 Iustin Pop
301 a8083063 Iustin Pop
      if len(splitfields) > 1:
302 a8083063 Iustin Pop
        key = splitfields[0].strip()
303 a8083063 Iustin Pop
        val = splitfields[1].strip()
304 a8083063 Iustin Pop
        if key == 'memory' or key == 'total_memory':
305 a8083063 Iustin Pop
          result['memory_total'] = int(val)
306 a8083063 Iustin Pop
        elif key == 'free_memory':
307 a8083063 Iustin Pop
          result['memory_free'] = int(val)
308 a8083063 Iustin Pop
    dom0_info = self.GetInstanceInfo("Domain-0")
309 a8083063 Iustin Pop
    if dom0_info is not None:
310 a8083063 Iustin Pop
      result['memory_dom0'] = dom0_info[2]
311 a8083063 Iustin Pop
312 a8083063 Iustin Pop
    return result
313 a8083063 Iustin Pop
314 a8083063 Iustin Pop
  @staticmethod
315 a8083063 Iustin Pop
  def GetShellCommandForConsole(instance_name):
316 a8083063 Iustin Pop
    """Return a command for connecting to the console of an instance.
317 a8083063 Iustin Pop

318 a8083063 Iustin Pop
    """
319 a8083063 Iustin Pop
    return "xm console %s" % instance_name
320 a8083063 Iustin Pop
321 a8083063 Iustin Pop
322 a8083063 Iustin Pop
  def Verify(self):
323 a8083063 Iustin Pop
    """Verify the hypervisor.
324 a8083063 Iustin Pop

325 a8083063 Iustin Pop
    For Xen, this verifies that the xend process is running.
326 a8083063 Iustin Pop

327 a8083063 Iustin Pop
    """
328 a8083063 Iustin Pop
    if not utils.CheckDaemonAlive('/var/run/xend.pid', 'xend'):
329 a8083063 Iustin Pop
      return "xend daemon is not running"
330 a8083063 Iustin Pop
331 a8083063 Iustin Pop
332 a8083063 Iustin Pop
class FakeHypervisor(BaseHypervisor):
333 a8083063 Iustin Pop
  """Fake hypervisor interface.
334 a8083063 Iustin Pop

335 a8083063 Iustin Pop
  This can be used for testing the ganeti code without having to have
336 a8083063 Iustin Pop
  a real virtualisation software installed.
337 a8083063 Iustin Pop

338 a8083063 Iustin Pop
  """
339 a8083063 Iustin Pop
  _ROOT_DIR = "/var/run/ganeti-fake-hypervisor"
340 a8083063 Iustin Pop
341 a8083063 Iustin Pop
  def __init__(self):
342 a8083063 Iustin Pop
    BaseHypervisor.__init__(self)
343 a8083063 Iustin Pop
    if not os.path.exists(self._ROOT_DIR):
344 a8083063 Iustin Pop
      os.mkdir(self._ROOT_DIR)
345 a8083063 Iustin Pop
346 a8083063 Iustin Pop
  def ListInstances(self):
347 a8083063 Iustin Pop
    """Get the list of running instances.
348 a8083063 Iustin Pop

349 a8083063 Iustin Pop
    """
350 a8083063 Iustin Pop
    return os.listdir(self._ROOT_DIR)
351 a8083063 Iustin Pop
352 a8083063 Iustin Pop
  def GetInstanceInfo(self, instance_name):
353 a8083063 Iustin Pop
    """Get instance properties.
354 a8083063 Iustin Pop

355 a8083063 Iustin Pop
    Args:
356 a8083063 Iustin Pop
      instance_name: the instance name
357 a8083063 Iustin Pop

358 a8083063 Iustin Pop
    Returns:
359 a8083063 Iustin Pop
      (name, id, memory, vcpus, stat, times)
360 a8083063 Iustin Pop
    """
361 a8083063 Iustin Pop
    file_name = "%s/%s" % (self._ROOT_DIR, instance_name)
362 a8083063 Iustin Pop
    if not os.path.exists(file_name):
363 a8083063 Iustin Pop
      return None
364 a8083063 Iustin Pop
    try:
365 a8083063 Iustin Pop
      fh = file(file_name, "r")
366 a8083063 Iustin Pop
      try:
367 a8083063 Iustin Pop
        inst_id = fh.readline().strip()
368 a8083063 Iustin Pop
        memory = fh.readline().strip()
369 a8083063 Iustin Pop
        vcpus = fh.readline().strip()
370 a8083063 Iustin Pop
        stat = "---b-"
371 a8083063 Iustin Pop
        times = "0"
372 a8083063 Iustin Pop
        return (instance_name, inst_id, memory, vcpus, stat, times)
373 a8083063 Iustin Pop
      finally:
374 a8083063 Iustin Pop
        fh.close()
375 a8083063 Iustin Pop
    except IOError, err:
376 a8083063 Iustin Pop
      raise HypervisorError("Failed to list instance %s: %s" %
377 a8083063 Iustin Pop
                            (instance_name, err))
378 a8083063 Iustin Pop
379 a8083063 Iustin Pop
  def GetAllInstancesInfo(self):
380 a8083063 Iustin Pop
    """Get properties of all instances.
381 a8083063 Iustin Pop

382 a8083063 Iustin Pop
    Returns:
383 a8083063 Iustin Pop
      [(name, id, memory, vcpus, stat, times),...]
384 a8083063 Iustin Pop
    """
385 a8083063 Iustin Pop
    data = []
386 a8083063 Iustin Pop
    for file_name in os.listdir(self._ROOT_DIR):
387 a8083063 Iustin Pop
      try:
388 a8083063 Iustin Pop
        fh = file(self._ROOT_DIR+"/"+file_name, "r")
389 a8083063 Iustin Pop
        inst_id = "-1"
390 a8083063 Iustin Pop
        memory = "0"
391 a8083063 Iustin Pop
        stat = "-----"
392 a8083063 Iustin Pop
        times = "-1"
393 a8083063 Iustin Pop
        try:
394 a8083063 Iustin Pop
          inst_id = fh.readline().strip()
395 a8083063 Iustin Pop
          memory = fh.readline().strip()
396 a8083063 Iustin Pop
          vcpus = fh.readline().strip()
397 a8083063 Iustin Pop
          stat = "---b-"
398 a8083063 Iustin Pop
          times = "0"
399 a8083063 Iustin Pop
        finally:
400 a8083063 Iustin Pop
          fh.close()
401 a8083063 Iustin Pop
        data.append((file_name, inst_id, memory, vcpus, stat, times))
402 a8083063 Iustin Pop
      except IOError, err:
403 a8083063 Iustin Pop
        raise HypervisorError("Failed to list instances: %s" % err)
404 a8083063 Iustin Pop
    return data
405 a8083063 Iustin Pop
406 a8083063 Iustin Pop
  def StartInstance(self, instance, force, extra_args):
407 a8083063 Iustin Pop
    """Start an instance.
408 a8083063 Iustin Pop

409 a8083063 Iustin Pop
    For the fake hypervisor, it just creates a file in the base dir,
410 a8083063 Iustin Pop
    creating an exception if it already exists. We don't actually
411 a8083063 Iustin Pop
    handle race conditions properly, since these are *FAKE* instances.
412 a8083063 Iustin Pop

413 a8083063 Iustin Pop
    """
414 a8083063 Iustin Pop
    file_name = self._ROOT_DIR + "/%s" % instance.name
415 a8083063 Iustin Pop
    if os.path.exists(file_name):
416 a8083063 Iustin Pop
      raise HypervisorError("Failed to start instance %s: %s" %
417 a8083063 Iustin Pop
                            (instance.name, "already running"))
418 a8083063 Iustin Pop
    try:
419 a8083063 Iustin Pop
      fh = file(file_name, "w")
420 a8083063 Iustin Pop
      try:
421 a8083063 Iustin Pop
        fh.write("0\n%d\n%d\n" % (instance.memory, instance.vcpus))
422 a8083063 Iustin Pop
      finally:
423 a8083063 Iustin Pop
        fh.close()
424 a8083063 Iustin Pop
    except IOError, err:
425 a8083063 Iustin Pop
      raise HypervisorError("Failed to start instance %s: %s" %
426 a8083063 Iustin Pop
                            (instance.name, err))
427 a8083063 Iustin Pop
428 a8083063 Iustin Pop
  def StopInstance(self, instance, force=False):
429 a8083063 Iustin Pop
    """Stop an instance.
430 a8083063 Iustin Pop

431 a8083063 Iustin Pop
    For the fake hypervisor, this just removes the file in the base
432 a8083063 Iustin Pop
    dir, if it exist, otherwise we raise an exception.
433 a8083063 Iustin Pop

434 a8083063 Iustin Pop
    """
435 a8083063 Iustin Pop
    file_name = self._ROOT_DIR + "/%s" % instance.name
436 a8083063 Iustin Pop
    if not os.path.exists(file_name):
437 a8083063 Iustin Pop
      raise HypervisorError("Failed to stop instance %s: %s" %
438 a8083063 Iustin Pop
                            (instance.name, "not running"))
439 a8083063 Iustin Pop
    utils.RemoveFile(file_name)
440 a8083063 Iustin Pop
441 a8083063 Iustin Pop
  def GetNodeInfo(self):
442 a8083063 Iustin Pop
    """Return information about the node.
443 a8083063 Iustin Pop

444 a8083063 Iustin Pop
    The return value is a dict, which has to have the following items:
445 a8083063 Iustin Pop
      (all values in MiB)
446 a8083063 Iustin Pop
      - memory_total: the total memory size on the node
447 a8083063 Iustin Pop
      - memory_free: the available memory on the node for instances
448 a8083063 Iustin Pop
      - memory_dom0: the memory used by the node itself, if available
449 a8083063 Iustin Pop

450 a8083063 Iustin Pop
    """
451 a8083063 Iustin Pop
    # global ram usage from the xm info command
452 a8083063 Iustin Pop
    # memory                 : 3583
453 a8083063 Iustin Pop
    # free_memory            : 747
454 a8083063 Iustin Pop
    # note: in xen 3, memory has changed to total_memory
455 a8083063 Iustin Pop
    try:
456 a8083063 Iustin Pop
      fh = file("/proc/meminfo")
457 a8083063 Iustin Pop
      try:
458 a8083063 Iustin Pop
        data = fh.readlines()
459 a8083063 Iustin Pop
      finally:
460 a8083063 Iustin Pop
        fh.close()
461 a8083063 Iustin Pop
    except IOError, err:
462 a8083063 Iustin Pop
      raise HypervisorError("Failed to list node info: %s" % err)
463 a8083063 Iustin Pop
464 a8083063 Iustin Pop
    result = {}
465 a8083063 Iustin Pop
    sum_free = 0
466 a8083063 Iustin Pop
    for line in data:
467 a8083063 Iustin Pop
      splitfields = line.split(":", 1)
468 a8083063 Iustin Pop
469 a8083063 Iustin Pop
      if len(splitfields) > 1:
470 a8083063 Iustin Pop
        key = splitfields[0].strip()
471 a8083063 Iustin Pop
        val = splitfields[1].strip()
472 a8083063 Iustin Pop
        if key == 'MemTotal':
473 a8083063 Iustin Pop
          result['memory_total'] = int(val.split()[0])/1024
474 a8083063 Iustin Pop
        elif key in ('MemFree', 'Buffers', 'Cached'):
475 a8083063 Iustin Pop
          sum_free += int(val.split()[0])/1024
476 a8083063 Iustin Pop
        elif key == 'Active':
477 a8083063 Iustin Pop
          result['memory_dom0'] = int(val.split()[0])/1024
478 a8083063 Iustin Pop
479 a8083063 Iustin Pop
    result['memory_free'] = sum_free
480 a8083063 Iustin Pop
    return result
481 a8083063 Iustin Pop
482 a8083063 Iustin Pop
  @staticmethod
483 a8083063 Iustin Pop
  def GetShellCommandForConsole(instance_name):
484 a8083063 Iustin Pop
    """Return a command for connecting to the console of an instance.
485 a8083063 Iustin Pop

486 a8083063 Iustin Pop
    """
487 a8083063 Iustin Pop
    return "echo Console not available for fake hypervisor"
488 a8083063 Iustin Pop
489 a8083063 Iustin Pop
  def Verify(self):
490 a8083063 Iustin Pop
    """Verify the hypervisor.
491 a8083063 Iustin Pop

492 a8083063 Iustin Pop
    For the fake hypervisor, it just checks the existence of the base
493 a8083063 Iustin Pop
    dir.
494 a8083063 Iustin Pop

495 a8083063 Iustin Pop
    """
496 a8083063 Iustin Pop
    if not os.path.exists(self._ROOT_DIR):
497 a8083063 Iustin Pop
      return "The required directory '%s' does not exist." % self._ROOT_DIR