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