Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_fake.py @ 6f1e1921

History | View | Annotate | Download (10.3 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 9d9bded1 Michael Hanselmann
from ganeti import pathutils
35 a2d32034 Michael Hanselmann
from ganeti.hypervisor import hv_base
36 65a6f9b7 Michael Hanselmann
37 65a6f9b7 Michael Hanselmann
38 a2d32034 Michael Hanselmann
class FakeHypervisor(hv_base.BaseHypervisor):
39 65a6f9b7 Michael Hanselmann
  """Fake hypervisor interface.
40 65a6f9b7 Michael Hanselmann

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

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

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

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

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

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

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

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

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

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

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

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

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

147 94fed7da Iustin Pop
    """
148 bbcf7ad0 Iustin Pop
    file_name = self._InstanceFile(instance_name)
149 94fed7da Iustin Pop
    utils.RemoveFile(file_name)
150 94fed7da Iustin Pop
151 323f9095 Stephen Shirley
  def StartInstance(self, instance, block_devices, startup_paused):
152 65a6f9b7 Michael Hanselmann
    """Start an instance.
153 65a6f9b7 Michael Hanselmann

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

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

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

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

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

187 65a6f9b7 Michael Hanselmann
    """
188 65a6f9b7 Michael Hanselmann
    return
189 65a6f9b7 Michael Hanselmann
190 cfb5f9da Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
191 cfb5f9da Guido Trotter
    """Balloon an instance memory to a certain value.
192 cfb5f9da Guido Trotter

193 cfb5f9da Guido Trotter
    @type instance: L{objects.Instance}
194 cfb5f9da Guido Trotter
    @param instance: instance to be accepted
195 cfb5f9da Guido Trotter
    @type mem: int
196 cfb5f9da Guido Trotter
    @param mem: actual memory size to use for instance runtime
197 cfb5f9da Guido Trotter

198 cfb5f9da Guido Trotter
    """
199 cfb5f9da Guido Trotter
    if not self._IsAlive(instance.name):
200 cfb5f9da Guido Trotter
      raise errors.HypervisorError("Failed to balloon memory for %s: %s" %
201 cfb5f9da Guido Trotter
                                   (instance.name, "not running"))
202 cfb5f9da Guido Trotter
    try:
203 cfb5f9da Guido Trotter
      self._MarkUp(instance, mem)
204 cfb5f9da Guido Trotter
    except EnvironmentError, err:
205 cfb5f9da Guido Trotter
      raise errors.HypervisorError("Failed to balloon memory for %s: %s" %
206 cfb5f9da Guido Trotter
                                   (instance.name, utils.ErrnoOrStr(err)))
207 cfb5f9da Guido Trotter
208 65a6f9b7 Michael Hanselmann
  def GetNodeInfo(self):
209 65a6f9b7 Michael Hanselmann
    """Return information about the node.
210 65a6f9b7 Michael Hanselmann

211 572e52bf Iustin Pop
    This is just a wrapper over the base GetLinuxNodeInfo method.
212 572e52bf Iustin Pop

213 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
214 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
215 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
216 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
217 65a6f9b7 Michael Hanselmann

218 65a6f9b7 Michael Hanselmann
    """
219 572e52bf Iustin Pop
    result = self.GetLinuxNodeInfo()
220 bfc30ec0 Iustin Pop
    # substract running instances
221 bfc30ec0 Iustin Pop
    all_instances = self.GetAllInstancesInfo()
222 d0c8c01d Iustin Pop
    result["memory_free"] -= min(result["memory_free"],
223 bfc30ec0 Iustin Pop
                                 sum([row[2] for row in all_instances]))
224 65a6f9b7 Michael Hanselmann
    return result
225 65a6f9b7 Michael Hanselmann
226 637ce7f9 Guido Trotter
  @classmethod
227 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
228 55cc0a44 Michael Hanselmann
    """Return information for connecting to the console of an instance.
229 65a6f9b7 Michael Hanselmann

230 65a6f9b7 Michael Hanselmann
    """
231 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
232 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
233 55cc0a44 Michael Hanselmann
                                   message=("Console not available for fake"
234 55cc0a44 Michael Hanselmann
                                            " hypervisor"))
235 65a6f9b7 Michael Hanselmann
236 65a6f9b7 Michael Hanselmann
  def Verify(self):
237 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
238 65a6f9b7 Michael Hanselmann

239 65a6f9b7 Michael Hanselmann
    For the fake hypervisor, it just checks the existence of the base
240 65a6f9b7 Michael Hanselmann
    dir.
241 65a6f9b7 Michael Hanselmann

242 cd04dfd2 Michael Hanselmann
    @return: Problem description if something is wrong, C{None} otherwise
243 cd04dfd2 Michael Hanselmann

244 65a6f9b7 Michael Hanselmann
    """
245 cd04dfd2 Michael Hanselmann
    if os.path.exists(self._ROOT_DIR):
246 cd04dfd2 Michael Hanselmann
      return None
247 cd04dfd2 Michael Hanselmann
    else:
248 cd04dfd2 Michael Hanselmann
      return "The required directory '%s' does not exist" % self._ROOT_DIR
249 f5118ade Iustin Pop
250 f5118ade Iustin Pop
  @classmethod
251 f5118ade Iustin Pop
  def PowercycleNode(cls):
252 f5118ade Iustin Pop
    """Fake hypervisor powercycle, just a wrapper over Linux powercycle.
253 f5118ade Iustin Pop

254 f5118ade Iustin Pop
    """
255 f5118ade Iustin Pop
    cls.LinuxPowercycle()
256 94fed7da Iustin Pop
257 94fed7da Iustin Pop
  def AcceptInstance(self, instance, info, target):
258 94fed7da Iustin Pop
    """Prepare to accept an instance.
259 94fed7da Iustin Pop

260 94fed7da Iustin Pop
    @type instance: L{objects.Instance}
261 94fed7da Iustin Pop
    @param instance: instance to be accepted
262 94fed7da Iustin Pop
    @type info: string
263 94fed7da Iustin Pop
    @param info: instance info, not used
264 94fed7da Iustin Pop
    @type target: string
265 94fed7da Iustin Pop
    @param target: target host (usually ip), on this node
266 94fed7da Iustin Pop

267 94fed7da Iustin Pop
    """
268 94fed7da Iustin Pop
    if self._IsAlive(instance.name):
269 94fed7da Iustin Pop
      raise errors.HypervisorError("Can't accept instance, already running")
270 94fed7da Iustin Pop
271 94fed7da Iustin Pop
  def MigrateInstance(self, instance, target, live):
272 94fed7da Iustin Pop
    """Migrate an instance.
273 94fed7da Iustin Pop

274 3a488770 Iustin Pop
    @type instance: L{objects.Instance}
275 94fed7da Iustin Pop
    @param instance: the instance to be migrated
276 94fed7da Iustin Pop
    @type target: string
277 94fed7da Iustin Pop
    @param target: hostname (usually ip) of the target node
278 94fed7da Iustin Pop
    @type live: boolean
279 94fed7da Iustin Pop
    @param live: whether to do a live or non-live migration
280 94fed7da Iustin Pop

281 94fed7da Iustin Pop
    """
282 94fed7da Iustin Pop
    logging.debug("Fake hypervisor migrating %s to %s (live=%s)",
283 94fed7da Iustin Pop
                  instance, target, live)
284 94fed7da Iustin Pop
285 60af751d Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
286 60af751d Andrea Spadaccini
    """Finalize the instance migration on the target node.
287 94fed7da Iustin Pop

288 94fed7da Iustin Pop
    For the fake hv, this just marks the instance up.
289 94fed7da Iustin Pop

290 94fed7da Iustin Pop
    @type instance: L{objects.Instance}
291 94fed7da Iustin Pop
    @param instance: instance whose migration is being finalized
292 60af751d Andrea Spadaccini
    @type info: string/data (opaque)
293 60af751d Andrea Spadaccini
    @param info: migration information, from the source node
294 60af751d Andrea Spadaccini
    @type success: boolean
295 60af751d Andrea Spadaccini
    @param success: whether the migration was a success or a failure
296 94fed7da Iustin Pop

297 94fed7da Iustin Pop
    """
298 94fed7da Iustin Pop
    if success:
299 61eb1a46 Guido Trotter
      self._MarkUp(instance, self._InstanceStartupMemory(instance))
300 94fed7da Iustin Pop
    else:
301 94fed7da Iustin Pop
      # ensure it's down
302 bbcf7ad0 Iustin Pop
      self._MarkDown(instance.name)
303 60af751d Andrea Spadaccini
304 60af751d Andrea Spadaccini
  def PostMigrationCleanup(self, instance):
305 60af751d Andrea Spadaccini
    """Clean-up after a migration.
306 60af751d Andrea Spadaccini

307 60af751d Andrea Spadaccini
    To be executed on the source node.
308 60af751d Andrea Spadaccini

309 60af751d Andrea Spadaccini
    @type instance: L{objects.Instance}
310 60af751d Andrea Spadaccini
    @param instance: the instance that was migrated
311 60af751d Andrea Spadaccini

312 60af751d Andrea Spadaccini
    """
313 60af751d Andrea Spadaccini
    pass
314 60af751d Andrea Spadaccini
315 60af751d Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
316 60af751d Andrea Spadaccini
    """Finalize the instance migration on the source node.
317 60af751d Andrea Spadaccini

318 60af751d Andrea Spadaccini
    @type instance: L{objects.Instance}
319 60af751d Andrea Spadaccini
    @param instance: the instance that was migrated
320 60af751d Andrea Spadaccini
    @type success: bool
321 60af751d Andrea Spadaccini
    @param success: whether the migration succeeded or not
322 60af751d Andrea Spadaccini
    @type live: bool
323 60af751d Andrea Spadaccini
    @param live: whether the user requested a live migration or not
324 60af751d Andrea Spadaccini

325 60af751d Andrea Spadaccini
    """
326 60af751d Andrea Spadaccini
    # pylint: disable=W0613
327 60af751d Andrea Spadaccini
    if success:
328 60af751d Andrea Spadaccini
      self._MarkDown(instance.name)
329 60af751d Andrea Spadaccini
330 60af751d Andrea Spadaccini
  def GetMigrationStatus(self, instance):
331 60af751d Andrea Spadaccini
    """Get the migration status
332 60af751d Andrea Spadaccini

333 60af751d Andrea Spadaccini
    The fake hypervisor migration always succeeds.
334 60af751d Andrea Spadaccini

335 60af751d Andrea Spadaccini
    @type instance: L{objects.Instance}
336 60af751d Andrea Spadaccini
    @param instance: the instance that is being migrated
337 60af751d Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
338 60af751d Andrea Spadaccini
    @return: the status of the current migration (one of
339 60af751d Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
340 60af751d Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
341 60af751d Andrea Spadaccini

342 60af751d Andrea Spadaccini
    """
343 60af751d Andrea Spadaccini
    return objects.MigrationStatus(status=constants.HV_MIGRATION_COMPLETED)