Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_fake.py @ ff05ff94

History | View | Annotate | Download (10.7 kB)

1 65a6f9b7 Michael Hanselmann
#
2 65a6f9b7 Michael Hanselmann
#
3 65a6f9b7 Michael Hanselmann
4 ef14e128 Bernardo Dal Seno
# Copyright (C) 2006, 2007, 2008, 2013 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 d76880d8 Thomas Thrainer
  PARAMETERS = {
46 d76880d8 Thomas Thrainer
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
47 d76880d8 Thomas Thrainer
    }
48 d76880d8 Thomas Thrainer
49 d271c6fd Iustin Pop
  CAN_MIGRATE = True
50 d271c6fd Iustin Pop
51 9d9bded1 Michael Hanselmann
  _ROOT_DIR = pathutils.RUN_DIR + "/fake-hypervisor"
52 65a6f9b7 Michael Hanselmann
53 65a6f9b7 Michael Hanselmann
  def __init__(self):
54 a2d32034 Michael Hanselmann
    hv_base.BaseHypervisor.__init__(self)
55 98c98ab9 Guido Trotter
    utils.EnsureDirs([(self._ROOT_DIR, constants.RUN_DIRS_MODE)])
56 65a6f9b7 Michael Hanselmann
57 58e356a9 Helga Velroyen
  def ListInstances(self, hvparams=None):
58 65a6f9b7 Michael Hanselmann
    """Get the list of running instances.
59 65a6f9b7 Michael Hanselmann

60 65a6f9b7 Michael Hanselmann
    """
61 65a6f9b7 Michael Hanselmann
    return os.listdir(self._ROOT_DIR)
62 65a6f9b7 Michael Hanselmann
63 0bbec3af Helga Velroyen
  def GetInstanceInfo(self, instance_name, hvparams=None):
64 65a6f9b7 Michael Hanselmann
    """Get instance properties.
65 65a6f9b7 Michael Hanselmann

66 0bbec3af Helga Velroyen
    @type instance_name: string
67 c41eea6e Iustin Pop
    @param instance_name: the instance name
68 0bbec3af Helga Velroyen
    @type hvparams: dict of strings
69 0bbec3af Helga Velroyen
    @param hvparams: hvparams to be used with this instance
70 c41eea6e Iustin Pop

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

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

95 0200a1af Helga Velroyen
    @type hvparams: dict of strings
96 0200a1af Helga Velroyen
    @param hvparams: hypervisor parameter
97 c41eea6e Iustin Pop
    @return: list of tuples (name, id, memory, vcpus, stat, times)
98 c41eea6e Iustin Pop

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

126 94fed7da Iustin Pop
    """
127 3b80eb2c Iustin Pop
    return utils.PathJoin(cls._ROOT_DIR, instance_name)
128 94fed7da Iustin Pop
129 94fed7da Iustin Pop
  def _IsAlive(self, instance_name):
130 94fed7da Iustin Pop
    """Checks if an instance is alive.
131 94fed7da Iustin Pop

132 94fed7da Iustin Pop
    """
133 94fed7da Iustin Pop
    file_name = self._InstanceFile(instance_name)
134 94fed7da Iustin Pop
    return os.path.exists(file_name)
135 94fed7da Iustin Pop
136 cfb5f9da Guido Trotter
  def _MarkUp(self, instance, memory):
137 94fed7da Iustin Pop
    """Mark the instance as running.
138 94fed7da Iustin Pop

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

141 94fed7da Iustin Pop
    """
142 94fed7da Iustin Pop
    file_name = self._InstanceFile(instance.name)
143 94fed7da Iustin Pop
    fh = file(file_name, "w")
144 94fed7da Iustin Pop
    try:
145 94fed7da Iustin Pop
      fh.write("0\n%d\n%d\n" %
146 cfb5f9da Guido Trotter
               (memory,
147 94fed7da Iustin Pop
                instance.beparams[constants.BE_VCPUS]))
148 94fed7da Iustin Pop
    finally:
149 94fed7da Iustin Pop
      fh.close()
150 94fed7da Iustin Pop
151 bbcf7ad0 Iustin Pop
  def _MarkDown(self, instance_name):
152 94fed7da Iustin Pop
    """Mark the instance as running.
153 94fed7da Iustin Pop

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

156 94fed7da Iustin Pop
    """
157 bbcf7ad0 Iustin Pop
    file_name = self._InstanceFile(instance_name)
158 94fed7da Iustin Pop
    utils.RemoveFile(file_name)
159 94fed7da Iustin Pop
160 323f9095 Stephen Shirley
  def StartInstance(self, instance, block_devices, startup_paused):
161 65a6f9b7 Michael Hanselmann
    """Start an instance.
162 65a6f9b7 Michael Hanselmann

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

167 65a6f9b7 Michael Hanselmann
    """
168 94fed7da Iustin Pop
    if self._IsAlive(instance.name):
169 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("Failed to start instance %s: %s" %
170 65a6f9b7 Michael Hanselmann
                                   (instance.name, "already running"))
171 65a6f9b7 Michael Hanselmann
    try:
172 61eb1a46 Guido Trotter
      self._MarkUp(instance, self._InstanceStartupMemory(instance))
173 65a6f9b7 Michael Hanselmann
    except IOError, err:
174 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("Failed to start instance %s: %s" %
175 65a6f9b7 Michael Hanselmann
                                   (instance.name, err))
176 65a6f9b7 Michael Hanselmann
177 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
178 65a6f9b7 Michael Hanselmann
    """Stop an instance.
179 65a6f9b7 Michael Hanselmann

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

183 65a6f9b7 Michael Hanselmann
    """
184 bbcf7ad0 Iustin Pop
    if name is None:
185 bbcf7ad0 Iustin Pop
      name = instance.name
186 bbcf7ad0 Iustin Pop
    if not self._IsAlive(name):
187 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("Failed to stop instance %s: %s" %
188 bbcf7ad0 Iustin Pop
                                   (name, "not running"))
189 bbcf7ad0 Iustin Pop
    self._MarkDown(name)
190 65a6f9b7 Michael Hanselmann
191 65a6f9b7 Michael Hanselmann
  def RebootInstance(self, instance):
192 65a6f9b7 Michael Hanselmann
    """Reboot an instance.
193 65a6f9b7 Michael Hanselmann

194 65a6f9b7 Michael Hanselmann
    For the fake hypervisor, this does nothing.
195 65a6f9b7 Michael Hanselmann

196 65a6f9b7 Michael Hanselmann
    """
197 65a6f9b7 Michael Hanselmann
    return
198 65a6f9b7 Michael Hanselmann
199 cfb5f9da Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
200 cfb5f9da Guido Trotter
    """Balloon an instance memory to a certain value.
201 cfb5f9da Guido Trotter

202 cfb5f9da Guido Trotter
    @type instance: L{objects.Instance}
203 cfb5f9da Guido Trotter
    @param instance: instance to be accepted
204 cfb5f9da Guido Trotter
    @type mem: int
205 cfb5f9da Guido Trotter
    @param mem: actual memory size to use for instance runtime
206 cfb5f9da Guido Trotter

207 cfb5f9da Guido Trotter
    """
208 cfb5f9da Guido Trotter
    if not self._IsAlive(instance.name):
209 cfb5f9da Guido Trotter
      raise errors.HypervisorError("Failed to balloon memory for %s: %s" %
210 cfb5f9da Guido Trotter
                                   (instance.name, "not running"))
211 cfb5f9da Guido Trotter
    try:
212 cfb5f9da Guido Trotter
      self._MarkUp(instance, mem)
213 cfb5f9da Guido Trotter
    except EnvironmentError, err:
214 cfb5f9da Guido Trotter
      raise errors.HypervisorError("Failed to balloon memory for %s: %s" %
215 cfb5f9da Guido Trotter
                                   (instance.name, utils.ErrnoOrStr(err)))
216 cfb5f9da Guido Trotter
217 fac489a5 Helga Velroyen
  def GetNodeInfo(self, hvparams=None):
218 65a6f9b7 Michael Hanselmann
    """Return information about the node.
219 65a6f9b7 Michael Hanselmann

220 ef14e128 Bernardo Dal Seno
    See L{BaseHypervisor.GetLinuxNodeInfo}.
221 65a6f9b7 Michael Hanselmann

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

234 65a6f9b7 Michael Hanselmann
    """
235 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
236 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_MESSAGE,
237 55cc0a44 Michael Hanselmann
                                   message=("Console not available for fake"
238 55cc0a44 Michael Hanselmann
                                            " hypervisor"))
239 65a6f9b7 Michael Hanselmann
240 75bf3149 Helga Velroyen
  def Verify(self, hvparams=None):
241 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
242 65a6f9b7 Michael Hanselmann

243 65a6f9b7 Michael Hanselmann
    For the fake hypervisor, it just checks the existence of the base
244 65a6f9b7 Michael Hanselmann
    dir.
245 65a6f9b7 Michael Hanselmann

246 75bf3149 Helga Velroyen
    @type hvparams: dict of strings
247 75bf3149 Helga Velroyen
    @param hvparams: hypervisor parameters to be verified against; not used
248 75bf3149 Helga Velroyen
      for fake hypervisors
249 75bf3149 Helga Velroyen

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

252 65a6f9b7 Michael Hanselmann
    """
253 cd04dfd2 Michael Hanselmann
    if os.path.exists(self._ROOT_DIR):
254 cd04dfd2 Michael Hanselmann
      return None
255 cd04dfd2 Michael Hanselmann
    else:
256 cd04dfd2 Michael Hanselmann
      return "The required directory '%s' does not exist" % self._ROOT_DIR
257 f5118ade Iustin Pop
258 f5118ade Iustin Pop
  @classmethod
259 8ef418bb Helga Velroyen
  def PowercycleNode(cls, hvparams=None):
260 f5118ade Iustin Pop
    """Fake hypervisor powercycle, just a wrapper over Linux powercycle.
261 f5118ade Iustin Pop

262 8ef418bb Helga Velroyen
    @type hvparams: dict of strings
263 8ef418bb Helga Velroyen
    @param hvparams: hypervisor params to be used on this node
264 8ef418bb Helga Velroyen

265 f5118ade Iustin Pop
    """
266 f5118ade Iustin Pop
    cls.LinuxPowercycle()
267 94fed7da Iustin Pop
268 94fed7da Iustin Pop
  def AcceptInstance(self, instance, info, target):
269 94fed7da Iustin Pop
    """Prepare to accept an instance.
270 94fed7da Iustin Pop

271 94fed7da Iustin Pop
    @type instance: L{objects.Instance}
272 94fed7da Iustin Pop
    @param instance: instance to be accepted
273 94fed7da Iustin Pop
    @type info: string
274 94fed7da Iustin Pop
    @param info: instance info, not used
275 94fed7da Iustin Pop
    @type target: string
276 94fed7da Iustin Pop
    @param target: target host (usually ip), on this node
277 94fed7da Iustin Pop

278 94fed7da Iustin Pop
    """
279 94fed7da Iustin Pop
    if self._IsAlive(instance.name):
280 94fed7da Iustin Pop
      raise errors.HypervisorError("Can't accept instance, already running")
281 94fed7da Iustin Pop
282 bc0a2284 Helga Velroyen
  def MigrateInstance(self, cluster_name, instance, target, live):
283 94fed7da Iustin Pop
    """Migrate an instance.
284 94fed7da Iustin Pop

285 bc0a2284 Helga Velroyen
    @type cluster_name: string
286 bc0a2284 Helga Velroyen
    @param cluster_name: name of the cluster
287 3a488770 Iustin Pop
    @type instance: L{objects.Instance}
288 94fed7da Iustin Pop
    @param instance: the instance to be migrated
289 94fed7da Iustin Pop
    @type target: string
290 94fed7da Iustin Pop
    @param target: hostname (usually ip) of the target node
291 94fed7da Iustin Pop
    @type live: boolean
292 94fed7da Iustin Pop
    @param live: whether to do a live or non-live migration
293 94fed7da Iustin Pop

294 94fed7da Iustin Pop
    """
295 94fed7da Iustin Pop
    logging.debug("Fake hypervisor migrating %s to %s (live=%s)",
296 94fed7da Iustin Pop
                  instance, target, live)
297 94fed7da Iustin Pop
298 60af751d Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
299 60af751d Andrea Spadaccini
    """Finalize the instance migration on the target node.
300 94fed7da Iustin Pop

301 94fed7da Iustin Pop
    For the fake hv, this just marks the instance up.
302 94fed7da Iustin Pop

303 94fed7da Iustin Pop
    @type instance: L{objects.Instance}
304 94fed7da Iustin Pop
    @param instance: instance whose migration is being finalized
305 60af751d Andrea Spadaccini
    @type info: string/data (opaque)
306 60af751d Andrea Spadaccini
    @param info: migration information, from the source node
307 60af751d Andrea Spadaccini
    @type success: boolean
308 60af751d Andrea Spadaccini
    @param success: whether the migration was a success or a failure
309 94fed7da Iustin Pop

310 94fed7da Iustin Pop
    """
311 94fed7da Iustin Pop
    if success:
312 61eb1a46 Guido Trotter
      self._MarkUp(instance, self._InstanceStartupMemory(instance))
313 94fed7da Iustin Pop
    else:
314 94fed7da Iustin Pop
      # ensure it's down
315 bbcf7ad0 Iustin Pop
      self._MarkDown(instance.name)
316 60af751d Andrea Spadaccini
317 60af751d Andrea Spadaccini
  def PostMigrationCleanup(self, instance):
318 60af751d Andrea Spadaccini
    """Clean-up after a migration.
319 60af751d Andrea Spadaccini

320 60af751d Andrea Spadaccini
    To be executed on the source node.
321 60af751d Andrea Spadaccini

322 60af751d Andrea Spadaccini
    @type instance: L{objects.Instance}
323 60af751d Andrea Spadaccini
    @param instance: the instance that was migrated
324 60af751d Andrea Spadaccini

325 60af751d Andrea Spadaccini
    """
326 60af751d Andrea Spadaccini
    pass
327 60af751d Andrea Spadaccini
328 60af751d Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
329 60af751d Andrea Spadaccini
    """Finalize the instance migration on the source node.
330 60af751d Andrea Spadaccini

331 60af751d Andrea Spadaccini
    @type instance: L{objects.Instance}
332 60af751d Andrea Spadaccini
    @param instance: the instance that was migrated
333 60af751d Andrea Spadaccini
    @type success: bool
334 60af751d Andrea Spadaccini
    @param success: whether the migration succeeded or not
335 60af751d Andrea Spadaccini
    @type live: bool
336 60af751d Andrea Spadaccini
    @param live: whether the user requested a live migration or not
337 60af751d Andrea Spadaccini

338 60af751d Andrea Spadaccini
    """
339 60af751d Andrea Spadaccini
    # pylint: disable=W0613
340 60af751d Andrea Spadaccini
    if success:
341 60af751d Andrea Spadaccini
      self._MarkDown(instance.name)
342 60af751d Andrea Spadaccini
343 60af751d Andrea Spadaccini
  def GetMigrationStatus(self, instance):
344 60af751d Andrea Spadaccini
    """Get the migration status
345 60af751d Andrea Spadaccini

346 60af751d Andrea Spadaccini
    The fake hypervisor migration always succeeds.
347 60af751d Andrea Spadaccini

348 60af751d Andrea Spadaccini
    @type instance: L{objects.Instance}
349 60af751d Andrea Spadaccini
    @param instance: the instance that is being migrated
350 60af751d Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
351 60af751d Andrea Spadaccini
    @return: the status of the current migration (one of
352 60af751d Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
353 60af751d Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
354 60af751d Andrea Spadaccini

355 60af751d Andrea Spadaccini
    """
356 60af751d Andrea Spadaccini
    return objects.MigrationStatus(status=constants.HV_MIGRATION_COMPLETED)