Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor.py @ 01121d61

History | View | Annotate | Download (15.4 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 631eb662 Alexander Schreiber
  if ht_kind == constants.HT_XEN_PVM30:
46 631eb662 Alexander Schreiber
    cls = XenPvmHypervisor
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 30989e69 Alexander Schreiber
  def GetShellCommandForConsole(instance):
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 631eb662 Alexander Schreiber
  """Xen generic hypervisor interface
128 631eb662 Alexander Schreiber

129 631eb662 Alexander Schreiber
  This is the Xen base class used for both Xen PVM and HVM. It contains
130 631eb662 Alexander Schreiber
  all the functionality that is identical for both.
131 631eb662 Alexander Schreiber

132 631eb662 Alexander Schreiber
  """
133 a8083063 Iustin Pop
134 a8083063 Iustin Pop
  @staticmethod
135 a8083063 Iustin Pop
  def _WriteConfigFile(instance, block_devices, extra_args):
136 631eb662 Alexander Schreiber
    """A Xen instance config file.
137 a8083063 Iustin Pop

138 a8083063 Iustin Pop
    """
139 631eb662 Alexander Schreiber
    raise NotImplementedError
140 a8083063 Iustin Pop
141 a8083063 Iustin Pop
  @staticmethod
142 a8083063 Iustin Pop
  def _RemoveConfigFile(instance):
143 a8083063 Iustin Pop
    """Remove the xen configuration file.
144 a8083063 Iustin Pop

145 a8083063 Iustin Pop
    """
146 a8083063 Iustin Pop
    utils.RemoveFile("/etc/xen/%s" % instance.name)
147 a8083063 Iustin Pop
148 a8083063 Iustin Pop
  @staticmethod
149 a8083063 Iustin Pop
  def _GetXMList(include_node):
150 a8083063 Iustin Pop
    """Return the list of running instances.
151 a8083063 Iustin Pop

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

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

157 a8083063 Iustin Pop
    """
158 a8083063 Iustin Pop
    for dummy in range(5):
159 a8083063 Iustin Pop
      result = utils.RunCmd(["xm", "list"])
160 a8083063 Iustin Pop
      if not result.failed:
161 a8083063 Iustin Pop
        break
162 a8083063 Iustin Pop
      logger.Error("xm list failed (%s): %s" % (result.fail_reason,
163 a8083063 Iustin Pop
                                                result.output))
164 a8083063 Iustin Pop
      time.sleep(1)
165 a8083063 Iustin Pop
166 a8083063 Iustin Pop
    if result.failed:
167 a8083063 Iustin Pop
      raise HypervisorError("xm list failed, retries exceeded (%s): %s" %
168 a8083063 Iustin Pop
                            (result.fail_reason, result.stderr))
169 a8083063 Iustin Pop
170 a8083063 Iustin Pop
    # skip over the heading and the domain 0 line (optional)
171 a8083063 Iustin Pop
    if include_node:
172 a8083063 Iustin Pop
      to_skip = 1
173 a8083063 Iustin Pop
    else:
174 a8083063 Iustin Pop
      to_skip = 2
175 a8083063 Iustin Pop
    lines = result.stdout.splitlines()[to_skip:]
176 a8083063 Iustin Pop
    result = []
177 a8083063 Iustin Pop
    for line in lines:
178 a8083063 Iustin Pop
      # The format of lines is:
179 a8083063 Iustin Pop
      # Name      ID Mem(MiB) VCPUs State  Time(s)
180 a8083063 Iustin Pop
      # Domain-0   0  3418     4 r-----    266.2
181 a8083063 Iustin Pop
      data = line.split()
182 a8083063 Iustin Pop
      if len(data) != 6:
183 a8083063 Iustin Pop
        raise HypervisorError("Can't parse output of xm list, line: %s" % line)
184 a8083063 Iustin Pop
      try:
185 a8083063 Iustin Pop
        data[1] = int(data[1])
186 a8083063 Iustin Pop
        data[2] = int(data[2])
187 a8083063 Iustin Pop
        data[3] = int(data[3])
188 a8083063 Iustin Pop
        data[5] = float(data[5])
189 a8083063 Iustin Pop
      except ValueError, err:
190 a8083063 Iustin Pop
        raise HypervisorError("Can't parse output of xm list,"
191 a8083063 Iustin Pop
                              " line: %s, error: %s" % (line, err))
192 a8083063 Iustin Pop
      result.append(data)
193 a8083063 Iustin Pop
    return result
194 a8083063 Iustin Pop
195 a8083063 Iustin Pop
  def ListInstances(self):
196 a8083063 Iustin Pop
    """Get the list of running instances.
197 a8083063 Iustin Pop

198 a8083063 Iustin Pop
    """
199 a8083063 Iustin Pop
    xm_list = self._GetXMList(False)
200 a8083063 Iustin Pop
    names = [info[0] for info in xm_list]
201 a8083063 Iustin Pop
    return names
202 a8083063 Iustin Pop
203 a8083063 Iustin Pop
  def GetInstanceInfo(self, instance_name):
204 a8083063 Iustin Pop
    """Get instance properties.
205 a8083063 Iustin Pop

206 a8083063 Iustin Pop
    Args:
207 a8083063 Iustin Pop
      instance_name: the instance name
208 a8083063 Iustin Pop

209 a8083063 Iustin Pop
    Returns:
210 a8083063 Iustin Pop
      (name, id, memory, vcpus, stat, times)
211 a8083063 Iustin Pop
    """
212 a8083063 Iustin Pop
    xm_list = self._GetXMList(instance_name=="Domain-0")
213 a8083063 Iustin Pop
    result = None
214 a8083063 Iustin Pop
    for data in xm_list:
215 a8083063 Iustin Pop
      if data[0] == instance_name:
216 a8083063 Iustin Pop
        result = data
217 a8083063 Iustin Pop
        break
218 a8083063 Iustin Pop
    return result
219 a8083063 Iustin Pop
220 a8083063 Iustin Pop
  def GetAllInstancesInfo(self):
221 a8083063 Iustin Pop
    """Get properties of all instances.
222 a8083063 Iustin Pop

223 a8083063 Iustin Pop
    Returns:
224 a8083063 Iustin Pop
      [(name, id, memory, vcpus, stat, times),...]
225 a8083063 Iustin Pop
    """
226 a8083063 Iustin Pop
    xm_list = self._GetXMList(False)
227 a8083063 Iustin Pop
    return xm_list
228 a8083063 Iustin Pop
229 a8083063 Iustin Pop
  def StartInstance(self, instance, block_devices, extra_args):
230 a8083063 Iustin Pop
    """Start an instance."""
231 a8083063 Iustin Pop
    self._WriteConfigFile(instance, block_devices, extra_args)
232 a8083063 Iustin Pop
    result = utils.RunCmd(["xm", "create", instance.name])
233 a8083063 Iustin Pop
234 a8083063 Iustin Pop
    if result.failed:
235 523687d7 Iustin Pop
      raise HypervisorError("Failed to start instance %s: %s (%s)" %
236 523687d7 Iustin Pop
                            (instance.name, result.fail_reason, result.output))
237 a8083063 Iustin Pop
238 a8083063 Iustin Pop
  def StopInstance(self, instance, force=False):
239 a8083063 Iustin Pop
    """Stop an instance."""
240 a8083063 Iustin Pop
    self._RemoveConfigFile(instance)
241 a8083063 Iustin Pop
    if force:
242 a8083063 Iustin Pop
      command = ["xm", "destroy", instance.name]
243 a8083063 Iustin Pop
    else:
244 a8083063 Iustin Pop
      command = ["xm", "shutdown", instance.name]
245 a8083063 Iustin Pop
    result = utils.RunCmd(command)
246 a8083063 Iustin Pop
247 a8083063 Iustin Pop
    if result.failed:
248 a8083063 Iustin Pop
      raise HypervisorError("Failed to stop instance %s: %s" %
249 a8083063 Iustin Pop
                            (instance.name, result.fail_reason))
250 a8083063 Iustin Pop
251 7e1394dc Alexander Schreiber
  def RebootInstance(self, instance):
252 7e1394dc Alexander Schreiber
    """Reboot an instance."""
253 7e1394dc Alexander Schreiber
    result = utils.RunCmd(["xm", "reboot", instance.name])
254 7e1394dc Alexander Schreiber
255 7e1394dc Alexander Schreiber
    if result.failed:
256 7e1394dc Alexander Schreiber
      raise HypervisorError("Failed to reboot instance %s: %s" %
257 7e1394dc Alexander Schreiber
                            (instance.name, result.fail_reason))
258 7e1394dc Alexander Schreiber
259 a8083063 Iustin Pop
  def GetNodeInfo(self):
260 a8083063 Iustin Pop
    """Return information about the node.
261 a8083063 Iustin Pop

262 a8083063 Iustin Pop
    The return value is a dict, which has to have the following items:
263 a8083063 Iustin Pop
      (all values in MiB)
264 a8083063 Iustin Pop
      - memory_total: the total memory size on the node
265 a8083063 Iustin Pop
      - memory_free: the available memory on the node for instances
266 a8083063 Iustin Pop
      - memory_dom0: the memory used by the node itself, if available
267 a8083063 Iustin Pop

268 a8083063 Iustin Pop
    """
269 a8083063 Iustin Pop
    # note: in xen 3, memory has changed to total_memory
270 a8083063 Iustin Pop
    result = utils.RunCmd(["xm", "info"])
271 a8083063 Iustin Pop
    if result.failed:
272 a8083063 Iustin Pop
      logger.Error("Can't run 'xm info': %s" % result.fail_reason)
273 a8083063 Iustin Pop
      return None
274 a8083063 Iustin Pop
275 a8083063 Iustin Pop
    xmoutput = result.stdout.splitlines()
276 a8083063 Iustin Pop
    result = {}
277 a8083063 Iustin Pop
    for line in xmoutput:
278 a8083063 Iustin Pop
      splitfields = line.split(":", 1)
279 a8083063 Iustin Pop
280 a8083063 Iustin Pop
      if len(splitfields) > 1:
281 a8083063 Iustin Pop
        key = splitfields[0].strip()
282 a8083063 Iustin Pop
        val = splitfields[1].strip()
283 a8083063 Iustin Pop
        if key == 'memory' or key == 'total_memory':
284 a8083063 Iustin Pop
          result['memory_total'] = int(val)
285 a8083063 Iustin Pop
        elif key == 'free_memory':
286 a8083063 Iustin Pop
          result['memory_free'] = int(val)
287 a8083063 Iustin Pop
    dom0_info = self.GetInstanceInfo("Domain-0")
288 a8083063 Iustin Pop
    if dom0_info is not None:
289 a8083063 Iustin Pop
      result['memory_dom0'] = dom0_info[2]
290 a8083063 Iustin Pop
291 a8083063 Iustin Pop
    return result
292 a8083063 Iustin Pop
293 a8083063 Iustin Pop
  @staticmethod
294 30989e69 Alexander Schreiber
  def GetShellCommandForConsole(instance):
295 a8083063 Iustin Pop
    """Return a command for connecting to the console of an instance.
296 a8083063 Iustin Pop

297 a8083063 Iustin Pop
    """
298 631eb662 Alexander Schreiber
    raise NotImplementedError
299 a8083063 Iustin Pop
300 a8083063 Iustin Pop
301 a8083063 Iustin Pop
  def Verify(self):
302 a8083063 Iustin Pop
    """Verify the hypervisor.
303 a8083063 Iustin Pop

304 a8083063 Iustin Pop
    For Xen, this verifies that the xend process is running.
305 a8083063 Iustin Pop

306 a8083063 Iustin Pop
    """
307 a8083063 Iustin Pop
    if not utils.CheckDaemonAlive('/var/run/xend.pid', 'xend'):
308 a8083063 Iustin Pop
      return "xend daemon is not running"
309 a8083063 Iustin Pop
310 a8083063 Iustin Pop
311 631eb662 Alexander Schreiber
class XenPvmHypervisor(XenHypervisor):
312 631eb662 Alexander Schreiber
  """Xen PVM hypervisor interface"""
313 631eb662 Alexander Schreiber
314 631eb662 Alexander Schreiber
  @staticmethod
315 631eb662 Alexander Schreiber
  def _WriteConfigFile(instance, block_devices, extra_args):
316 631eb662 Alexander Schreiber
    """Create a Xen instance config file.
317 631eb662 Alexander Schreiber

318 631eb662 Alexander Schreiber
    """
319 631eb662 Alexander Schreiber
    config = StringIO()
320 631eb662 Alexander Schreiber
    config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
321 631eb662 Alexander Schreiber
    config.write("kernel = '%s'\n" % constants.XEN_KERNEL)
322 631eb662 Alexander Schreiber
    if os.path.exists(constants.XEN_INITRD):
323 631eb662 Alexander Schreiber
      config.write("ramdisk = '%s'\n" % constants.XEN_INITRD)
324 631eb662 Alexander Schreiber
    config.write("memory = %d\n" % instance.memory)
325 631eb662 Alexander Schreiber
    config.write("vcpus = %d\n" % instance.vcpus)
326 631eb662 Alexander Schreiber
    config.write("name = '%s'\n" % instance.name)
327 631eb662 Alexander Schreiber
328 631eb662 Alexander Schreiber
    vif_data = []
329 631eb662 Alexander Schreiber
    for nic in instance.nics:
330 631eb662 Alexander Schreiber
      nic_str = "mac=%s, bridge=%s" % (nic.mac, nic.bridge)
331 631eb662 Alexander Schreiber
      ip = getattr(nic, "ip", None)
332 631eb662 Alexander Schreiber
      if ip is not None:
333 631eb662 Alexander Schreiber
        nic_str += ", ip=%s" % ip
334 631eb662 Alexander Schreiber
      vif_data.append("'%s'" % nic_str)
335 631eb662 Alexander Schreiber
336 631eb662 Alexander Schreiber
    config.write("vif = [%s]\n" % ",".join(vif_data))
337 631eb662 Alexander Schreiber
338 631eb662 Alexander Schreiber
    disk_data = ["'phy:%s,%s,w'" % (rldev.dev_path, cfdev.iv_name)
339 631eb662 Alexander Schreiber
                 for cfdev, rldev in block_devices]
340 631eb662 Alexander Schreiber
    config.write("disk = [%s]\n" % ",".join(disk_data))
341 631eb662 Alexander Schreiber
342 631eb662 Alexander Schreiber
    config.write("root = '/dev/sda ro'\n")
343 631eb662 Alexander Schreiber
    config.write("on_poweroff = 'destroy'\n")
344 631eb662 Alexander Schreiber
    config.write("on_reboot = 'restart'\n")
345 631eb662 Alexander Schreiber
    config.write("on_crash = 'restart'\n")
346 631eb662 Alexander Schreiber
    if extra_args:
347 631eb662 Alexander Schreiber
      config.write("extra = '%s'\n" % extra_args)
348 631eb662 Alexander Schreiber
    # just in case it exists
349 631eb662 Alexander Schreiber
    utils.RemoveFile("/etc/xen/auto/%s" % instance.name)
350 01121d61 Alexander Schreiber
    try:
351 01121d61 Alexander Schreiber
      f = open("/etc/xen/%s" % instance.name, "w")
352 01121d61 Alexander Schreiber
      try:
353 01121d61 Alexander Schreiber
        f.write(config.getvalue())
354 01121d61 Alexander Schreiber
      finally:
355 01121d61 Alexander Schreiber
        f.close()
356 01121d61 Alexander Schreiber
    except IOError, err:
357 01121d61 Alexander Schreiber
      raise errors.OpExecError("Cannot write Xen instance confile"
358 01121d61 Alexander Schreiber
                               " file /etc/xen/%s: %s" % (instance.name, err))
359 631eb662 Alexander Schreiber
    return True
360 631eb662 Alexander Schreiber
361 631eb662 Alexander Schreiber
  @staticmethod
362 631eb662 Alexander Schreiber
  def GetShellCommandForConsole(instance):
363 631eb662 Alexander Schreiber
    """Return a command for connecting to the console of an instance.
364 631eb662 Alexander Schreiber

365 631eb662 Alexander Schreiber
    """
366 631eb662 Alexander Schreiber
    return "xm console %s" % instance.name
367 631eb662 Alexander Schreiber
368 631eb662 Alexander Schreiber
369 a8083063 Iustin Pop
class FakeHypervisor(BaseHypervisor):
370 a8083063 Iustin Pop
  """Fake hypervisor interface.
371 a8083063 Iustin Pop

372 a8083063 Iustin Pop
  This can be used for testing the ganeti code without having to have
373 a8083063 Iustin Pop
  a real virtualisation software installed.
374 a8083063 Iustin Pop

375 a8083063 Iustin Pop
  """
376 a8083063 Iustin Pop
  _ROOT_DIR = "/var/run/ganeti-fake-hypervisor"
377 a8083063 Iustin Pop
378 a8083063 Iustin Pop
  def __init__(self):
379 a8083063 Iustin Pop
    BaseHypervisor.__init__(self)
380 a8083063 Iustin Pop
    if not os.path.exists(self._ROOT_DIR):
381 a8083063 Iustin Pop
      os.mkdir(self._ROOT_DIR)
382 a8083063 Iustin Pop
383 a8083063 Iustin Pop
  def ListInstances(self):
384 a8083063 Iustin Pop
    """Get the list of running instances.
385 a8083063 Iustin Pop

386 a8083063 Iustin Pop
    """
387 a8083063 Iustin Pop
    return os.listdir(self._ROOT_DIR)
388 a8083063 Iustin Pop
389 a8083063 Iustin Pop
  def GetInstanceInfo(self, instance_name):
390 a8083063 Iustin Pop
    """Get instance properties.
391 a8083063 Iustin Pop

392 a8083063 Iustin Pop
    Args:
393 a8083063 Iustin Pop
      instance_name: the instance name
394 a8083063 Iustin Pop

395 a8083063 Iustin Pop
    Returns:
396 a8083063 Iustin Pop
      (name, id, memory, vcpus, stat, times)
397 a8083063 Iustin Pop
    """
398 a8083063 Iustin Pop
    file_name = "%s/%s" % (self._ROOT_DIR, instance_name)
399 a8083063 Iustin Pop
    if not os.path.exists(file_name):
400 a8083063 Iustin Pop
      return None
401 a8083063 Iustin Pop
    try:
402 a8083063 Iustin Pop
      fh = file(file_name, "r")
403 a8083063 Iustin Pop
      try:
404 a8083063 Iustin Pop
        inst_id = fh.readline().strip()
405 a8083063 Iustin Pop
        memory = fh.readline().strip()
406 a8083063 Iustin Pop
        vcpus = fh.readline().strip()
407 a8083063 Iustin Pop
        stat = "---b-"
408 a8083063 Iustin Pop
        times = "0"
409 a8083063 Iustin Pop
        return (instance_name, inst_id, memory, vcpus, stat, times)
410 a8083063 Iustin Pop
      finally:
411 a8083063 Iustin Pop
        fh.close()
412 a8083063 Iustin Pop
    except IOError, err:
413 a8083063 Iustin Pop
      raise HypervisorError("Failed to list instance %s: %s" %
414 a8083063 Iustin Pop
                            (instance_name, err))
415 a8083063 Iustin Pop
416 a8083063 Iustin Pop
  def GetAllInstancesInfo(self):
417 a8083063 Iustin Pop
    """Get properties of all instances.
418 a8083063 Iustin Pop

419 a8083063 Iustin Pop
    Returns:
420 a8083063 Iustin Pop
      [(name, id, memory, vcpus, stat, times),...]
421 a8083063 Iustin Pop
    """
422 a8083063 Iustin Pop
    data = []
423 a8083063 Iustin Pop
    for file_name in os.listdir(self._ROOT_DIR):
424 a8083063 Iustin Pop
      try:
425 a8083063 Iustin Pop
        fh = file(self._ROOT_DIR+"/"+file_name, "r")
426 a8083063 Iustin Pop
        inst_id = "-1"
427 a8083063 Iustin Pop
        memory = "0"
428 a8083063 Iustin Pop
        stat = "-----"
429 a8083063 Iustin Pop
        times = "-1"
430 a8083063 Iustin Pop
        try:
431 a8083063 Iustin Pop
          inst_id = fh.readline().strip()
432 a8083063 Iustin Pop
          memory = fh.readline().strip()
433 a8083063 Iustin Pop
          vcpus = fh.readline().strip()
434 a8083063 Iustin Pop
          stat = "---b-"
435 a8083063 Iustin Pop
          times = "0"
436 a8083063 Iustin Pop
        finally:
437 a8083063 Iustin Pop
          fh.close()
438 a8083063 Iustin Pop
        data.append((file_name, inst_id, memory, vcpus, stat, times))
439 a8083063 Iustin Pop
      except IOError, err:
440 a8083063 Iustin Pop
        raise HypervisorError("Failed to list instances: %s" % err)
441 a8083063 Iustin Pop
    return data
442 a8083063 Iustin Pop
443 a8083063 Iustin Pop
  def StartInstance(self, instance, force, extra_args):
444 a8083063 Iustin Pop
    """Start an instance.
445 a8083063 Iustin Pop

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

450 a8083063 Iustin Pop
    """
451 a8083063 Iustin Pop
    file_name = self._ROOT_DIR + "/%s" % instance.name
452 a8083063 Iustin Pop
    if os.path.exists(file_name):
453 a8083063 Iustin Pop
      raise HypervisorError("Failed to start instance %s: %s" %
454 a8083063 Iustin Pop
                            (instance.name, "already running"))
455 a8083063 Iustin Pop
    try:
456 a8083063 Iustin Pop
      fh = file(file_name, "w")
457 a8083063 Iustin Pop
      try:
458 a8083063 Iustin Pop
        fh.write("0\n%d\n%d\n" % (instance.memory, instance.vcpus))
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 start instance %s: %s" %
463 a8083063 Iustin Pop
                            (instance.name, err))
464 a8083063 Iustin Pop
465 a8083063 Iustin Pop
  def StopInstance(self, instance, force=False):
466 a8083063 Iustin Pop
    """Stop an instance.
467 a8083063 Iustin Pop

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

471 a8083063 Iustin Pop
    """
472 a8083063 Iustin Pop
    file_name = self._ROOT_DIR + "/%s" % instance.name
473 a8083063 Iustin Pop
    if not os.path.exists(file_name):
474 a8083063 Iustin Pop
      raise HypervisorError("Failed to stop instance %s: %s" %
475 a8083063 Iustin Pop
                            (instance.name, "not running"))
476 a8083063 Iustin Pop
    utils.RemoveFile(file_name)
477 a8083063 Iustin Pop
478 7e1394dc Alexander Schreiber
  def RebootInstance(self, instance):
479 7e1394dc Alexander Schreiber
    """Reboot an instance.
480 7e1394dc Alexander Schreiber

481 7e1394dc Alexander Schreiber
    For the fake hypervisor, this does nothing.
482 7e1394dc Alexander Schreiber

483 7e1394dc Alexander Schreiber
    """
484 7e1394dc Alexander Schreiber
    return
485 7e1394dc Alexander Schreiber
486 a8083063 Iustin Pop
  def GetNodeInfo(self):
487 a8083063 Iustin Pop
    """Return information about the node.
488 a8083063 Iustin Pop

489 a8083063 Iustin Pop
    The return value is a dict, which has to have the following items:
490 a8083063 Iustin Pop
      (all values in MiB)
491 a8083063 Iustin Pop
      - memory_total: the total memory size on the node
492 a8083063 Iustin Pop
      - memory_free: the available memory on the node for instances
493 a8083063 Iustin Pop
      - memory_dom0: the memory used by the node itself, if available
494 a8083063 Iustin Pop

495 a8083063 Iustin Pop
    """
496 a8083063 Iustin Pop
    # global ram usage from the xm info command
497 a8083063 Iustin Pop
    # memory                 : 3583
498 a8083063 Iustin Pop
    # free_memory            : 747
499 a8083063 Iustin Pop
    # note: in xen 3, memory has changed to total_memory
500 a8083063 Iustin Pop
    try:
501 a8083063 Iustin Pop
      fh = file("/proc/meminfo")
502 a8083063 Iustin Pop
      try:
503 a8083063 Iustin Pop
        data = fh.readlines()
504 a8083063 Iustin Pop
      finally:
505 a8083063 Iustin Pop
        fh.close()
506 a8083063 Iustin Pop
    except IOError, err:
507 a8083063 Iustin Pop
      raise HypervisorError("Failed to list node info: %s" % err)
508 a8083063 Iustin Pop
509 a8083063 Iustin Pop
    result = {}
510 a8083063 Iustin Pop
    sum_free = 0
511 a8083063 Iustin Pop
    for line in data:
512 a8083063 Iustin Pop
      splitfields = line.split(":", 1)
513 a8083063 Iustin Pop
514 a8083063 Iustin Pop
      if len(splitfields) > 1:
515 a8083063 Iustin Pop
        key = splitfields[0].strip()
516 a8083063 Iustin Pop
        val = splitfields[1].strip()
517 a8083063 Iustin Pop
        if key == 'MemTotal':
518 a8083063 Iustin Pop
          result['memory_total'] = int(val.split()[0])/1024
519 a8083063 Iustin Pop
        elif key in ('MemFree', 'Buffers', 'Cached'):
520 a8083063 Iustin Pop
          sum_free += int(val.split()[0])/1024
521 a8083063 Iustin Pop
        elif key == 'Active':
522 a8083063 Iustin Pop
          result['memory_dom0'] = int(val.split()[0])/1024
523 a8083063 Iustin Pop
524 a8083063 Iustin Pop
    result['memory_free'] = sum_free
525 a8083063 Iustin Pop
    return result
526 a8083063 Iustin Pop
527 a8083063 Iustin Pop
  @staticmethod
528 30989e69 Alexander Schreiber
  def GetShellCommandForConsole(instance):
529 a8083063 Iustin Pop
    """Return a command for connecting to the console of an instance.
530 a8083063 Iustin Pop

531 a8083063 Iustin Pop
    """
532 a8083063 Iustin Pop
    return "echo Console not available for fake hypervisor"
533 a8083063 Iustin Pop
534 a8083063 Iustin Pop
  def Verify(self):
535 a8083063 Iustin Pop
    """Verify the hypervisor.
536 a8083063 Iustin Pop

537 a8083063 Iustin Pop
    For the fake hypervisor, it just checks the existence of the base
538 a8083063 Iustin Pop
    dir.
539 a8083063 Iustin Pop

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