Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_fake.py @ cfdf561d

History | View | Annotate | Download (10.2 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 cfb5f9da Guido Trotter
  def _MarkUp(self, instance, memory):
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 cfb5f9da Guido Trotter
               (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 323f9095 Stephen Shirley
  def StartInstance(self, instance, block_devices, startup_paused):
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 61eb1a46 Guido Trotter
      self._MarkUp(instance, self._InstanceStartupMemory(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 cfb5f9da Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
190 cfb5f9da Guido Trotter
    """Balloon an instance memory to a certain value.
191 cfb5f9da Guido Trotter

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

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

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

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

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

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

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

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

249 f5118ade Iustin Pop
    """
250 f5118ade Iustin Pop
    cls.LinuxPowercycle()
251 94fed7da Iustin Pop
252 94fed7da Iustin Pop
  def AcceptInstance(self, instance, info, target):
253 94fed7da Iustin Pop
    """Prepare to accept an instance.
254 94fed7da Iustin Pop

255 94fed7da Iustin Pop
    @type instance: L{objects.Instance}
256 94fed7da Iustin Pop
    @param instance: instance to be accepted
257 94fed7da Iustin Pop
    @type info: string
258 94fed7da Iustin Pop
    @param info: instance info, not used
259 94fed7da Iustin Pop
    @type target: string
260 94fed7da Iustin Pop
    @param target: target host (usually ip), on this node
261 94fed7da Iustin Pop

262 94fed7da Iustin Pop
    """
263 94fed7da Iustin Pop
    if self._IsAlive(instance.name):
264 94fed7da Iustin Pop
      raise errors.HypervisorError("Can't accept instance, already running")
265 94fed7da Iustin Pop
266 94fed7da Iustin Pop
  def MigrateInstance(self, instance, target, live):
267 94fed7da Iustin Pop
    """Migrate an instance.
268 94fed7da Iustin Pop

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

276 94fed7da Iustin Pop
    """
277 94fed7da Iustin Pop
    logging.debug("Fake hypervisor migrating %s to %s (live=%s)",
278 94fed7da Iustin Pop
                  instance, target, live)
279 94fed7da Iustin Pop
280 60af751d Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
281 60af751d Andrea Spadaccini
    """Finalize the instance migration on the target node.
282 94fed7da Iustin Pop

283 94fed7da Iustin Pop
    For the fake hv, this just marks the instance up.
284 94fed7da Iustin Pop

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

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

302 60af751d Andrea Spadaccini
    To be executed on the source node.
303 60af751d Andrea Spadaccini

304 60af751d Andrea Spadaccini
    @type instance: L{objects.Instance}
305 60af751d Andrea Spadaccini
    @param instance: the instance that was migrated
306 60af751d Andrea Spadaccini

307 60af751d Andrea Spadaccini
    """
308 60af751d Andrea Spadaccini
    pass
309 60af751d Andrea Spadaccini
310 60af751d Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
311 60af751d Andrea Spadaccini
    """Finalize the instance migration on the source node.
312 60af751d Andrea Spadaccini

313 60af751d Andrea Spadaccini
    @type instance: L{objects.Instance}
314 60af751d Andrea Spadaccini
    @param instance: the instance that was migrated
315 60af751d Andrea Spadaccini
    @type success: bool
316 60af751d Andrea Spadaccini
    @param success: whether the migration succeeded or not
317 60af751d Andrea Spadaccini
    @type live: bool
318 60af751d Andrea Spadaccini
    @param live: whether the user requested a live migration or not
319 60af751d Andrea Spadaccini

320 60af751d Andrea Spadaccini
    """
321 60af751d Andrea Spadaccini
    # pylint: disable=W0613
322 60af751d Andrea Spadaccini
    if success:
323 60af751d Andrea Spadaccini
      self._MarkDown(instance.name)
324 60af751d Andrea Spadaccini
325 60af751d Andrea Spadaccini
  def GetMigrationStatus(self, instance):
326 60af751d Andrea Spadaccini
    """Get the migration status
327 60af751d Andrea Spadaccini

328 60af751d Andrea Spadaccini
    The fake hypervisor migration always succeeds.
329 60af751d Andrea Spadaccini

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

337 60af751d Andrea Spadaccini
    """
338 60af751d Andrea Spadaccini
    return objects.MigrationStatus(status=constants.HV_MIGRATION_COMPLETED)