Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor.py @ 24818e8f

History | View | Annotate | Download (14.7 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 7e1394dc Alexander Schreiber
  def RebootInstance(self, instance):
77 7e1394dc Alexander Schreiber
    """Reboot an instance."""
78 7e1394dc Alexander Schreiber
    raise NotImplementedError
79 7e1394dc Alexander Schreiber
80 a8083063 Iustin Pop
  def ListInstances(self):
81 a8083063 Iustin Pop
    """Get the list of running instances."""
82 a8083063 Iustin Pop
    raise NotImplementedError
83 a8083063 Iustin Pop
84 a8083063 Iustin Pop
  def GetInstanceInfo(self, instance_name):
85 a8083063 Iustin Pop
    """Get instance properties.
86 a8083063 Iustin Pop

87 a8083063 Iustin Pop
    Args:
88 a8083063 Iustin Pop
      instance_name: the instance name
89 a8083063 Iustin Pop

90 a8083063 Iustin Pop
    Returns:
91 a8083063 Iustin Pop
      (name, id, memory, vcpus, state, times)
92 a8083063 Iustin Pop

93 a8083063 Iustin Pop
    """
94 a8083063 Iustin Pop
    raise NotImplementedError
95 a8083063 Iustin Pop
96 a8083063 Iustin Pop
  def GetAllInstancesInfo(self):
97 a8083063 Iustin Pop
    """Get properties of all instances.
98 a8083063 Iustin Pop

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

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

113 a8083063 Iustin Pop
    """
114 a8083063 Iustin Pop
    raise NotImplementedError
115 a8083063 Iustin Pop
116 a8083063 Iustin Pop
  @staticmethod
117 a8083063 Iustin Pop
  def GetShellCommandForConsole(instance_name):
118 a8083063 Iustin Pop
    """Return a command for connecting to the console of an instance.
119 a8083063 Iustin Pop

120 a8083063 Iustin Pop
    """
121 a8083063 Iustin Pop
    raise NotImplementedError
122 a8083063 Iustin Pop
123 a8083063 Iustin Pop
  def Verify(self):
124 a8083063 Iustin Pop
    """Verify the hypervisor.
125 a8083063 Iustin Pop

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

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

178 a8083063 Iustin Pop
    """
179 a8083063 Iustin Pop
    utils.RemoveFile("/etc/xen/%s" % instance.name)
180 a8083063 Iustin Pop
181 a8083063 Iustin Pop
  @staticmethod
182 a8083063 Iustin Pop
  def _GetXMList(include_node):
183 a8083063 Iustin Pop
    """Return the list of running instances.
184 a8083063 Iustin Pop

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

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

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

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

239 a8083063 Iustin Pop
    Args:
240 a8083063 Iustin Pop
      instance_name: the instance name
241 a8083063 Iustin Pop

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

256 a8083063 Iustin Pop
    Returns:
257 a8083063 Iustin Pop
      [(name, id, memory, vcpus, stat, times),...]
258 a8083063 Iustin Pop
    """
259 a8083063 Iustin Pop
    xm_list = self._GetXMList(False)
260 a8083063 Iustin Pop
    return xm_list
261 a8083063 Iustin Pop
262 a8083063 Iustin Pop
  def StartInstance(self, instance, block_devices, extra_args):
263 a8083063 Iustin Pop
    """Start an instance."""
264 a8083063 Iustin Pop
    self._WriteConfigFile(instance, block_devices, extra_args)
265 a8083063 Iustin Pop
    result = utils.RunCmd(["xm", "create", instance.name])
266 a8083063 Iustin Pop
267 a8083063 Iustin Pop
    if result.failed:
268 a8083063 Iustin Pop
      raise HypervisorError("Failed to start instance %s: %s" %
269 a8083063 Iustin Pop
                            (instance.name, result.fail_reason))
270 a8083063 Iustin Pop
271 a8083063 Iustin Pop
  def StopInstance(self, instance, force=False):
272 a8083063 Iustin Pop
    """Stop an instance."""
273 a8083063 Iustin Pop
    self._RemoveConfigFile(instance)
274 a8083063 Iustin Pop
    if force:
275 a8083063 Iustin Pop
      command = ["xm", "destroy", instance.name]
276 a8083063 Iustin Pop
    else:
277 a8083063 Iustin Pop
      command = ["xm", "shutdown", instance.name]
278 a8083063 Iustin Pop
    result = utils.RunCmd(command)
279 a8083063 Iustin Pop
280 a8083063 Iustin Pop
    if result.failed:
281 a8083063 Iustin Pop
      raise HypervisorError("Failed to stop instance %s: %s" %
282 a8083063 Iustin Pop
                            (instance.name, result.fail_reason))
283 a8083063 Iustin Pop
284 7e1394dc Alexander Schreiber
  def RebootInstance(self, instance):
285 7e1394dc Alexander Schreiber
    """Reboot an instance."""
286 7e1394dc Alexander Schreiber
    result = utils.RunCmd(["xm", "reboot", instance.name])
287 7e1394dc Alexander Schreiber
288 7e1394dc Alexander Schreiber
    if result.failed:
289 7e1394dc Alexander Schreiber
      raise HypervisorError("Failed to reboot instance %s: %s" %
290 7e1394dc Alexander Schreiber
                            (instance.name, result.fail_reason))
291 7e1394dc Alexander Schreiber
292 a8083063 Iustin Pop
  def GetNodeInfo(self):
293 a8083063 Iustin Pop
    """Return information about the node.
294 a8083063 Iustin Pop

295 a8083063 Iustin Pop
    The return value is a dict, which has to have the following items:
296 a8083063 Iustin Pop
      (all values in MiB)
297 a8083063 Iustin Pop
      - memory_total: the total memory size on the node
298 a8083063 Iustin Pop
      - memory_free: the available memory on the node for instances
299 a8083063 Iustin Pop
      - memory_dom0: the memory used by the node itself, if available
300 a8083063 Iustin Pop

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

330 a8083063 Iustin Pop
    """
331 a8083063 Iustin Pop
    return "xm console %s" % instance_name
332 a8083063 Iustin Pop
333 a8083063 Iustin Pop
334 a8083063 Iustin Pop
  def Verify(self):
335 a8083063 Iustin Pop
    """Verify the hypervisor.
336 a8083063 Iustin Pop

337 a8083063 Iustin Pop
    For Xen, this verifies that the xend process is running.
338 a8083063 Iustin Pop

339 a8083063 Iustin Pop
    """
340 a8083063 Iustin Pop
    if not utils.CheckDaemonAlive('/var/run/xend.pid', 'xend'):
341 a8083063 Iustin Pop
      return "xend daemon is not running"
342 a8083063 Iustin Pop
343 a8083063 Iustin Pop
344 a8083063 Iustin Pop
class FakeHypervisor(BaseHypervisor):
345 a8083063 Iustin Pop
  """Fake hypervisor interface.
346 a8083063 Iustin Pop

347 a8083063 Iustin Pop
  This can be used for testing the ganeti code without having to have
348 a8083063 Iustin Pop
  a real virtualisation software installed.
349 a8083063 Iustin Pop

350 a8083063 Iustin Pop
  """
351 a8083063 Iustin Pop
  _ROOT_DIR = "/var/run/ganeti-fake-hypervisor"
352 a8083063 Iustin Pop
353 a8083063 Iustin Pop
  def __init__(self):
354 a8083063 Iustin Pop
    BaseHypervisor.__init__(self)
355 a8083063 Iustin Pop
    if not os.path.exists(self._ROOT_DIR):
356 a8083063 Iustin Pop
      os.mkdir(self._ROOT_DIR)
357 a8083063 Iustin Pop
358 a8083063 Iustin Pop
  def ListInstances(self):
359 a8083063 Iustin Pop
    """Get the list of running instances.
360 a8083063 Iustin Pop

361 a8083063 Iustin Pop
    """
362 a8083063 Iustin Pop
    return os.listdir(self._ROOT_DIR)
363 a8083063 Iustin Pop
364 a8083063 Iustin Pop
  def GetInstanceInfo(self, instance_name):
365 a8083063 Iustin Pop
    """Get instance properties.
366 a8083063 Iustin Pop

367 a8083063 Iustin Pop
    Args:
368 a8083063 Iustin Pop
      instance_name: the instance name
369 a8083063 Iustin Pop

370 a8083063 Iustin Pop
    Returns:
371 a8083063 Iustin Pop
      (name, id, memory, vcpus, stat, times)
372 a8083063 Iustin Pop
    """
373 a8083063 Iustin Pop
    file_name = "%s/%s" % (self._ROOT_DIR, instance_name)
374 a8083063 Iustin Pop
    if not os.path.exists(file_name):
375 a8083063 Iustin Pop
      return None
376 a8083063 Iustin Pop
    try:
377 a8083063 Iustin Pop
      fh = file(file_name, "r")
378 a8083063 Iustin Pop
      try:
379 a8083063 Iustin Pop
        inst_id = fh.readline().strip()
380 a8083063 Iustin Pop
        memory = fh.readline().strip()
381 a8083063 Iustin Pop
        vcpus = fh.readline().strip()
382 a8083063 Iustin Pop
        stat = "---b-"
383 a8083063 Iustin Pop
        times = "0"
384 a8083063 Iustin Pop
        return (instance_name, inst_id, memory, vcpus, stat, times)
385 a8083063 Iustin Pop
      finally:
386 a8083063 Iustin Pop
        fh.close()
387 a8083063 Iustin Pop
    except IOError, err:
388 a8083063 Iustin Pop
      raise HypervisorError("Failed to list instance %s: %s" %
389 a8083063 Iustin Pop
                            (instance_name, err))
390 a8083063 Iustin Pop
391 a8083063 Iustin Pop
  def GetAllInstancesInfo(self):
392 a8083063 Iustin Pop
    """Get properties of all instances.
393 a8083063 Iustin Pop

394 a8083063 Iustin Pop
    Returns:
395 a8083063 Iustin Pop
      [(name, id, memory, vcpus, stat, times),...]
396 a8083063 Iustin Pop
    """
397 a8083063 Iustin Pop
    data = []
398 a8083063 Iustin Pop
    for file_name in os.listdir(self._ROOT_DIR):
399 a8083063 Iustin Pop
      try:
400 a8083063 Iustin Pop
        fh = file(self._ROOT_DIR+"/"+file_name, "r")
401 a8083063 Iustin Pop
        inst_id = "-1"
402 a8083063 Iustin Pop
        memory = "0"
403 a8083063 Iustin Pop
        stat = "-----"
404 a8083063 Iustin Pop
        times = "-1"
405 a8083063 Iustin Pop
        try:
406 a8083063 Iustin Pop
          inst_id = fh.readline().strip()
407 a8083063 Iustin Pop
          memory = fh.readline().strip()
408 a8083063 Iustin Pop
          vcpus = fh.readline().strip()
409 a8083063 Iustin Pop
          stat = "---b-"
410 a8083063 Iustin Pop
          times = "0"
411 a8083063 Iustin Pop
        finally:
412 a8083063 Iustin Pop
          fh.close()
413 a8083063 Iustin Pop
        data.append((file_name, inst_id, memory, vcpus, stat, times))
414 a8083063 Iustin Pop
      except IOError, err:
415 a8083063 Iustin Pop
        raise HypervisorError("Failed to list instances: %s" % err)
416 a8083063 Iustin Pop
    return data
417 a8083063 Iustin Pop
418 a8083063 Iustin Pop
  def StartInstance(self, instance, force, extra_args):
419 a8083063 Iustin Pop
    """Start an instance.
420 a8083063 Iustin Pop

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

425 a8083063 Iustin Pop
    """
426 a8083063 Iustin Pop
    file_name = self._ROOT_DIR + "/%s" % instance.name
427 a8083063 Iustin Pop
    if os.path.exists(file_name):
428 a8083063 Iustin Pop
      raise HypervisorError("Failed to start instance %s: %s" %
429 a8083063 Iustin Pop
                            (instance.name, "already running"))
430 a8083063 Iustin Pop
    try:
431 a8083063 Iustin Pop
      fh = file(file_name, "w")
432 a8083063 Iustin Pop
      try:
433 a8083063 Iustin Pop
        fh.write("0\n%d\n%d\n" % (instance.memory, instance.vcpus))
434 a8083063 Iustin Pop
      finally:
435 a8083063 Iustin Pop
        fh.close()
436 a8083063 Iustin Pop
    except IOError, err:
437 a8083063 Iustin Pop
      raise HypervisorError("Failed to start instance %s: %s" %
438 a8083063 Iustin Pop
                            (instance.name, err))
439 a8083063 Iustin Pop
440 a8083063 Iustin Pop
  def StopInstance(self, instance, force=False):
441 a8083063 Iustin Pop
    """Stop an instance.
442 a8083063 Iustin Pop

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

446 a8083063 Iustin Pop
    """
447 a8083063 Iustin Pop
    file_name = self._ROOT_DIR + "/%s" % instance.name
448 a8083063 Iustin Pop
    if not os.path.exists(file_name):
449 a8083063 Iustin Pop
      raise HypervisorError("Failed to stop instance %s: %s" %
450 a8083063 Iustin Pop
                            (instance.name, "not running"))
451 a8083063 Iustin Pop
    utils.RemoveFile(file_name)
452 a8083063 Iustin Pop
453 7e1394dc Alexander Schreiber
  def RebootInstance(self, instance):
454 7e1394dc Alexander Schreiber
    """Reboot an instance.
455 7e1394dc Alexander Schreiber

456 7e1394dc Alexander Schreiber
    For the fake hypervisor, this does nothing.
457 7e1394dc Alexander Schreiber

458 7e1394dc Alexander Schreiber
    """
459 7e1394dc Alexander Schreiber
    return
460 7e1394dc Alexander Schreiber
461 a8083063 Iustin Pop
  def GetNodeInfo(self):
462 a8083063 Iustin Pop
    """Return information about the node.
463 a8083063 Iustin Pop

464 a8083063 Iustin Pop
    The return value is a dict, which has to have the following items:
465 a8083063 Iustin Pop
      (all values in MiB)
466 a8083063 Iustin Pop
      - memory_total: the total memory size on the node
467 a8083063 Iustin Pop
      - memory_free: the available memory on the node for instances
468 a8083063 Iustin Pop
      - memory_dom0: the memory used by the node itself, if available
469 a8083063 Iustin Pop

470 a8083063 Iustin Pop
    """
471 a8083063 Iustin Pop
    # global ram usage from the xm info command
472 a8083063 Iustin Pop
    # memory                 : 3583
473 a8083063 Iustin Pop
    # free_memory            : 747
474 a8083063 Iustin Pop
    # note: in xen 3, memory has changed to total_memory
475 a8083063 Iustin Pop
    try:
476 a8083063 Iustin Pop
      fh = file("/proc/meminfo")
477 a8083063 Iustin Pop
      try:
478 a8083063 Iustin Pop
        data = fh.readlines()
479 a8083063 Iustin Pop
      finally:
480 a8083063 Iustin Pop
        fh.close()
481 a8083063 Iustin Pop
    except IOError, err:
482 a8083063 Iustin Pop
      raise HypervisorError("Failed to list node info: %s" % err)
483 a8083063 Iustin Pop
484 a8083063 Iustin Pop
    result = {}
485 a8083063 Iustin Pop
    sum_free = 0
486 a8083063 Iustin Pop
    for line in data:
487 a8083063 Iustin Pop
      splitfields = line.split(":", 1)
488 a8083063 Iustin Pop
489 a8083063 Iustin Pop
      if len(splitfields) > 1:
490 a8083063 Iustin Pop
        key = splitfields[0].strip()
491 a8083063 Iustin Pop
        val = splitfields[1].strip()
492 a8083063 Iustin Pop
        if key == 'MemTotal':
493 a8083063 Iustin Pop
          result['memory_total'] = int(val.split()[0])/1024
494 a8083063 Iustin Pop
        elif key in ('MemFree', 'Buffers', 'Cached'):
495 a8083063 Iustin Pop
          sum_free += int(val.split()[0])/1024
496 a8083063 Iustin Pop
        elif key == 'Active':
497 a8083063 Iustin Pop
          result['memory_dom0'] = int(val.split()[0])/1024
498 a8083063 Iustin Pop
499 a8083063 Iustin Pop
    result['memory_free'] = sum_free
500 a8083063 Iustin Pop
    return result
501 a8083063 Iustin Pop
502 a8083063 Iustin Pop
  @staticmethod
503 a8083063 Iustin Pop
  def GetShellCommandForConsole(instance_name):
504 a8083063 Iustin Pop
    """Return a command for connecting to the console of an instance.
505 a8083063 Iustin Pop

506 a8083063 Iustin Pop
    """
507 a8083063 Iustin Pop
    return "echo Console not available for fake hypervisor"
508 a8083063 Iustin Pop
509 a8083063 Iustin Pop
  def Verify(self):
510 a8083063 Iustin Pop
    """Verify the hypervisor.
511 a8083063 Iustin Pop

512 a8083063 Iustin Pop
    For the fake hypervisor, it just checks the existence of the base
513 a8083063 Iustin Pop
    dir.
514 a8083063 Iustin Pop

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