Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor.py @ 2584d4a4

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
37 a8083063 Iustin Pop
def GetHypervisor():
38 a8083063 Iustin Pop
  """Return a Hypervisor instance.
39 a8083063 Iustin Pop

40 a8083063 Iustin Pop
  This function parses the cluster hypervisor configuration file and
41 a8083063 Iustin Pop
  instantiates a class based on the value of this file.
42 a8083063 Iustin Pop

43 a8083063 Iustin Pop
  """
44 a8083063 Iustin Pop
  ht_kind = ssconf.SimpleStore().GetHypervisorType()
45 2584d4a4 Alexander Schreiber
  if ht_kind == constants.HT_XEN30:
46 a8083063 Iustin Pop
    cls = XenHypervisor
47 2584d4a4 Alexander Schreiber
  elif ht_kind == constants.HT_FAKE:
48 a8083063 Iustin Pop
    cls = FakeHypervisor
49 a8083063 Iustin Pop
  else:
50 3ecf6786 Iustin Pop
    raise HypervisorError("Unknown hypervisor type '%s'" % ht_kind)
51 a8083063 Iustin Pop
  return cls()
52 a8083063 Iustin Pop
53 a8083063 Iustin Pop
54 a8083063 Iustin Pop
class BaseHypervisor(object):
55 a8083063 Iustin Pop
  """Abstract virtualisation technology interface
56 a8083063 Iustin Pop

57 a8083063 Iustin Pop
  The goal is that all aspects of the virtualisation technology must
58 a8083063 Iustin Pop
  be abstracted away from the rest of code.
59 a8083063 Iustin Pop

60 a8083063 Iustin Pop
  """
61 a8083063 Iustin Pop
  def __init__(self):
62 a8083063 Iustin Pop
    pass
63 a8083063 Iustin Pop
64 a8083063 Iustin Pop
  def StartInstance(self, instance, block_devices, extra_args):
65 a8083063 Iustin Pop
    """Start an instance."""
66 a8083063 Iustin Pop
    raise NotImplementedError
67 a8083063 Iustin Pop
68 a8083063 Iustin Pop
  def StopInstance(self, instance, force=False):
69 a8083063 Iustin Pop
    """Stop an instance."""
70 a8083063 Iustin Pop
    raise NotImplementedError
71 a8083063 Iustin Pop
72 7e1394dc Alexander Schreiber
  def RebootInstance(self, instance):
73 7e1394dc Alexander Schreiber
    """Reboot an instance."""
74 7e1394dc Alexander Schreiber
    raise NotImplementedError
75 7e1394dc Alexander Schreiber
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 523687d7 Iustin Pop
      raise HypervisorError("Failed to start instance %s: %s (%s)" %
265 523687d7 Iustin Pop
                            (instance.name, result.fail_reason, result.output))
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 7e1394dc Alexander Schreiber
  def RebootInstance(self, instance):
281 7e1394dc Alexander Schreiber
    """Reboot an instance."""
282 7e1394dc Alexander Schreiber
    result = utils.RunCmd(["xm", "reboot", instance.name])
283 7e1394dc Alexander Schreiber
284 7e1394dc Alexander Schreiber
    if result.failed:
285 7e1394dc Alexander Schreiber
      raise HypervisorError("Failed to reboot instance %s: %s" %
286 7e1394dc Alexander Schreiber
                            (instance.name, result.fail_reason))
287 7e1394dc Alexander Schreiber
288 a8083063 Iustin Pop
  def GetNodeInfo(self):
289 a8083063 Iustin Pop
    """Return information about the node.
290 a8083063 Iustin Pop

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

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

326 a8083063 Iustin Pop
    """
327 a8083063 Iustin Pop
    return "xm console %s" % instance_name
328 a8083063 Iustin Pop
329 a8083063 Iustin Pop
330 a8083063 Iustin Pop
  def Verify(self):
331 a8083063 Iustin Pop
    """Verify the hypervisor.
332 a8083063 Iustin Pop

333 a8083063 Iustin Pop
    For Xen, this verifies that the xend process is running.
334 a8083063 Iustin Pop

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

343 a8083063 Iustin Pop
  This can be used for testing the ganeti code without having to have
344 a8083063 Iustin Pop
  a real virtualisation software installed.
345 a8083063 Iustin Pop

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

357 a8083063 Iustin Pop
    """
358 a8083063 Iustin Pop
    return os.listdir(self._ROOT_DIR)
359 a8083063 Iustin Pop
360 a8083063 Iustin Pop
  def GetInstanceInfo(self, instance_name):
361 a8083063 Iustin Pop
    """Get instance properties.
362 a8083063 Iustin Pop

363 a8083063 Iustin Pop
    Args:
364 a8083063 Iustin Pop
      instance_name: the instance name
365 a8083063 Iustin Pop

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

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

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

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

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

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

452 7e1394dc Alexander Schreiber
    For the fake hypervisor, this does nothing.
453 7e1394dc Alexander Schreiber

454 7e1394dc Alexander Schreiber
    """
455 7e1394dc Alexander Schreiber
    return
456 7e1394dc Alexander Schreiber
457 a8083063 Iustin Pop
  def GetNodeInfo(self):
458 a8083063 Iustin Pop
    """Return information about the node.
459 a8083063 Iustin Pop

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

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

502 a8083063 Iustin Pop
    """
503 a8083063 Iustin Pop
    return "echo Console not available for fake hypervisor"
504 a8083063 Iustin Pop
505 a8083063 Iustin Pop
  def Verify(self):
506 a8083063 Iustin Pop
    """Verify the hypervisor.
507 a8083063 Iustin Pop

508 a8083063 Iustin Pop
    For the fake hypervisor, it just checks the existence of the base
509 a8083063 Iustin Pop
    dir.
510 a8083063 Iustin Pop

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