Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_fake.py @ 5661b908

History | View | Annotate | Download (6.5 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 hv_base
34

    
35

    
36
class FakeHypervisor(hv_base.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
    hv_base.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
    @param instance_name: the instance name
60

61
    @return: tuple of (name, id, memory, vcpus, stat, times)
62

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

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

85
    @return: list of tuples (name, id, memory, vcpus, stat, times)
86

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

    
109
  def StartInstance(self, instance, block_devices, extra_args):
110
    """Start an instance.
111

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

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

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

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

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

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

149
    For the fake hypervisor, this does nothing.
150

151
    """
152
    return
153

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

157
    @return: a dict with the following keys (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 errors.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