Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_fake.py @ 55cc0a44

History | View | Annotate | Download (8 kB)

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

24 65a6f9b7 Michael Hanselmann
"""
25 65a6f9b7 Michael Hanselmann
26 65a6f9b7 Michael Hanselmann
import os
27 65a6f9b7 Michael Hanselmann
import os.path
28 94fed7da Iustin Pop
import logging
29 65a6f9b7 Michael Hanselmann
30 65a6f9b7 Michael Hanselmann
from ganeti import utils
31 65a6f9b7 Michael Hanselmann
from ganeti import constants
32 65a6f9b7 Michael Hanselmann
from ganeti import errors
33 55cc0a44 Michael Hanselmann
from ganeti import objects
34 a2d32034 Michael Hanselmann
from ganeti.hypervisor import hv_base
35 65a6f9b7 Michael Hanselmann
36 65a6f9b7 Michael Hanselmann
37 a2d32034 Michael Hanselmann
class FakeHypervisor(hv_base.BaseHypervisor):
38 65a6f9b7 Michael Hanselmann
  """Fake hypervisor interface.
39 65a6f9b7 Michael Hanselmann

40 65a6f9b7 Michael Hanselmann
  This can be used for testing the ganeti code without having to have
41 65a6f9b7 Michael Hanselmann
  a real virtualisation software installed.
42 65a6f9b7 Michael Hanselmann

43 65a6f9b7 Michael Hanselmann
  """
44 d271c6fd Iustin Pop
  CAN_MIGRATE = True
45 d271c6fd Iustin Pop
46 6df291d4 Iustin Pop
  _ROOT_DIR = constants.RUN_GANETI_DIR + "/fake-hypervisor"
47 65a6f9b7 Michael Hanselmann
48 65a6f9b7 Michael Hanselmann
  def __init__(self):
49 a2d32034 Michael Hanselmann
    hv_base.BaseHypervisor.__init__(self)
50 98c98ab9 Guido Trotter
    utils.EnsureDirs([(self._ROOT_DIR, constants.RUN_DIRS_MODE)])
51 65a6f9b7 Michael Hanselmann
52 65a6f9b7 Michael Hanselmann
  def ListInstances(self):
53 65a6f9b7 Michael Hanselmann
    """Get the list of running instances.
54 65a6f9b7 Michael Hanselmann

55 65a6f9b7 Michael Hanselmann
    """
56 65a6f9b7 Michael Hanselmann
    return os.listdir(self._ROOT_DIR)
57 65a6f9b7 Michael Hanselmann
58 65a6f9b7 Michael Hanselmann
  def GetInstanceInfo(self, instance_name):
59 65a6f9b7 Michael Hanselmann
    """Get instance properties.
60 65a6f9b7 Michael Hanselmann

61 c41eea6e Iustin Pop
    @param instance_name: the instance name
62 c41eea6e Iustin Pop

63 c41eea6e Iustin Pop
    @return: tuple of (name, id, memory, vcpus, stat, times)
64 65a6f9b7 Michael Hanselmann

65 65a6f9b7 Michael Hanselmann
    """
66 3b80eb2c Iustin Pop
    file_name = self._InstanceFile(instance_name)
67 65a6f9b7 Michael Hanselmann
    if not os.path.exists(file_name):
68 65a6f9b7 Michael Hanselmann
      return None
69 65a6f9b7 Michael Hanselmann
    try:
70 bfc30ec0 Iustin Pop
      fh = open(file_name, "r")
71 65a6f9b7 Michael Hanselmann
      try:
72 65a6f9b7 Michael Hanselmann
        inst_id = fh.readline().strip()
73 bfc30ec0 Iustin Pop
        memory = utils.TryConvert(int, fh.readline().strip())
74 4c4b5058 Iustin Pop
        vcpus = utils.TryConvert(int, fh.readline().strip())
75 65a6f9b7 Michael Hanselmann
        stat = "---b-"
76 65a6f9b7 Michael Hanselmann
        times = "0"
77 65a6f9b7 Michael Hanselmann
        return (instance_name, inst_id, memory, vcpus, stat, times)
78 65a6f9b7 Michael Hanselmann
      finally:
79 65a6f9b7 Michael Hanselmann
        fh.close()
80 65a6f9b7 Michael Hanselmann
    except IOError, err:
81 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("Failed to list instance %s: %s" %
82 65a6f9b7 Michael Hanselmann
                                   (instance_name, err))
83 65a6f9b7 Michael Hanselmann
84 65a6f9b7 Michael Hanselmann
  def GetAllInstancesInfo(self):
85 65a6f9b7 Michael Hanselmann
    """Get properties of all instances.
86 65a6f9b7 Michael Hanselmann

87 c41eea6e Iustin Pop
    @return: list of tuples (name, id, memory, vcpus, stat, times)
88 c41eea6e Iustin Pop

89 65a6f9b7 Michael Hanselmann
    """
90 65a6f9b7 Michael Hanselmann
    data = []
91 65a6f9b7 Michael Hanselmann
    for file_name in os.listdir(self._ROOT_DIR):
92 65a6f9b7 Michael Hanselmann
      try:
93 3b80eb2c Iustin Pop
        fh = open(utils.PathJoin(self._ROOT_DIR, file_name), "r")
94 65a6f9b7 Michael Hanselmann
        inst_id = "-1"
95 bfc30ec0 Iustin Pop
        memory = 0
96 bfc30ec0 Iustin Pop
        vcpus = 1
97 65a6f9b7 Michael Hanselmann
        stat = "-----"
98 65a6f9b7 Michael Hanselmann
        times = "-1"
99 65a6f9b7 Michael Hanselmann
        try:
100 65a6f9b7 Michael Hanselmann
          inst_id = fh.readline().strip()
101 bfc30ec0 Iustin Pop
          memory = utils.TryConvert(int, fh.readline().strip())
102 bfc30ec0 Iustin Pop
          vcpus = utils.TryConvert(int, fh.readline().strip())
103 65a6f9b7 Michael Hanselmann
          stat = "---b-"
104 65a6f9b7 Michael Hanselmann
          times = "0"
105 65a6f9b7 Michael Hanselmann
        finally:
106 65a6f9b7 Michael Hanselmann
          fh.close()
107 65a6f9b7 Michael Hanselmann
        data.append((file_name, inst_id, memory, vcpus, stat, times))
108 65a6f9b7 Michael Hanselmann
      except IOError, err:
109 65a6f9b7 Michael Hanselmann
        raise errors.HypervisorError("Failed to list instances: %s" % err)
110 65a6f9b7 Michael Hanselmann
    return data
111 65a6f9b7 Michael Hanselmann
112 3b80eb2c Iustin Pop
  @classmethod
113 3b80eb2c Iustin Pop
  def _InstanceFile(cls, instance_name):
114 94fed7da Iustin Pop
    """Compute the instance file for an instance name.
115 94fed7da Iustin Pop

116 94fed7da Iustin Pop
    """
117 3b80eb2c Iustin Pop
    return utils.PathJoin(cls._ROOT_DIR, instance_name)
118 94fed7da Iustin Pop
119 94fed7da Iustin Pop
  def _IsAlive(self, instance_name):
120 94fed7da Iustin Pop
    """Checks if an instance is alive.
121 94fed7da Iustin Pop

122 94fed7da Iustin Pop
    """
123 94fed7da Iustin Pop
    file_name = self._InstanceFile(instance_name)
124 94fed7da Iustin Pop
    return os.path.exists(file_name)
125 94fed7da Iustin Pop
126 94fed7da Iustin Pop
  def _MarkUp(self, instance):
127 94fed7da Iustin Pop
    """Mark the instance as running.
128 94fed7da Iustin Pop

129 94fed7da Iustin Pop
    This does no checks, which should be done by its callers.
130 94fed7da Iustin Pop

131 94fed7da Iustin Pop
    """
132 94fed7da Iustin Pop
    file_name = self._InstanceFile(instance.name)
133 94fed7da Iustin Pop
    fh = file(file_name, "w")
134 94fed7da Iustin Pop
    try:
135 94fed7da Iustin Pop
      fh.write("0\n%d\n%d\n" %
136 94fed7da Iustin Pop
               (instance.beparams[constants.BE_MEMORY],
137 94fed7da Iustin Pop
                instance.beparams[constants.BE_VCPUS]))
138 94fed7da Iustin Pop
    finally:
139 94fed7da Iustin Pop
      fh.close()
140 94fed7da Iustin Pop
141 bbcf7ad0 Iustin Pop
  def _MarkDown(self, instance_name):
142 94fed7da Iustin Pop
    """Mark the instance as running.
143 94fed7da Iustin Pop

144 94fed7da Iustin Pop
    This does no checks, which should be done by its callers.
145 94fed7da Iustin Pop

146 94fed7da Iustin Pop
    """
147 bbcf7ad0 Iustin Pop
    file_name = self._InstanceFile(instance_name)
148 94fed7da Iustin Pop
    utils.RemoveFile(file_name)
149 94fed7da Iustin Pop
150 07813a9e Iustin Pop
  def StartInstance(self, instance, block_devices):
151 65a6f9b7 Michael Hanselmann
    """Start an instance.
152 65a6f9b7 Michael Hanselmann

153 65a6f9b7 Michael Hanselmann
    For the fake hypervisor, it just creates a file in the base dir,
154 65a6f9b7 Michael Hanselmann
    creating an exception if it already exists. We don't actually
155 65a6f9b7 Michael Hanselmann
    handle race conditions properly, since these are *FAKE* instances.
156 65a6f9b7 Michael Hanselmann

157 65a6f9b7 Michael Hanselmann
    """
158 94fed7da Iustin Pop
    if self._IsAlive(instance.name):
159 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("Failed to start instance %s: %s" %
160 65a6f9b7 Michael Hanselmann
                                   (instance.name, "already running"))
161 65a6f9b7 Michael Hanselmann
    try:
162 94fed7da Iustin Pop
      self._MarkUp(instance)
163 65a6f9b7 Michael Hanselmann
    except IOError, err:
164 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("Failed to start instance %s: %s" %
165 65a6f9b7 Michael Hanselmann
                                   (instance.name, err))
166 65a6f9b7 Michael Hanselmann
167 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
168 65a6f9b7 Michael Hanselmann
    """Stop an instance.
169 65a6f9b7 Michael Hanselmann

170 65a6f9b7 Michael Hanselmann
    For the fake hypervisor, this just removes the file in the base
171 65a6f9b7 Michael Hanselmann
    dir, if it exist, otherwise we raise an exception.
172 65a6f9b7 Michael Hanselmann

173 65a6f9b7 Michael Hanselmann
    """
174 bbcf7ad0 Iustin Pop
    if name is None:
175 bbcf7ad0 Iustin Pop
      name = instance.name
176 bbcf7ad0 Iustin Pop
    if not self._IsAlive(name):
177 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("Failed to stop instance %s: %s" %
178 bbcf7ad0 Iustin Pop
                                   (name, "not running"))
179 bbcf7ad0 Iustin Pop
    self._MarkDown(name)
180 65a6f9b7 Michael Hanselmann
181 65a6f9b7 Michael Hanselmann
  def RebootInstance(self, instance):
182 65a6f9b7 Michael Hanselmann
    """Reboot an instance.
183 65a6f9b7 Michael Hanselmann

184 65a6f9b7 Michael Hanselmann
    For the fake hypervisor, this does nothing.
185 65a6f9b7 Michael Hanselmann

186 65a6f9b7 Michael Hanselmann
    """
187 65a6f9b7 Michael Hanselmann
    return
188 65a6f9b7 Michael Hanselmann
189 65a6f9b7 Michael Hanselmann
  def GetNodeInfo(self):
190 65a6f9b7 Michael Hanselmann
    """Return information about the node.
191 65a6f9b7 Michael Hanselmann

192 572e52bf Iustin Pop
    This is just a wrapper over the base GetLinuxNodeInfo method.
193 572e52bf Iustin Pop

194 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
195 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
196 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
197 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
198 65a6f9b7 Michael Hanselmann

199 65a6f9b7 Michael Hanselmann
    """
200 572e52bf Iustin Pop
    result = self.GetLinuxNodeInfo()
201 bfc30ec0 Iustin Pop
    # substract running instances
202 bfc30ec0 Iustin Pop
    all_instances = self.GetAllInstancesInfo()
203 bfc30ec0 Iustin Pop
    result['memory_free'] -= min(result['memory_free'],
204 bfc30ec0 Iustin Pop
                                 sum([row[2] for row in all_instances]))
205 65a6f9b7 Michael Hanselmann
    return result
206 65a6f9b7 Michael Hanselmann
207 637ce7f9 Guido Trotter
  @classmethod
208 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
209 55cc0a44 Michael Hanselmann
    """Return information for connecting to the console of an instance.
210 65a6f9b7 Michael Hanselmann

211 65a6f9b7 Michael Hanselmann
    """
212 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
213 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
214 55cc0a44 Michael Hanselmann
                                   message=("Console not available for fake"
215 55cc0a44 Michael Hanselmann
                                            " hypervisor"))
216 65a6f9b7 Michael Hanselmann
217 65a6f9b7 Michael Hanselmann
  def Verify(self):
218 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
219 65a6f9b7 Michael Hanselmann

220 65a6f9b7 Michael Hanselmann
    For the fake hypervisor, it just checks the existence of the base
221 65a6f9b7 Michael Hanselmann
    dir.
222 65a6f9b7 Michael Hanselmann

223 65a6f9b7 Michael Hanselmann
    """
224 65a6f9b7 Michael Hanselmann
    if not os.path.exists(self._ROOT_DIR):
225 65a6f9b7 Michael Hanselmann
      return "The required directory '%s' does not exist." % self._ROOT_DIR
226 f5118ade Iustin Pop
227 f5118ade Iustin Pop
  @classmethod
228 f5118ade Iustin Pop
  def PowercycleNode(cls):
229 f5118ade Iustin Pop
    """Fake hypervisor powercycle, just a wrapper over Linux powercycle.
230 f5118ade Iustin Pop

231 f5118ade Iustin Pop
    """
232 f5118ade Iustin Pop
    cls.LinuxPowercycle()
233 94fed7da Iustin Pop
234 94fed7da Iustin Pop
  def AcceptInstance(self, instance, info, target):
235 94fed7da Iustin Pop
    """Prepare to accept an instance.
236 94fed7da Iustin Pop

237 94fed7da Iustin Pop
    @type instance: L{objects.Instance}
238 94fed7da Iustin Pop
    @param instance: instance to be accepted
239 94fed7da Iustin Pop
    @type info: string
240 94fed7da Iustin Pop
    @param info: instance info, not used
241 94fed7da Iustin Pop
    @type target: string
242 94fed7da Iustin Pop
    @param target: target host (usually ip), on this node
243 94fed7da Iustin Pop

244 94fed7da Iustin Pop
    """
245 94fed7da Iustin Pop
    if self._IsAlive(instance.name):
246 94fed7da Iustin Pop
      raise errors.HypervisorError("Can't accept instance, already running")
247 94fed7da Iustin Pop
248 94fed7da Iustin Pop
  def MigrateInstance(self, instance, target, live):
249 94fed7da Iustin Pop
    """Migrate an instance.
250 94fed7da Iustin Pop

251 3a488770 Iustin Pop
    @type instance: L{objects.Instance}
252 94fed7da Iustin Pop
    @param instance: the instance to be migrated
253 94fed7da Iustin Pop
    @type target: string
254 94fed7da Iustin Pop
    @param target: hostname (usually ip) of the target node
255 94fed7da Iustin Pop
    @type live: boolean
256 94fed7da Iustin Pop
    @param live: whether to do a live or non-live migration
257 94fed7da Iustin Pop

258 94fed7da Iustin Pop
    """
259 94fed7da Iustin Pop
    logging.debug("Fake hypervisor migrating %s to %s (live=%s)",
260 94fed7da Iustin Pop
                  instance, target, live)
261 94fed7da Iustin Pop
262 bbcf7ad0 Iustin Pop
    self._MarkDown(instance.name)
263 94fed7da Iustin Pop
264 94fed7da Iustin Pop
  def FinalizeMigration(self, instance, info, success):
265 94fed7da Iustin Pop
    """Finalize an instance migration.
266 94fed7da Iustin Pop

267 94fed7da Iustin Pop
    For the fake hv, this just marks the instance up.
268 94fed7da Iustin Pop

269 94fed7da Iustin Pop
    @type instance: L{objects.Instance}
270 94fed7da Iustin Pop
    @param instance: instance whose migration is being finalized
271 94fed7da Iustin Pop

272 94fed7da Iustin Pop
    """
273 94fed7da Iustin Pop
    if success:
274 94fed7da Iustin Pop
      self._MarkUp(instance)
275 94fed7da Iustin Pop
    else:
276 94fed7da Iustin Pop
      # ensure it's down
277 bbcf7ad0 Iustin Pop
      self._MarkDown(instance.name)