1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
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
51
53 """Get the list of running instances.
54
55 """
56 return os.listdir(self._ROOT_DIR)
57
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
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
114 """Compute the instance file for an instance name.
115
116 """
117 return utils.PathJoin(cls._ROOT_DIR, instance_name)
118
120 """Checks if an instance is alive.
121
122 """
123 file_name = self._InstanceFile(instance_name)
124 return os.path.exists(file_name)
125
140
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
182 """Reboot an instance.
183
184 For the fake hypervisor, this does nothing.
185
186 """
187 return
188
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
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
216
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
229 """Fake hypervisor powercycle, just a wrapper over Linux powercycle.
230
231 """
232 cls.LinuxPowercycle()
233
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
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
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
277 self._MarkDown(instance.name)
278