Package ganeti :: Package hypervisor :: Module hv_fake
[hide private]
[frames] | no frames]

Source Code for Module ganeti.hypervisor.hv_fake

  1  # 
  2  # 
  3   
  4  # Copyright (C) 2006, 2007, 2008 Google Inc. 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify 
  7  # it under the terms of the GNU General Public License as published by 
  8  # the Free Software Foundation; either version 2 of the License, or 
  9  # (at your option) any later version. 
 10  # 
 11  # This program is distributed in the hope that it will be useful, but 
 12  # WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 14  # General Public License for more details. 
 15  # 
 16  # You should have received a copy of the GNU General Public License 
 17  # along with this program; if not, write to the Free Software 
 18  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
 19  # 02110-1301, USA. 
 20   
 21   
 22  """Fake hypervisor 
 23   
 24  """ 
 25   
 26  import os 
 27  import os.path 
 28  import logging 
 29   
 30  from ganeti import utils 
 31  from ganeti import constants 
 32  from ganeti import errors 
 33  from ganeti import objects 
 34  from ganeti.hypervisor import hv_base 
35 36 37 -class FakeHypervisor(hv_base.BaseHypervisor):
38 """Fake hypervisor interface. 39 40 This can be used for testing the ganeti code without having to have 41 a real virtualisation software installed. 42 43 """ 44 CAN_MIGRATE = True 45 46 _ROOT_DIR = constants.RUN_GANETI_DIR + "/fake-hypervisor" 47
48 - def __init__(self):
51
52 - def ListInstances(self):
53 """Get the list of running instances. 54 55 """ 56 return os.listdir(self._ROOT_DIR)
57
58 - def GetInstanceInfo(self, instance_name):
59 """Get instance properties. 60 61 @param instance_name: the instance name 62 63 @return: tuple of (name, id, memory, vcpus, stat, times) 64 65 """ 66 file_name = self._InstanceFile(instance_name) 67 if not os.path.exists(file_name): 68 return None 69 try: 70 fh = open(file_name, "r") 71 try: 72 inst_id = fh.readline().strip() 73 memory = utils.TryConvert(int, fh.readline().strip()) 74 vcpus = utils.TryConvert(int, fh.readline().strip()) 75 stat = "---b-" 76 times = "0" 77 return (instance_name, inst_id, memory, vcpus, stat, times) 78 finally: 79 fh.close() 80 except IOError, err: 81 raise errors.HypervisorError("Failed to list instance %s: %s" % 82 (instance_name, err))
83
84 - def GetAllInstancesInfo(self):
85 """Get properties of all instances. 86 87 @return: list of tuples (name, id, memory, vcpus, stat, times) 88 89 """ 90 data = [] 91 for file_name in os.listdir(self._ROOT_DIR): 92 try: 93 fh = open(utils.PathJoin(self._ROOT_DIR, file_name), "r") 94 inst_id = "-1" 95 memory = 0 96 vcpus = 1 97 stat = "-----" 98 times = "-1" 99 try: 100 inst_id = fh.readline().strip() 101 memory = utils.TryConvert(int, fh.readline().strip()) 102 vcpus = utils.TryConvert(int, fh.readline().strip()) 103 stat = "---b-" 104 times = "0" 105 finally: 106 fh.close() 107 data.append((file_name, inst_id, memory, vcpus, stat, times)) 108 except IOError, err: 109 raise errors.HypervisorError("Failed to list instances: %s" % err) 110 return data
111 112 @classmethod
113 - def _InstanceFile(cls, instance_name):
114 """Compute the instance file for an instance name. 115 116 """ 117 return utils.PathJoin(cls._ROOT_DIR, instance_name)
118
119 - def _IsAlive(self, instance_name):
120 """Checks if an instance is alive. 121 122 """ 123 file_name = self._InstanceFile(instance_name) 124 return os.path.exists(file_name)
125
126 - def _MarkUp(self, instance):
127 """Mark the instance as running. 128 129 This does no checks, which should be done by its callers. 130 131 """ 132 file_name = self._InstanceFile(instance.name) 133 fh = file(file_name, "w") 134 try: 135 fh.write("0\n%d\n%d\n" % 136 (instance.beparams[constants.BE_MEMORY], 137 instance.beparams[constants.BE_VCPUS])) 138 finally: 139 fh.close()
140
141 - def _MarkDown(self, instance_name):
142 """Mark the instance as running. 143 144 This does no checks, which should be done by its callers. 145 146 """ 147 file_name = self._InstanceFile(instance_name) 148 utils.RemoveFile(file_name)
149
150 - def StartInstance(self, instance, block_devices, startup_paused):
151 """Start an instance. 152 153 For the fake hypervisor, it just creates a file in the base dir, 154 creating an exception if it already exists. We don't actually 155 handle race conditions properly, since these are *FAKE* instances. 156 157 """ 158 if self._IsAlive(instance.name): 159 raise errors.HypervisorError("Failed to start instance %s: %s" % 160 (instance.name, "already running")) 161 try: 162 self._MarkUp(instance) 163 except IOError, err: 164 raise errors.HypervisorError("Failed to start instance %s: %s" % 165 (instance.name, err))
166
167 - def StopInstance(self, instance, force=False, retry=False, name=None):
168 """Stop an instance. 169 170 For the fake hypervisor, this just removes the file in the base 171 dir, if it exist, otherwise we raise an exception. 172 173 """ 174 if name is None: 175 name = instance.name 176 if not self._IsAlive(name): 177 raise errors.HypervisorError("Failed to stop instance %s: %s" % 178 (name, "not running")) 179 self._MarkDown(name)
180
181 - def RebootInstance(self, instance):
182 """Reboot an instance. 183 184 For the fake hypervisor, this does nothing. 185 186 """ 187 return
188
189 - def GetNodeInfo(self):
190 """Return information about the node. 191 192 This is just a wrapper over the base GetLinuxNodeInfo method. 193 194 @return: a dict with the following keys (values in MiB): 195 - memory_total: the total memory size on the node 196 - memory_free: the available memory on the node for instances 197 - memory_dom0: the memory used by the node itself, if available 198 199 """ 200 result = self.GetLinuxNodeInfo() 201 # substract running instances 202 all_instances = self.GetAllInstancesInfo() 203 result["memory_free"] -= min(result["memory_free"], 204 sum([row[2] for row in all_instances])) 205 return result
206 207 @classmethod
208 - def GetInstanceConsole(cls, instance, hvparams, beparams):
209 """Return information for connecting to the console of an instance. 210 211 """ 212 return objects.InstanceConsole(instance=instance.name, 213 kind=constants.CONS_MESSAGE, 214 message=("Console not available for fake" 215 " hypervisor"))
216
217 - def Verify(self):
218 """Verify the hypervisor. 219 220 For the fake hypervisor, it just checks the existence of the base 221 dir. 222 223 """ 224 if not os.path.exists(self._ROOT_DIR): 225 return "The required directory '%s' does not exist." % self._ROOT_DIR
226 227 @classmethod
228 - def PowercycleNode(cls):
229 """Fake hypervisor powercycle, just a wrapper over Linux powercycle. 230 231 """ 232 cls.LinuxPowercycle()
233
234 - def AcceptInstance(self, instance, info, target):
235 """Prepare to accept an instance. 236 237 @type instance: L{objects.Instance} 238 @param instance: instance to be accepted 239 @type info: string 240 @param info: instance info, not used 241 @type target: string 242 @param target: target host (usually ip), on this node 243 244 """ 245 if self._IsAlive(instance.name): 246 raise errors.HypervisorError("Can't accept instance, already running")
247
248 - def MigrateInstance(self, instance, target, live):
249 """Migrate an instance. 250 251 @type instance: L{objects.Instance} 252 @param instance: the instance to be migrated 253 @type target: string 254 @param target: hostname (usually ip) of the target node 255 @type live: boolean 256 @param live: whether to do a live or non-live migration 257 258 """ 259 logging.debug("Fake hypervisor migrating %s to %s (live=%s)", 260 instance, target, live) 261 262 self._MarkDown(instance.name)
263
264 - def FinalizeMigration(self, instance, info, success):
265 """Finalize an instance migration. 266 267 For the fake hv, this just marks the instance up. 268 269 @type instance: L{objects.Instance} 270 @param instance: instance whose migration is being finalized 271 272 """ 273 if success: 274 self._MarkUp(instance) 275 else: 276 # ensure it's down 277 self._MarkDown(instance.name)
278