Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_fake.py @ 98c98ab9

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

210 65a6f9b7 Michael Hanselmann
    """
211 65a6f9b7 Michael Hanselmann
    return "echo Console not available for fake hypervisor"
212 65a6f9b7 Michael Hanselmann
213 65a6f9b7 Michael Hanselmann
  def Verify(self):
214 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
215 65a6f9b7 Michael Hanselmann

216 65a6f9b7 Michael Hanselmann
    For the fake hypervisor, it just checks the existence of the base
217 65a6f9b7 Michael Hanselmann
    dir.
218 65a6f9b7 Michael Hanselmann

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

227 f5118ade Iustin Pop
    """
228 f5118ade Iustin Pop
    cls.LinuxPowercycle()
229 94fed7da Iustin Pop
230 94fed7da Iustin Pop
  def AcceptInstance(self, instance, info, target):
231 94fed7da Iustin Pop
    """Prepare to accept an instance.
232 94fed7da Iustin Pop

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

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

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

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

263 94fed7da Iustin Pop
    For the fake hv, this just marks the instance up.
264 94fed7da Iustin Pop

265 94fed7da Iustin Pop
    @type instance: L{objects.Instance}
266 94fed7da Iustin Pop
    @param instance: instance whose migration is being finalized
267 94fed7da Iustin Pop

268 94fed7da Iustin Pop
    """
269 94fed7da Iustin Pop
    if success:
270 94fed7da Iustin Pop
      self._MarkUp(instance)
271 94fed7da Iustin Pop
    else:
272 94fed7da Iustin Pop
      # ensure it's down
273 bbcf7ad0 Iustin Pop
      self._MarkDown(instance.name)