Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / FakeHypervisor.py @ e8a4c138

History | View | Annotate | Download (6.4 kB)

1
#
2
#
3

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

    
21

    
22
"""Fake hypervisor
23

24
"""
25

    
26
import os
27
import os.path
28
import re
29

    
30
from ganeti import utils
31
from ganeti import constants
32
from ganeti import errors
33
from ganeti.hypervisor import BaseHypervisor
34

    
35

    
36
class FakeHypervisor(BaseHypervisor.BaseHypervisor):
37
  """Fake hypervisor interface.
38

39
  This can be used for testing the ganeti code without having to have
40
  a real virtualisation software installed.
41

42
  """
43
  _ROOT_DIR = constants.RUN_DIR + "/ganeti-fake-hypervisor"
44

    
45
  def __init__(self):
46
    BaseHypervisor.__init__(self)
47
    if not os.path.exists(self._ROOT_DIR):
48
      os.mkdir(self._ROOT_DIR)
49

    
50
  def ListInstances(self):
51
    """Get the list of running instances.
52

53
    """
54
    return os.listdir(self._ROOT_DIR)
55

    
56
  def GetInstanceInfo(self, instance_name):
57
    """Get instance properties.
58

59
    Args:
60
      instance_name: the instance name
61

62
    Returns:
63
      (name, id, memory, vcpus, stat, times)
64
    """
65
    file_name = "%s/%s" % (self._ROOT_DIR, instance_name)
66
    if not os.path.exists(file_name):
67
      return None
68
    try:
69
      fh = file(file_name, "r")
70
      try:
71
        inst_id = fh.readline().strip()
72
        memory = fh.readline().strip()
73
        vcpus = fh.readline().strip()
74
        stat = "---b-"
75
        times = "0"
76
        return (instance_name, inst_id, memory, vcpus, stat, times)
77
      finally:
78
        fh.close()
79
    except IOError, err:
80
      raise errors.HypervisorError("Failed to list instance %s: %s" %
81
                                   (instance_name, err))
82

    
83
  def GetAllInstancesInfo(self):
84
    """Get properties of all instances.
85

86
    Returns:
87
      [(name, id, memory, vcpus, stat, times),...]
88
    """
89
    data = []
90
    for file_name in os.listdir(self._ROOT_DIR):
91
      try:
92
        fh = file(self._ROOT_DIR+"/"+file_name, "r")
93
        inst_id = "-1"
94
        memory = "0"
95
        stat = "-----"
96
        times = "-1"
97
        try:
98
          inst_id = fh.readline().strip()
99
          memory = fh.readline().strip()
100
          vcpus = fh.readline().strip()
101
          stat = "---b-"
102
          times = "0"
103
        finally:
104
          fh.close()
105
        data.append((file_name, inst_id, memory, vcpus, stat, times))
106
      except IOError, err:
107
        raise errors.HypervisorError("Failed to list instances: %s" % err)
108
    return data
109

    
110
  def StartInstance(self, instance, force, extra_args):
111
    """Start an instance.
112

113
    For the fake hypervisor, it just creates a file in the base dir,
114
    creating an exception if it already exists. We don't actually
115
    handle race conditions properly, since these are *FAKE* instances.
116

117
    """
118
    file_name = self._ROOT_DIR + "/%s" % instance.name
119
    if os.path.exists(file_name):
120
      raise errors.HypervisorError("Failed to start instance %s: %s" %
121
                                   (instance.name, "already running"))
122
    try:
123
      fh = file(file_name, "w")
124
      try:
125
        fh.write("0\n%d\n%d\n" % (instance.memory, instance.vcpus))
126
      finally:
127
        fh.close()
128
    except IOError, err:
129
      raise errors.HypervisorError("Failed to start instance %s: %s" %
130
                                   (instance.name, err))
131

    
132
  def StopInstance(self, instance, force=False):
133
    """Stop an instance.
134

135
    For the fake hypervisor, this just removes the file in the base
136
    dir, if it exist, otherwise we raise an exception.
137

138
    """
139
    file_name = self._ROOT_DIR + "/%s" % instance.name
140
    if not os.path.exists(file_name):
141
      raise errors.HypervisorError("Failed to stop instance %s: %s" %
142
                                   (instance.name, "not running"))
143
    utils.RemoveFile(file_name)
144

    
145
  def RebootInstance(self, instance):
146
    """Reboot an instance.
147

148
    For the fake hypervisor, this does nothing.
149

150
    """
151
    return
152

    
153
  def GetNodeInfo(self):
154
    """Return information about the node.
155

156
    The return value is a dict, which has to have the following items:
157
      (all values in MiB)
158
      - memory_total: the total memory size on the node
159
      - memory_free: the available memory on the node for instances
160
      - memory_dom0: the memory used by the node itself, if available
161

162
    """
163
    # global ram usage from the xm info command
164
    # memory                 : 3583
165
    # free_memory            : 747
166
    # note: in xen 3, memory has changed to total_memory
167
    try:
168
      fh = file("/proc/meminfo")
169
      try:
170
        data = fh.readlines()
171
      finally:
172
        fh.close()
173
    except IOError, err:
174
      raise errors.HypervisorError("Failed to list node info: %s" % err)
175

    
176
    result = {}
177
    sum_free = 0
178
    for line in data:
179
      splitfields = line.split(":", 1)
180

    
181
      if len(splitfields) > 1:
182
        key = splitfields[0].strip()
183
        val = splitfields[1].strip()
184
        if key == 'MemTotal':
185
          result['memory_total'] = int(val.split()[0])/1024
186
        elif key in ('MemFree', 'Buffers', 'Cached'):
187
          sum_free += int(val.split()[0])/1024
188
        elif key == 'Active':
189
          result['memory_dom0'] = int(val.split()[0])/1024
190
    result['memory_free'] = sum_free
191

    
192
    cpu_total = 0
193
    try:
194
      fh = open("/proc/cpuinfo")
195
      try:
196
        cpu_total = len(re.findall("(?m)^processor\s*:\s*[0-9]+\s*$",
197
                                   fh.read()))
198
      finally:
199
        fh.close()
200
    except EnvironmentError, err:
201
      raise HypervisorError("Failed to list node info: %s" % err)
202
    result['cpu_total'] = cpu_total
203

    
204
    return result
205

    
206
  @staticmethod
207
  def GetShellCommandForConsole(instance):
208
    """Return a command for connecting to the console of an instance.
209

210
    """
211
    return "echo Console not available for fake hypervisor"
212

    
213
  def Verify(self):
214
    """Verify the hypervisor.
215

216
    For the fake hypervisor, it just checks the existence of the base
217
    dir.
218

219
    """
220
    if not os.path.exists(self._ROOT_DIR):
221
      return "The required directory '%s' does not exist." % self._ROOT_DIR