Merge lp:~fwereade/pyjuju/cobbler-shutdown into lp:pyjuju

Proposed by William Reade
Status: Merged
Approved by: Kapil Thangavelu
Approved revision: 334
Merged at revision: 325
Proposed branch: lp:~fwereade/pyjuju/cobbler-shutdown
Merge into: lp:pyjuju
Prerequisite: lp:~fwereade/pyjuju/provider-base
Diff against target: 1578 lines (+719/-379)
14 files modified
ensemble/providers/common/base.py (+15/-9)
ensemble/providers/common/tests/test_base.py (+10/-3)
ensemble/providers/dummy.py (+8/-4)
ensemble/providers/ec2/__init__.py (+14/-7)
ensemble/providers/ec2/tests/test_shutdown.py (+56/-35)
ensemble/providers/orchestra/__init__.py (+23/-1)
ensemble/providers/orchestra/cobbler.py (+23/-15)
ensemble/providers/orchestra/launch.py (+1/-1)
ensemble/providers/orchestra/tests/common.py (+0/-6)
ensemble/providers/orchestra/tests/test_bootstrap.py (+5/-1)
ensemble/providers/orchestra/tests/test_cobbler.py (+362/-295)
ensemble/providers/orchestra/tests/test_getmachines.py (+0/-1)
ensemble/providers/orchestra/tests/test_launch.py (+7/-1)
ensemble/providers/orchestra/tests/test_shutdown.py (+195/-0)
To merge this branch: bzr merge lp:~fwereade/pyjuju/cobbler-shutdown
Reviewer Review Type Date Requested Status
Kapil Thangavelu (community) Approve
Gustavo Niemeyer Approve
Review via email: mp+71391@code.launchpad.net

Description of the change

destroy_environment now attempts to clear state before killing machines; if it doesn't manage, it ignores the error and kills the machines regardless.

orchestra provider now has a shutdown_machines method, and hence shutdown_machine and destroy_environment.

To post a comment you must log in.
Revision history for this message
William Reade (fwereade) wrote :
lp:~fwereade/pyjuju/cobbler-shutdown updated
328. By William Reade

fix base interface, docstring for shutdown_machines

329. By William Reade

merge parent

Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :

Very nice branch too. Only a few simple things, and +1.

[1]

- def shutdown_machines(self, requested_machines=()):
+ def shutdown_machines(self, requested_machines):

Woohay. :-)

[2]

+ try:
+ yield self.save_state({})
+ except Exception as error:
+ # failing to clear state is a bit bad; failing to kill
+ # the machines would be *really* bad
+ log.error("Failed to clear provider state: %s", error)
+ live_machines = yield self.get_machines()
+ killed_machines = yield self.shutdown_machines(live_machines)

The try/except above will eat NameErrors and the such blindly and
unnecessarily. This can easily try/finally instead:

   try:
       yield self.save_state({})
   finally:
       live_machines = yield self.get_machines()
       killed_machines = yield self.shutdown_machines(live_machines)

[3]

+ @inlineCallbacks
     def destroy_environment(self):
     - return self.shutdown_machines()
     + machines = yield self.get_machines()
     + yield self.shutdown_machines(machines)
     + returnValue(machines)

This looks naturally structured for callbacks (at last!):

d = self.get_machines()
d.addCallback(self.shutdown_machines)
return d

[4]

+ def shutdown_machines(self, requested_machines):
         """Terminate machine resources associated with this provider."""
+ if not requested_machines:
+ returnValue(requested_machines)

s/requested_// would go well here too.

returnValue([]) feels more readable as well, and slightly less error
prone (lists are mutable).

[5]

Same as above for Orchestra version.

[6]

+class StartSystemTest(CobblerClientTestCase, PowerTestsMixin):
+
+ desired_state = "on"
+ method_name = "start_system"
+
+
+class StopSystemTest(CobblerClientTestCase, PowerTestsMixin):
+
+ desired_state = "off"
+ method_name = "stop_system"

Interesting design.

[7]

    def describe_systems(self, *instance_ids):
(...)
+ def shutdown_machines(self, machines):

We have an inconsistency in calling conventions here. Please don't
fix in this branch, but a good candidate for a small trivial branch
later.

review: Approve
lp:~fwereade/pyjuju/cobbler-shutdown updated
330. By William Reade

fixes per review

331. By William Reade

merge parent

Revision history for this message
William Reade (fwereade) wrote :

> [1]

Yeehaw!

> [2]

Good point :)

> [3]
> This looks naturally structured for callbacks (at last!):

It would be, if I hadn't forgotten to call save_state :/. Fixed now.

> [4,5]
> s/requested_// would go well here too.
>
> returnValue([]) feels more readable as well, and slightly less error
> prone (lists are mutable).

Both fixed.

> [6]
> Interesting design.

They're so similar, it seemed a shame to duplicate the effort :). I doubt they'll stay so perfectly similar forever, but for now I think it's a win.

> [7]

Filed lp:827994

lp:~fwereade/pyjuju/cobbler-shutdown updated
332. By William Reade

merge trunk

Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :

LGTM

lp:~fwereade/pyjuju/cobbler-shutdown updated
333. By William Reade

merge trunk

334. By William Reade

merge trunk

Revision history for this message
Kapil Thangavelu (hazmat) wrote :

[0] Branch implementation looks very clean, and with good testing, nice.

[1] Pep 8 cleanups
 https://pastebin.canonical.com/51598/

review: Approve
lp:~fwereade/pyjuju/cobbler-shutdown updated
335. By William Reade

pep8 re review

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ensemble/providers/common/base.py'
2--- ensemble/providers/common/base.py 2011-08-17 12:04:56 +0000
3+++ ensemble/providers/common/base.py 2011-08-23 21:41:27 +0000
4@@ -1,11 +1,13 @@
5 import copy
6 from operator import itemgetter
7
8+from twisted.internet.defer import inlineCallbacks, returnValue
9+
10 from ensemble.environment.errors import EnvironmentsConfigError
11-from ensemble.providers.common.bootstrap import Bootstrap
12-from ensemble.providers.common.findzookeepers import find_zookeepers
13-from ensemble.providers.common.state import SaveState, LoadState
14-from ensemble.providers.common.utils import get_user_authorized_keys
15+from .bootstrap import Bootstrap
16+from .findzookeepers import find_zookeepers
17+from .state import SaveState, LoadState
18+from .utils import get_user_authorized_keys
19
20
21 class MachineProviderBase(object):
22@@ -93,11 +95,10 @@
23 """
24 raise NotImplementedError()
25
26- def shutdown_machines(self, requested_machines=()):
27+ def shutdown_machines(self, machines):
28 """Terminate machines associated with this provider.
29
30- @param requested_machines: list of machines to shut down; leave
31- empty to shut down all associated machines.
32+ @param machines: list of machines to shut down
33 """
34 raise NotImplementedError()
35
36@@ -152,9 +153,15 @@
37 d.addCallback(itemgetter(0))
38 return d
39
40+ @inlineCallbacks
41 def destroy_environment(self):
42 """Clear ensemble state and terminate all associated machines"""
43- return self.shutdown_machines()
44+ try:
45+ yield self.save_state({})
46+ finally:
47+ live_machines = yield self.get_machines()
48+ killed_machines = yield self.shutdown_machines(live_machines)
49+ returnValue(killed_machines)
50
51 def save_state(self, state):
52 """Save state to the provider.
53@@ -170,4 +177,3 @@
54 @return: a dictionary.
55 """
56 return LoadState(self).run()
57-
58
59=== modified file 'ensemble/providers/common/tests/test_base.py'
60--- ensemble/providers/common/tests/test_base.py 2011-08-17 12:04:56 +0000
61+++ ensemble/providers/common/tests/test_base.py 2011-08-23 21:41:27 +0000
62@@ -110,8 +110,12 @@
63
64 def test_destroy_environment_error(self):
65 provider = DummyProvider()
66+ provider.get_machines = self.mocker.mock()
67+ provider.get_machines()
68+ machines = [object(), object()]
69+ self.mocker.result(succeed(machines))
70 provider.shutdown_machines = self.mocker.mock()
71- provider.shutdown_machines()
72+ provider.shutdown_machines(machines)
73 self.mocker.result(fail(SomeError()))
74 self.mocker.replay()
75
76@@ -121,9 +125,12 @@
77
78 def test_destroy_environment_success(self):
79 provider = DummyProvider()
80+ provider.get_machines = self.mocker.mock()
81+ provider.get_machines()
82+ machines = [object(), object()]
83+ self.mocker.result(succeed(machines))
84 provider.shutdown_machines = self.mocker.mock()
85- provider.shutdown_machines()
86- machines = object()
87+ provider.shutdown_machines(machines)
88 self.mocker.result(succeed(machines))
89 self.mocker.replay()
90
91
92=== modified file 'ensemble/providers/dummy.py'
93--- ensemble/providers/dummy.py 2011-08-22 23:03:03 +0000
94+++ ensemble/providers/dummy.py 2011-08-23 21:41:27 +0000
95@@ -85,11 +85,11 @@
96 return self.start_machine({"machine-id": 0})
97
98 @inlineCallbacks
99- def shutdown_machines(self, requested_machines=()):
100+ def shutdown_machines(self, machines):
101 """
102 Terminate any machine resources associated to the provider.
103 """
104- instance_ids = [m.instance_id for m in requested_machines]
105+ instance_ids = [m.instance_id for m in machines]
106 machines = yield self.get_machines(instance_ids)
107 for machine in machines:
108 self._machines.remove(machine)
109@@ -102,11 +102,15 @@
110 for m in self._machines:
111 if m.instance_id == machine.instance_id:
112 self._machines.remove(m)
113- return
114+ return m
115 return fail(ProviderError("Machine not found %r" % machine))
116
117+ @inlineCallbacks
118 def destroy_environment(self):
119- return self.shutdown_machines()
120+ yield self.save_state({})
121+ machines = yield self.get_machines()
122+ machines = yield self.shutdown_machines(machines)
123+ returnValue(machines)
124
125 def save_state(self, state):
126 """Save the state to the provider."""
127
128=== modified file 'ensemble/providers/ec2/__init__.py'
129--- ensemble/providers/ec2/__init__.py 2011-08-17 12:04:56 +0000
130+++ ensemble/providers/ec2/__init__.py 2011-08-23 21:41:27 +0000
131@@ -98,7 +98,8 @@
132 code = error.get_error_codes()
133 if code == "InvalidInstanceID.NotFound":
134 message = error.get_error_messages()
135- raise MachinesNotFound(re.findall(r"\bi-[0-9a-f]{3,15}\b", message))
136+ raise MachinesNotFound(
137+ re.findall(r"\bi-[0-9a-f]{3,15}\b", message))
138 raise ProviderInteractionError(
139 "EC2 error when looking up instances %s: %s"
140 % (", ".join(instance_ids), error.get_error_messages()))
141@@ -121,19 +122,25 @@
142 returnValue(machines)
143
144 @inlineCallbacks
145- def shutdown_machines(self, requested_machines=()):
146- """Terminate machine resources associated with this provider."""
147- for machine in requested_machines:
148+ def shutdown_machines(self, machines):
149+ """Terminate machines associated with this provider.
150+
151+ @param machines: list of machines to shut down
152+ """
153+ if not machines:
154+ returnValue([])
155+
156+ for machine in machines:
157 if not isinstance(machine, EC2ProviderMachine):
158 raise ProviderError("Can only shut down EC2ProviderMachines; "
159 "got a %r" % type(machine))
160
161- requested_ids = [m.instance_id for m in requested_machines]
162- killable_machines = yield self.get_machines(requested_ids)
163+ ids = [m.instance_id for m in machines]
164+ killable_machines = yield self.get_machines(ids)
165 if killable_machines:
166 killable_ids = [m.instance_id for m in killable_machines]
167 yield self.ec2.terminate_instances(*killable_ids)
168- returnValue(killable_machines)
169+ returnValue(killable_machines)
170
171 def open_port(self, machine, machine_id, port, protocol="tcp"):
172 """Authorizes `port` using `protocol` on EC2 for `machine`."""
173
174=== modified file 'ensemble/providers/ec2/tests/test_shutdown.py'
175--- ensemble/providers/ec2/tests/test_shutdown.py 2011-08-12 21:22:07 +0000
176+++ ensemble/providers/ec2/tests/test_shutdown.py 2011-08-23 21:41:27 +0000
177@@ -1,4 +1,4 @@
178-from twisted.internet.defer import succeed
179+from twisted.internet.defer import fail, succeed
180
181 from ensemble.lib.testing import TestCase
182 from ensemble.providers.ec2.tests.common import EC2TestMixin
183@@ -9,6 +9,10 @@
184 from ensemble.providers.ec2.machine import EC2ProviderMachine
185
186
187+class SomeError(Exception):
188+ pass
189+
190+
191 class EC2ShutdownMachineTest(EC2TestMixin, TestCase):
192
193 def test_shutdown_machine(self):
194@@ -67,47 +71,34 @@
195 d.addCallback(check_error)
196 return d
197
198- def test_shutdown_machines_all(self):
199- self.ec2.describe_instances()
200+ def test_shutdown_machines_none(self):
201+ self.mocker.replay()
202+ provider = self.get_provider()
203+ d = provider.shutdown_machines([])
204+
205+ def verify(result):
206+ self.assertEquals(result, [])
207+ d.addCallback(verify)
208+ return d
209+
210+ def test_shutdown_machines_some_invalid(self):
211+ self.ec2.describe_instances("i-amkillable", "i-amalien", "i-amdead")
212 self.mocker.result(succeed([
213 self.get_instance("i-amkillable"),
214- self.get_instance("i-amdead", "shutting-down"),
215 self.get_instance("i-amalien", groups=["other"]),
216- self.get_instance("i-amkillabletoo")]))
217- self.ec2.terminate_instances("i-amkillable", "i-amkillabletoo")
218- self.mocker.result(succeed([
219- ("i-amkillable", "running", "shutting-down"),
220- ("i-amkillabletoo", "running", "shutting-down")]))
221- self.mocker.replay()
222-
223- provider = self.get_provider()
224- d = provider.shutdown_machines()
225-
226- def verify(result):
227- (machine_1, machine_2) = result
228- self.assertTrue(isinstance(machine_1, EC2ProviderMachine))
229- self.assertEquals(machine_1.instance_id, "i-amkillable")
230- self.assertTrue(isinstance(machine_2, EC2ProviderMachine))
231- self.assertEquals(machine_2.instance_id, "i-amkillabletoo")
232- d.addCallback(verify)
233- return d
234-
235- def test_shutdown_machines_some_invalid(self):
236- self.ec2.describe_instances("i-amkillable", "i-amdead")
237- self.mocker.result(succeed([
238- self.get_instance("i-amkillable"),
239 self.get_instance("i-amdead", "shutting-down")]))
240 self.mocker.replay()
241
242 provider = self.get_provider()
243 d = provider.shutdown_machines([
244 EC2ProviderMachine("i-amkillable"),
245+ EC2ProviderMachine("i-amalien"),
246 EC2ProviderMachine("i-amdead")])
247 self.failUnlessFailure(d, MachinesNotFound)
248
249 def verify(error):
250 self.assertEquals(str(error),
251- "Cannot find machine: i-amdead")
252+ "Cannot find machines: i-amalien, i-amdead")
253 d.addCallback(verify)
254 return d
255
256@@ -144,13 +135,18 @@
257 The destroy_environment operation terminates all running and pending
258 instances associated to the C{MachineProvider} instance.
259 """
260- instances = [self.get_instance("i-canbekilled"),
261- self.get_instance("i-amdead", state="terminated"),
262- self.get_instance("i-dontbelong", groups=["unknown"]),
263- self.get_instance("i-canbekilledtoo", state="pending")]
264-
265+ self.s3.put_object("moon", "provider-state", "{}\n")
266+ self.mocker.result(succeed(None))
267 self.ec2.describe_instances()
268- self.mocker.result(succeed(instances))
269+ self.mocker.result(succeed([
270+ self.get_instance("i-canbekilled"),
271+ self.get_instance("i-amdead", state="terminated"),
272+ self.get_instance("i-dontbelong", groups=["unknown"]),
273+ self.get_instance("i-canbekilledtoo", state="pending")]))
274+ self.ec2.describe_instances("i-canbekilled", "i-canbekilledtoo")
275+ self.mocker.result(succeed([
276+ self.get_instance("i-canbekilled"),
277+ self.get_instance("i-canbekilledtoo", state="pending")]))
278 self.ec2.terminate_instances("i-canbekilled", "i-canbekilledtoo")
279 self.mocker.result(succeed([
280 ("i-canbekilled", "running", "shutting-down"),
281@@ -169,11 +165,36 @@
282 d.addCallback(verify)
283 return d
284
285+ def test_s3_failure(self):
286+ """Failing to store empty state should not stop us killing machines"""
287+ self.s3.put_object("moon", "provider-state", "{}\n")
288+ self.mocker.result(fail(SomeError()))
289+ self.ec2.describe_instances()
290+ self.mocker.result(succeed([self.get_instance("i-canbekilled")]))
291+ self.ec2.describe_instances("i-canbekilled")
292+ self.mocker.result(succeed([self.get_instance("i-canbekilled")]))
293+ self.ec2.terminate_instances("i-canbekilled")
294+ self.mocker.result(succeed([
295+ ("i-canbekilled", "running", "shutting-down")]))
296+ self.mocker.replay()
297+
298+ provider = self.get_provider()
299+ d = provider.destroy_environment()
300+
301+ def verify(result):
302+ (machine,) = result
303+ self.assertTrue(isinstance(machine, EC2ProviderMachine))
304+ self.assertEquals(machine.instance_id, "i-canbekilled")
305+ d.addCallback(verify)
306+ return d
307+
308 def test_shutdown_no_instances(self):
309 """
310 If there are no instances to shutdown, running the destroy_environment
311 operation does nothing.
312 """
313+ self.s3.put_object("moon", "provider-state", "{}\n")
314+ self.mocker.result(succeed(None))
315 self.ec2.describe_instances()
316 self.mocker.result(succeed([]))
317 self.mocker.replay()
318@@ -182,6 +203,6 @@
319 d = provider.destroy_environment()
320
321 def verify(result):
322- self.assertEquals(result, None)
323+ self.assertEquals(result, [])
324 d.addCallback(verify)
325 return d
326
327=== modified file 'ensemble/providers/orchestra/__init__.py'
328--- ensemble/providers/orchestra/__init__.py 2011-08-17 12:04:56 +0000
329+++ ensemble/providers/orchestra/__init__.py 2011-08-23 21:41:27 +0000
330@@ -1,11 +1,12 @@
331 from twisted.internet.defer import inlineCallbacks, returnValue
332
333+from ensemble.errors import ProviderError
334 from ensemble.providers.common.base import MachineProviderBase
335
336 from .cobbler import CobblerClient
337 from .files import FileStorage
338 from .launch import OrchestraLaunchMachine
339-from .machine import machine_from_dict
340+from .machine import machine_from_dict, OrchestraMachine
341
342
343 class MachineProvider(MachineProviderBase):
344@@ -45,3 +46,24 @@
345 """
346 instances = yield self.cobbler.describe_systems(*instance_ids)
347 returnValue([machine_from_dict(i) for i in instances])
348+
349+ @inlineCallbacks
350+ def shutdown_machines(self, machines):
351+ """Terminate machines associated with this provider.
352+
353+ @param machines: list of machines to shut down
354+ """
355+ if not machines:
356+ returnValue([])
357+
358+ for machine in machines:
359+ if not isinstance(machine, OrchestraMachine):
360+ raise ProviderError("Can only shut down OrchestraMachines; "
361+ "got a %r" % type(machine))
362+
363+ ids = [m.instance_id for m in machines]
364+ killable_machines = yield self.get_machines(ids)
365+ for machine in killable_machines:
366+ yield self.cobbler.stop_system(machine.instance_id)
367+ yield self.cobbler.release_system(machine.instance_id)
368+ returnValue(killable_machines)
369
370=== modified file 'ensemble/providers/orchestra/cobbler.py'
371--- ensemble/providers/orchestra/cobbler.py 2011-08-19 19:43:33 +0000
372+++ ensemble/providers/orchestra/cobbler.py 2011-08-23 21:41:27 +0000
373@@ -121,10 +121,13 @@
374 def _class_swapper(self, class_):
375 if class_ == self._available_class:
376 return self._acquired_class
377+ if class_ == self._acquired_class:
378+ return self._available_class
379 return class_
380
381 @inlineCallbacks
382 def _get_available_system(self):
383+ # TODO it would be simpler just to use get_systems here...
384 names = yield self._caller.call(
385 "find_system", ({"mgmt_classes": self._available_class,
386 "netboot_enabled": "true"},))
387@@ -164,18 +167,12 @@
388 returnValue(instance_id)
389
390 @inlineCallbacks
391- def describe_system(self, instance_id):
392- """Get all available information about a system.
393-
394- @return: a dictionary
395-
396- @raise: MachinesNotFound if the machine doesn't exist
397- """
398- name = yield self._get_name(instance_id)
399- info = yield self._caller.call("get_system", (name,))
400- if info == "~":
401- raise MachinesNotFound([instance_id])
402- returnValue(info)
403+ def release_system(self, instance_id):
404+ """Take a system marked as acquired, and make it available again"""
405+ (system,) = yield self.describe_systems(instance_id)
406+ new_classes = map(self._class_swapper, system["mgmt_classes"])
407+ yield self.set_on_system(instance_id, "mgmt_classes", new_classes)
408+ returnValue(True)
409
410 @inlineCallbacks
411 def describe_systems(self, *instance_ids):
412@@ -204,10 +201,21 @@
413 raise MachinesNotFound(missing_instance_ids)
414 returnValue(result_systems)
415
416+ def _power_call(self, operation, names):
417+ return self._caller.call("background_power_system",
418+ ({"power": operation, "systems": names},),
419+ auth=True)
420 @inlineCallbacks
421 def start_system(self, instance_id):
422 """Launch a cobbler system."""
423 name = yield self.set_on_system(instance_id, "netboot_enabled", True)
424- yield self._caller.call("background_power_system",
425- ({"power": "on", "systems": [name]},),
426- auth=True)
427+ yield self._power_call("on", [name])
428+
429+ @inlineCallbacks
430+ def stop_system(self, instance_id):
431+ """Shut down a cobbler system.
432+
433+ Also reenables netboot for next time.
434+ """
435+ name = yield self.set_on_system(instance_id, "netboot_enabled", True)
436+ yield self._power_call("off", [name])
437
438=== modified file 'ensemble/providers/orchestra/launch.py'
439--- ensemble/providers/orchestra/launch.py 2011-08-10 18:16:51 +0000
440+++ ensemble/providers/orchestra/launch.py 2011-08-23 21:41:27 +0000
441@@ -68,7 +68,7 @@
442 ks_meta = self._build_ks_meta(instance_id, variables)
443 yield cobbler.set_on_system(instance_id, "ks_meta", ks_meta)
444 yield cobbler.start_system(instance_id)
445- info = yield cobbler.describe_system(instance_id)
446+ (info,) = yield cobbler.describe_systems(instance_id)
447 returnValue([machine_from_dict(info)])
448
449 def get_instance_id_command(self):
450
451=== modified file 'ensemble/providers/orchestra/tests/common.py'
452--- ensemble/providers/orchestra/tests/common.py 2011-08-11 05:59:30 +0000
453+++ ensemble/providers/orchestra/tests/common.py 2011-08-23 21:41:27 +0000
454@@ -150,12 +150,6 @@
455 "TOKEN")
456 self.mocker.result(succeed("[some-timestamp]_power"))
457
458- def mock_describe_system(self, uid="winston-uid", name="winston"):
459- self.proxy_m.callRemote("find_system", {"uid": uid})
460- self.mocker.result(succeed([name]))
461- self.proxy_m.callRemote("get_system", name)
462- self.mocker.result(succeed({"name": name, "uid": uid}))
463-
464 def mock_describe_systems(self, result):
465 self.proxy_m.callRemote("get_systems")
466 self.mocker.result(result)
467
468=== modified file 'ensemble/providers/orchestra/tests/test_bootstrap.py'
469--- ensemble/providers/orchestra/tests/test_bootstrap.py 2011-08-11 05:59:30 +0000
470+++ ensemble/providers/orchestra/tests/test_bootstrap.py 2011-08-23 21:41:27 +0000
471@@ -87,7 +87,10 @@
472 self.mock_set_ks_meta(
473 self.get_verify_ks_meta(0, "bootstrap_late_command"))
474 self.mock_start_system()
475- self.mock_describe_system()
476+ self.mock_describe_systems(succeed([{
477+ "uid": "winston-uid",
478+ "name": "winston",
479+ "mgmt_classes": ["acquired"]}]))
480 self.mock_save_state()
481 self.mocker.replay()
482
483@@ -95,6 +98,7 @@
484 (machine,) = machines
485 self.assertTrue(isinstance(machine, OrchestraMachine))
486 self.assertEquals(machine.instance_id, "winston-uid")
487+ self.assertEquals(machine.dns_name, "winston")
488 d = self.get_provider().bootstrap()
489 d.addCallback(verify_machines)
490 return d
491
492=== modified file 'ensemble/providers/orchestra/tests/test_cobbler.py'
493--- ensemble/providers/orchestra/tests/test_cobbler.py 2011-08-12 19:28:37 +0000
494+++ ensemble/providers/orchestra/tests/test_cobbler.py 2011-08-23 21:41:27 +0000
495@@ -187,7 +187,7 @@
496 return d
497
498
499-class CobblerClientTest(TestCase):
500+class CobblerClientTestCase(TestCase):
501
502 def setup_mock(self):
503 self.proxy_m = self.mocker.mock(Proxy)
504@@ -221,19 +221,19 @@
505 "netboot_enabled": "true"})
506 self.mocker.result(result)
507
508- def mock_power_system(self, result):
509+ def mock_power_system(self, state, result):
510 self.proxy_m.callRemote("background_power_system",
511- {"power": "on", "systems": ["some-name"]}, "")
512+ {"power": state, "systems": ["some-name"]}, "")
513 self.mocker.result(result)
514
515 def mock_get_systems(self, result):
516 self.proxy_m.callRemote("get_systems")
517 self.mocker.result(result)
518
519- def call_cobbler_method(self, method_name, *args, **kwargs):
520+ def call_cobbler_method(self, method_name, *args):
521 cobbler = CobblerClient(_CONFIG)
522 method = getattr(cobbler, method_name)
523- return method(*args, **kwargs)
524+ return method(*args)
525
526 def check_not_found(self, d, uids=["some-uid"]):
527 self.assertFailure(d, MachinesNotFound)
528@@ -251,18 +251,16 @@
529 d.addCallback(verify)
530 return d
531
532- def check_get_name_failure(self, method_name, *args, **kwargs):
533- self.setup_mock()
534+ def check_get_name_failure(self, method_name, *args):
535 self.mock_get_name(succeed([]))
536 self.mocker.replay()
537- d = self.call_cobbler_method(method_name, *args, **kwargs)
538+ d = self.call_cobbler_method(method_name, *args)
539 return self.check_not_found(d)
540
541- def check_get_name_insane(self, method_name, *args, **kwargs):
542- self.setup_mock()
543+ def check_get_name_insane(self, method_name, *args):
544 self.mock_get_name(succeed(["some-name", "another-name"]))
545 self.mocker.replay()
546- d = self.call_cobbler_method(method_name, *args, **kwargs)
547+ d = self.call_cobbler_method(method_name, *args)
548 self.assertFailure(d, ProviderInteractionError)
549
550 def check_error(error):
551@@ -271,137 +269,127 @@
552 d.addCallback(check_error)
553 return d
554
555- def check_get_name_error(self, method_name, *args, **kwargs):
556- self.setup_mock()
557+ def check_get_name_error(self, method_name, *args):
558 self.mock_get_name(fail(SomeError()))
559 self.mocker.replay()
560- d = self.call_cobbler_method(method_name, *args, **kwargs)
561+ d = self.call_cobbler_method(method_name, *args)
562 self.assertFailure(d, SomeError)
563 return d
564
565- def test_describe_system_get_name_failure(self):
566- return self.check_get_name_failure("describe_system", "some-uid")
567-
568- def test_describe_system_get_name_insane(self):
569- return self.check_get_name_insane("describe_system", "some-uid")
570-
571- def test_describe_system_get_name_error(self):
572- return self.check_get_name_error("describe_system", "some-uid")
573-
574- def test_describe_system_get_system_failure(self):
575- self.setup_mock()
576- self.mock_get_name(succeed(["some-name"]))
577- self.mock_get_system(succeed("~"))
578+ def check_get_system_handle_failure(self, method_name, *args):
579+ self.mock_get_system_handle(fail(
580+ Fault("blah", "blah unknown system name blah")))
581 self.mocker.replay()
582- d = self.call_cobbler_method("describe_system", "some-uid")
583+ d = self.call_cobbler_method(method_name, *args)
584 return self.check_not_found(d)
585
586- def test_describe_system_get_system_error(self):
587- self.setup_mock()
588- self.mock_get_name(succeed(["some-name"]))
589- self.mock_get_system(fail(SomeError()))
590- self.mocker.replay()
591- d = self.call_cobbler_method("describe_system", "some-uid")
592- self.assertFailure(d, SomeError)
593- return d
594-
595- def test_describe_system_success(self):
596- self.setup_mock()
597- self.mock_get_name(succeed(["some-name"]))
598- self.mock_get_system(succeed(_SOME_SYSTEM))
599- self.mocker.replay()
600- d = self.call_cobbler_method("describe_system", "some-uid")
601-
602- def verify_info(info):
603- self.assertEquals(info, _SOME_SYSTEM)
604- d.addCallback(verify_info)
605- return d
606+ def check_get_system_handle_fault(self, method_name, *args):
607+ self.mock_get_system_handle(fail(Fault("blah", "blah")))
608+ self.mocker.replay()
609+ d = self.call_cobbler_method(method_name, *args)
610+ self.assertFailure(d, Fault)
611+ return d
612+
613+ def check_get_system_handle_error(self, method_name, *args):
614+ self.mock_get_system_handle(fail(SomeError()))
615+ self.mocker.replay()
616+ d = self.call_cobbler_method(method_name, *args)
617+ self.assertFailure(d, SomeError)
618+ return d
619+
620+ def check_modify_system_failure(self, key, value, method_name, *args):
621+ self.mock_modify_system(succeed(False), key, value)
622+ self.mocker.replay()
623+ d = self.call_cobbler_method(method_name, *args)
624+ return self.check_bad_call(d, "modify_system")
625+
626+ def check_modify_system_error(self, key, value, method_name, *args):
627+ self.mock_modify_system(fail(SomeError()), key, value)
628+ self.mocker.replay()
629+ d = self.call_cobbler_method(method_name, *args)
630+ self.assertFailure(d, SomeError)
631+ return d
632+
633+ def check_save_system_failure(self, method_name, *args):
634+ self.mock_save_system(succeed(False))
635+ self.mocker.replay()
636+ d = self.call_cobbler_method(method_name, *args)
637+ return self.check_bad_call(d, "save_system")
638+
639+ def check_save_system_error(self, method_name, *args):
640+ self.mock_save_system(fail(SomeError()))
641+ self.mocker.replay()
642+ d = self.call_cobbler_method(method_name, *args)
643+ self.assertFailure(d, SomeError)
644+ return d
645+
646+
647+class SetOnSystemTest(CobblerClientTestCase):
648
649 def test_set_on_system_get_name_failure(self):
650+ self.setup_mock()
651 return self.check_get_name_failure(
652 "set_on_system", "some-uid", "don't", "care")
653
654 def test_set_on_system_get_name_insane(self):
655+ self.setup_mock()
656 return self.check_get_name_insane(
657 "set_on_system", "some-uid", "don't", "care")
658
659 def test_set_on_system_get_name_error(self):
660+ self.setup_mock()
661 return self.check_get_name_error(
662 "set_on_system", "some-uid", "don't", "care")
663
664 def test_set_on_system_get_system_handle_failure(self):
665 self.setup_mock()
666 self.mock_get_name(succeed(["some-name"]))
667- self.mock_get_system_handle(fail(
668- Fault("blah", "blah unknown system name blah")))
669- self.mocker.replay()
670- d = self.call_cobbler_method(
671+ return self.check_get_system_handle_failure(
672 "set_on_system", "some-uid", "don't", "care")
673- return self.check_not_found(d)
674
675 def test_set_on_system_get_system_handle_unknown_fault(self):
676 self.setup_mock()
677 self.mock_get_name(succeed(["some-name"]))
678- self.mock_get_system_handle(fail(Fault("blah", "blah")))
679- self.mocker.replay()
680- d = self.call_cobbler_method(
681+ return self.check_get_system_handle_fault(
682 "set_on_system", "some-uid", "don't", "care")
683- self.assertFailure(d, Fault)
684- return d
685
686 def test_set_on_system_get_system_handle_error(self):
687 self.setup_mock()
688 self.mock_get_name(succeed(["some-name"]))
689- self.mock_get_system_handle(fail(SomeError()))
690- self.mocker.replay()
691- d = self.call_cobbler_method(
692+ return self.check_get_system_handle_error(
693 "set_on_system", "some-uid", "don't", "care")
694- self.assertFailure(d, SomeError)
695- return d
696
697 def test_set_on_system_modify_system_failure(self):
698 self.setup_mock()
699 self.mock_get_name(succeed(["some-name"]))
700 self.mock_get_system_handle(succeed("some-handle"))
701- self.mock_modify_system(succeed(False))
702- self.mocker.replay()
703- d = self.call_cobbler_method(
704+ return self.check_modify_system_failure(
705+ "some-key", "some-value",
706 "set_on_system", "some-uid", "some-key", "some-value")
707- return self.check_bad_call(d, "modify_system")
708
709 def test_set_on_system_modify_system_error(self):
710 self.setup_mock()
711 self.mock_get_name(succeed(["some-name"]))
712 self.mock_get_system_handle(succeed("some-handle"))
713- self.mock_modify_system(fail(SomeError()))
714- self.mocker.replay()
715- d = self.call_cobbler_method(
716+ return self.check_modify_system_error(
717+ "some-key", "some-value",
718 "set_on_system", "some-uid", "some-key", "some-value")
719- self.assertFailure(d, SomeError)
720- return d
721
722 def test_set_on_system_save_system_failure(self):
723 self.setup_mock()
724 self.mock_get_name(succeed(["some-name"]))
725 self.mock_get_system_handle(succeed("some-handle"))
726 self.mock_modify_system(succeed(True))
727- self.mock_save_system(succeed(False))
728- self.mocker.replay()
729- d = self.call_cobbler_method(
730+ return self.check_save_system_failure(
731 "set_on_system", "some-uid", "some-key", "some-value")
732- return self.check_bad_call(d, "save_system")
733
734 def test_set_on_system_save_system_error(self):
735 self.setup_mock()
736 self.mock_get_name(succeed(["some-name"]))
737 self.mock_get_system_handle(succeed("some-handle"))
738 self.mock_modify_system(succeed(True))
739- self.mock_save_system(fail(SomeError()))
740- self.mocker.replay()
741- d = self.call_cobbler_method(
742+ return self.check_save_system_error(
743 "set_on_system", "some-uid", "some-key", "some-value")
744- self.assertFailure(d, SomeError)
745- return d
746
747 def test_set_on_system_success(self):
748 self.setup_mock()
749@@ -418,7 +406,10 @@
750 d.addCallback(verify)
751 return d
752
753- def test_acquire_system_find_error(self):
754+
755+class AcquireSystemTest(CobblerClientTestCase):
756+
757+ def test_find_error(self):
758 self.setup_mock()
759 self.mock_find_system(fail(SomeError()))
760 self.mocker.replay()
761@@ -426,7 +417,7 @@
762 self.assertFailure(d, SomeError)
763 return d
764
765- def test_acquire_system_find_failure(self):
766+ def test_find_failure(self):
767 self.setup_mock()
768 self.mock_find_system(succeed([]))
769 self.mocker.replay()
770@@ -440,7 +431,7 @@
771 d.addCallback(verify)
772 return d
773
774- def test_acquire_system_get_error(self):
775+ def test_get_system_error(self):
776 self.setup_mock()
777 self.mock_find_system(succeed(["some-name", "other-name"]))
778 self.mock_get_system(fail(SomeError()))
779@@ -449,7 +440,7 @@
780 self.assertFailure(d, SomeError)
781 return d
782
783- def test_acquire_system_find_all_insane(self):
784+ def test_find_all_insane(self):
785 self.setup_mock()
786 self.mock_find_system(succeed(["some-name", "other-name"]))
787 self.mock_get_system(succeed(_crazy_system("some-uid")))
788@@ -466,119 +457,88 @@
789 d.addCallback(verify)
790 return d
791
792- def test_acquire_system_get_name_failure(self):
793- self.setup_mock()
794- self.mock_find_system(succeed(["some-name"]))
795- self.mock_get_system(succeed(_SOME_SYSTEM))
796- self.mock_get_name(succeed([]))
797- self.mocker.replay()
798- d = self.call_cobbler_method("acquire_system")
799- return self.check_not_found(d)
800-
801- def test_acquire_system_get_name_error(self):
802- self.setup_mock()
803- self.mock_find_system(succeed(["some-name"]))
804- self.mock_get_system(succeed(_SOME_SYSTEM))
805- self.mock_get_name(fail(SomeError()))
806- self.mocker.replay()
807- d = self.call_cobbler_method("acquire_system")
808- self.assertFailure(d, SomeError)
809- return d
810-
811- def test_acquire_system_get_system_handle_failure(self):
812- self.setup_mock()
813- self.mock_find_system(succeed(["some-name"]))
814- self.mock_get_system(succeed(_SOME_SYSTEM))
815- self.mock_get_name(succeed(["some-name"]))
816- self.mock_get_system_handle(fail(
817- Fault("blah", "blah unknown system name blah")))
818- self.mocker.replay()
819- d = self.call_cobbler_method("acquire_system")
820- return self.check_not_found(d)
821-
822- def test_acquire_system_get_system_handle_unknown_fault(self):
823- self.setup_mock()
824- self.mock_find_system(succeed(["some-name"]))
825- self.mock_get_system(succeed(_SOME_SYSTEM))
826- self.mock_get_name(succeed(["some-name"]))
827- self.mock_get_system_handle(fail(Fault("blah", "blah")))
828- self.mocker.replay()
829- d = self.call_cobbler_method("acquire_system")
830- self.assertFailure(d, Fault)
831- return d
832-
833- def test_acquire_system_get_system_handle_error(self):
834- self.setup_mock()
835- self.mock_find_system(succeed(["some-name"]))
836- self.mock_get_system(succeed(_SOME_SYSTEM))
837- self.mock_get_name(succeed(["some-name"]))
838- self.mock_get_system_handle(fail(SomeError()))
839- self.mocker.replay()
840- d = self.call_cobbler_method("acquire_system")
841- self.assertFailure(d, SomeError)
842- return d
843-
844- def test_acquire_system_modify_system_failure(self):
845- self.setup_mock()
846- self.mock_find_system(succeed(["some-name"]))
847- self.mock_get_system(succeed(_SOME_SYSTEM))
848- self.mock_get_name(succeed(["some-name"]))
849- self.mock_get_system_handle(succeed("some-handle"))
850- self.mock_modify_system(succeed(False),
851- "mgmt_classes", ["preserve_me", "acquired"])
852- self.mocker.replay()
853- d = self.call_cobbler_method("acquire_system")
854- return self.check_bad_call(d, "modify_system")
855-
856- def test_acquire_system_modify_system_error(self):
857- self.setup_mock()
858- self.mock_find_system(succeed(["some-name"]))
859- self.mock_get_system(succeed(_SOME_SYSTEM))
860- self.mock_get_name(succeed(["some-name"]))
861- self.mock_get_system_handle(succeed("some-handle"))
862- self.mock_modify_system(fail(SomeError()),
863- "mgmt_classes", ["preserve_me", "acquired"])
864- self.mocker.replay()
865- d = self.call_cobbler_method("acquire_system")
866- self.assertFailure(d, SomeError)
867- return d
868-
869- def test_acquire_system_save_system_failure(self):
870- self.setup_mock()
871- self.mock_find_system(succeed(["some-name"]))
872- self.mock_get_system(succeed(_SOME_SYSTEM))
873- self.mock_get_name(succeed(["some-name"]))
874- self.mock_get_system_handle(succeed("some-handle"))
875- self.mock_modify_system(succeed(True),
876- "mgmt_classes", ["preserve_me", "acquired"])
877- self.mock_save_system(succeed(False))
878- self.mocker.replay()
879- d = self.call_cobbler_method("acquire_system")
880- return self.check_bad_call(d, "save_system")
881-
882- def test_acquire_system_save_system_error(self):
883- self.setup_mock()
884- self.mock_find_system(succeed(["some-name"]))
885- self.mock_get_system(succeed(_SOME_SYSTEM))
886- self.mock_get_name(succeed(["some-name"]))
887- self.mock_get_system_handle(succeed("some-handle"))
888- self.mock_modify_system(succeed(True),
889- "mgmt_classes", ["preserve_me", "acquired"])
890- self.mock_save_system(fail(SomeError()))
891- self.mocker.replay()
892- d = self.call_cobbler_method("acquire_system")
893- self.assertFailure(d, SomeError)
894- return d
895-
896- def test_acquire_system_eventual_success(self):
897+ def test_get_name_failure(self):
898+ self.setup_mock()
899+ self.mock_find_system(succeed(["some-name"]))
900+ self.mock_get_system(succeed(_SOME_SYSTEM))
901+ return self.check_get_name_failure("acquire_system")
902+
903+ def test_get_name_error(self):
904+ self.setup_mock()
905+ self.mock_find_system(succeed(["some-name"]))
906+ self.mock_get_system(succeed(_SOME_SYSTEM))
907+ return self.check_get_name_error("acquire_system")
908+
909+ def test_get_system_handle_failure(self):
910+ self.setup_mock()
911+ self.mock_find_system(succeed(["some-name"]))
912+ self.mock_get_system(succeed(_SOME_SYSTEM))
913+ self.mock_get_name(succeed(["some-name"]))
914+ return self.check_get_system_handle_failure("acquire_system")
915+
916+ def test_get_system_handle_unknown_fault(self):
917+ self.setup_mock()
918+ self.mock_find_system(succeed(["some-name"]))
919+ self.mock_get_system(succeed(_SOME_SYSTEM))
920+ self.mock_get_name(succeed(["some-name"]))
921+ return self.check_get_system_handle_fault("acquire_system")
922+
923+ def test_get_system_handle_error(self):
924+ self.setup_mock()
925+ self.mock_find_system(succeed(["some-name"]))
926+ self.mock_get_system(succeed(_SOME_SYSTEM))
927+ self.mock_get_name(succeed(["some-name"]))
928+ return self.check_get_system_handle_error("acquire_system")
929+
930+ def test_modify_system_failure(self):
931+ self.setup_mock()
932+ self.mock_find_system(succeed(["some-name"]))
933+ self.mock_get_system(succeed(_SOME_SYSTEM))
934+ self.mock_get_name(succeed(["some-name"]))
935+ self.mock_get_system_handle(succeed("some-handle"))
936+ return self.check_modify_system_failure(
937+ "mgmt_classes", ["preserve_me", "acquired"],
938+ "acquire_system")
939+
940+ def test_modify_system_error(self):
941+ self.setup_mock()
942+ self.mock_find_system(succeed(["some-name"]))
943+ self.mock_get_system(succeed(_SOME_SYSTEM))
944+ self.mock_get_name(succeed(["some-name"]))
945+ self.mock_get_system_handle(succeed("some-handle"))
946+ return self.check_modify_system_error(
947+ "mgmt_classes", ["preserve_me", "acquired"],
948+ "acquire_system")
949+
950+ def test_save_system_failure(self):
951+ self.setup_mock()
952+ self.mock_find_system(succeed(["some-name"]))
953+ self.mock_get_system(succeed(_SOME_SYSTEM))
954+ self.mock_get_name(succeed(["some-name"]))
955+ self.mock_get_system_handle(succeed("some-handle"))
956+ self.mock_modify_system(
957+ succeed(True), "mgmt_classes", ["preserve_me", "acquired"])
958+ return self.check_save_system_failure("acquire_system")
959+
960+ def test_save_system_error(self):
961+ self.setup_mock()
962+ self.mock_find_system(succeed(["some-name"]))
963+ self.mock_get_system(succeed(_SOME_SYSTEM))
964+ self.mock_get_name(succeed(["some-name"]))
965+ self.mock_get_system_handle(succeed("some-handle"))
966+ self.mock_modify_system(
967+ succeed(True), "mgmt_classes", ["preserve_me", "acquired"])
968+ return self.check_save_system_error("acquire_system")
969+
970+ def test_eventual_success(self):
971 self.setup_mock()
972 self.mock_find_system(succeed(["bad-name", "some-name"]))
973 self.mock_get_system(succeed("~"), name="bad-name")
974 self.mock_get_system(succeed(_SOME_SYSTEM))
975 self.mock_get_name(succeed(["some-name"]))
976 self.mock_get_system_handle(succeed("some-handle"))
977- self.mock_modify_system(succeed(True),
978- "mgmt_classes", ["preserve_me", "acquired"])
979+ self.mock_modify_system(
980+ succeed(True), "mgmt_classes", ["preserve_me", "acquired"])
981 self.mock_save_system(succeed(True))
982 self.mocker.replay()
983 d = self.call_cobbler_method("acquire_system")
984@@ -588,106 +548,213 @@
985 d.addCallback(verify)
986 return d
987
988- def test_start_system_get_name_failure(self):
989- return self.check_get_name_failure("start_system", "some-uid")
990-
991- def test_start_system_get_name_insane(self):
992- return self.check_get_name_insane("start_system", "some-uid")
993-
994- def test_start_system_get_name_error(self):
995- return self.check_get_name_error("start_system", "some-uid")
996-
997- def test_start_system_get_system_handle_failure(self):
998- self.setup_mock()
999- self.mock_get_name(succeed(["some-name"]))
1000- self.mock_get_system_handle(fail(
1001- Fault("blah", "blah unknown system name blah")))
1002- self.mocker.replay()
1003- d = self.call_cobbler_method("start_system", "some-uid")
1004+
1005+class ReleaseSystemTest(CobblerClientTestCase):
1006+
1007+ def test_get_systems_error(self):
1008+ self.setup_mock()
1009+ self.mock_get_systems(fail(SomeError()))
1010+ self.mocker.replay()
1011+
1012+ d = self.call_cobbler_method("release_system", "some-uid")
1013+ self.assertFailure(d, SomeError)
1014+ return d
1015+
1016+ def test_get_systems_failure(self):
1017+ self.setup_mock()
1018+ self.mock_get_systems(succeed([]))
1019+ self.mocker.replay()
1020+
1021+ d = self.call_cobbler_method("release_system", "some-uid")
1022 return self.check_not_found(d)
1023
1024- def test_start_system_get_system_handle_unknown_fault(self):
1025- self.setup_mock()
1026- self.mock_get_name(succeed(["some-name"]))
1027- self.mock_get_system_handle(fail(Fault("blah", "blah")))
1028- self.mocker.replay()
1029- d = self.call_cobbler_method("start_system", "some-uid")
1030- self.assertFailure(d, Fault)
1031- return d
1032-
1033- def test_start_system_get_system_handle_error(self):
1034- self.setup_mock()
1035- self.mock_get_name(succeed(["some-name"]))
1036- self.mock_get_system_handle(fail(SomeError()))
1037- self.mocker.replay()
1038- d = self.call_cobbler_method("start_system", "some-uid")
1039- self.assertFailure(d, SomeError)
1040- return d
1041-
1042- def test_start_system_modify_system_failure(self):
1043- self.setup_mock()
1044- self.mock_get_name(succeed(["some-name"]))
1045- self.mock_get_system_handle(succeed("some-handle"))
1046- self.mock_modify_system(succeed(False), "netboot_enabled", True)
1047- self.mocker.replay()
1048- d = self.call_cobbler_method("start_system", "some-uid")
1049- return self.check_bad_call(d, "modify_system")
1050-
1051- def test_start_system_modify_system_error(self):
1052- self.setup_mock()
1053- self.mock_get_name(succeed(["some-name"]))
1054- self.mock_get_system_handle(succeed("some-handle"))
1055- self.mock_modify_system(fail(SomeError()), "netboot_enabled", True)
1056- self.mocker.replay()
1057- d = self.call_cobbler_method("start_system", "some-uid")
1058- self.assertFailure(d, SomeError)
1059- return d
1060-
1061- def test_start_system_save_system_failure(self):
1062- self.setup_mock()
1063- self.mock_get_name(succeed(["some-name"]))
1064- self.mock_get_system_handle(succeed("some-handle"))
1065- self.mock_modify_system(succeed(True), "netboot_enabled", True)
1066- self.mock_save_system(succeed(False))
1067- self.mocker.replay()
1068- d = self.call_cobbler_method("start_system", "some-uid")
1069- return self.check_bad_call(d, "save_system")
1070-
1071- def test_start_system_save_system_error(self):
1072- self.setup_mock()
1073- self.mock_get_name(succeed(["some-name"]))
1074- self.mock_get_system_handle(succeed("some-handle"))
1075- self.mock_modify_system(succeed(True), "netboot_enabled", True)
1076- self.mock_save_system(fail(SomeError()))
1077- self.mocker.replay()
1078- d = self.call_cobbler_method("start_system", "some-uid")
1079- self.assertFailure(d, SomeError)
1080- return d
1081-
1082- def test_start_system_power_error(self):
1083- self.setup_mock()
1084- self.mock_get_name(succeed(["some-name"]))
1085- self.mock_get_system_handle(succeed("some-handle"))
1086- self.mock_modify_system(succeed(True), "netboot_enabled", True)
1087- self.mock_save_system(succeed(True))
1088- self.mock_power_system(fail(SomeError()))
1089- self.mocker.replay()
1090- d = self.call_cobbler_method("start_system", "some-uid")
1091- self.assertFailure(d, SomeError)
1092- return d
1093-
1094- def test_start_system_power_probably_success_cant_tell(self):
1095- self.setup_mock()
1096- self.mock_get_name(succeed(["some-name"]))
1097- self.mock_get_system_handle(succeed("some-handle"))
1098- self.mock_modify_system(succeed(True), "netboot_enabled", True)
1099- self.mock_save_system(succeed(True))
1100- self.mock_power_system(succeed("ignored"))
1101- self.mocker.replay()
1102- d = self.call_cobbler_method("start_system", "some-uid")
1103- return d
1104-
1105- def test_describe_systems_error(self):
1106+ def test_get_name_error(self):
1107+ self.setup_mock()
1108+ self.mock_get_systems(succeed([
1109+ {"uid": "some-uid", "mgmt_classes": ["acquired"]}]))
1110+ return self.check_get_name_error("release_system", "some-uid")
1111+
1112+ def test_get_name_failure(self):
1113+ self.setup_mock()
1114+ self.mock_get_systems(succeed([
1115+ {"uid": "some-uid", "mgmt_classes": ["acquired"]}]))
1116+ return self.check_get_name_failure("release_system", "some-uid")
1117+
1118+ def test_get_system_handle_error(self):
1119+ self.setup_mock()
1120+ self.mock_get_systems(succeed([
1121+ {"uid": "some-uid", "mgmt_classes": ["acquired"]}]))
1122+ self.mock_get_name(succeed(["some-name"]))
1123+ return self.check_get_system_handle_error("release_system", "some-uid")
1124+
1125+ def test_get_system_handle_fault(self):
1126+ self.setup_mock()
1127+ self.mock_get_systems(succeed([
1128+ {"uid": "some-uid", "mgmt_classes": ["acquired"]}]))
1129+ self.mock_get_name(succeed(["some-name"]))
1130+ return self.check_get_system_handle_fault("release_system", "some-uid")
1131+
1132+ def test_get_system_handle_failure(self):
1133+ self.setup_mock()
1134+ self.mock_get_systems(succeed([
1135+ {"uid": "some-uid", "mgmt_classes": ["acquired"]}]))
1136+ self.mock_get_name(succeed(["some-name"]))
1137+ return self.check_get_system_handle_failure(
1138+ "release_system", "some-uid")
1139+
1140+ def test_modify_system_error(self):
1141+ self.setup_mock()
1142+ self.mock_get_systems(succeed([
1143+ {"uid": "some-uid", "mgmt_classes": ["preserve_me", "acquired"]}]))
1144+ self.mock_get_name(succeed(["some-name"]))
1145+ self.mock_get_system_handle(succeed("some-handle"))
1146+ return self.check_modify_system_error(
1147+ "mgmt_classes", ["preserve_me", "available"],
1148+ "release_system", "some-uid")
1149+
1150+ def test_modify_system_failure(self):
1151+ self.setup_mock()
1152+ self.mock_get_systems(succeed([
1153+ {"uid": "some-uid", "mgmt_classes": ["preserve_me", "acquired"]}]))
1154+ self.mock_get_name(succeed(["some-name"]))
1155+ self.mock_get_system_handle(succeed("some-handle"))
1156+ return self.check_modify_system_failure(
1157+ "mgmt_classes", ["preserve_me", "available"],
1158+ "release_system", "some-uid")
1159+
1160+ def test_save_system_error(self):
1161+ self.setup_mock()
1162+ self.mock_get_systems(succeed([
1163+ {"uid": "some-uid", "mgmt_classes": ["preserve_me", "acquired"]}]))
1164+ self.mock_get_name(succeed(["some-name"]))
1165+ self.mock_get_system_handle(succeed("some-handle"))
1166+ self.mock_modify_system(
1167+ succeed(True), "mgmt_classes", ["preserve_me", "available"])
1168+ return self.check_save_system_error("release_system", "some-uid")
1169+
1170+ def test_save_system_failure(self):
1171+ self.setup_mock()
1172+ self.mock_get_systems(succeed([
1173+ {"uid": "some-uid", "mgmt_classes": ["preserve_me", "acquired"]}]))
1174+ self.mock_get_name(succeed(["some-name"]))
1175+ self.mock_get_system_handle(succeed("some-handle"))
1176+ self.mock_modify_system(
1177+ succeed(True), "mgmt_classes", ["preserve_me", "available"])
1178+ return self.check_save_system_failure("release_system", "some-uid")
1179+
1180+ def test_success(self):
1181+ self.setup_mock()
1182+ self.mock_get_systems(succeed([
1183+ {"uid": "some-uid", "mgmt_classes": ["preserve_me", "acquired"]}]))
1184+ self.mock_get_name(succeed(["some-name"]))
1185+ self.mock_get_system_handle(succeed("some-handle"))
1186+ self.mock_modify_system(
1187+ succeed(True), "mgmt_classes", ["preserve_me", "available"])
1188+ self.mock_save_system(succeed(True))
1189+ self.mocker.replay()
1190+ return self.call_cobbler_method("release_system", "some-uid")
1191+
1192+
1193+class PowerTestsMixin(object):
1194+
1195+ def test_get_name_failure(self):
1196+ self.setup_mock()
1197+ return self.check_get_name_failure(self.method_name, "some-uid")
1198+
1199+ def test_get_name_insane(self):
1200+ self.setup_mock()
1201+ return self.check_get_name_insane(self.method_name, "some-uid")
1202+
1203+ def test_get_name_error(self):
1204+ self.setup_mock()
1205+ return self.check_get_name_error(self.method_name, "some-uid")
1206+
1207+ def test_get_system_handle_failure(self):
1208+ self.setup_mock()
1209+ self.mock_get_name(succeed(["some-name"]))
1210+ return self.check_get_system_handle_failure(
1211+ self.method_name, "some-uid")
1212+
1213+ def test_get_system_handle_unknown_fault(self):
1214+ self.setup_mock()
1215+ self.mock_get_name(succeed(["some-name"]))
1216+ return self.check_get_system_handle_fault(
1217+ self.method_name, "some-uid")
1218+
1219+ def test_get_system_handle_error(self):
1220+ self.setup_mock()
1221+ self.mock_get_name(succeed(["some-name"]))
1222+ return self.check_get_system_handle_error(
1223+ self.method_name, "some-uid")
1224+
1225+ def test_modify_system_failure(self):
1226+ self.setup_mock()
1227+ self.mock_get_name(succeed(["some-name"]))
1228+ self.mock_get_system_handle(succeed("some-handle"))
1229+ return self.check_modify_system_failure(
1230+ "netboot_enabled", True,
1231+ self.method_name, "some-uid")
1232+
1233+ def test_modify_system_error(self):
1234+ self.setup_mock()
1235+ self.mock_get_name(succeed(["some-name"]))
1236+ self.mock_get_system_handle(succeed("some-handle"))
1237+ return self.check_modify_system_error(
1238+ "netboot_enabled", True,
1239+ self.method_name, "some-uid")
1240+
1241+ def test_save_system_failure(self):
1242+ self.setup_mock()
1243+ self.mock_get_name(succeed(["some-name"]))
1244+ self.mock_get_system_handle(succeed("some-handle"))
1245+ self.mock_modify_system(succeed(True), "netboot_enabled", True)
1246+ return self.check_save_system_failure(self.method_name, "some-uid")
1247+
1248+ def test_save_system_error(self):
1249+ self.setup_mock()
1250+ self.mock_get_name(succeed(["some-name"]))
1251+ self.mock_get_system_handle(succeed("some-handle"))
1252+ self.mock_modify_system(succeed(True), "netboot_enabled", True)
1253+ return self.check_save_system_error(self.method_name, "some-uid")
1254+
1255+ def test_power_error(self):
1256+ self.setup_mock()
1257+ self.mock_get_name(succeed(["some-name"]))
1258+ self.mock_get_system_handle(succeed("some-handle"))
1259+ self.mock_modify_system(succeed(True), "netboot_enabled", True)
1260+ self.mock_save_system(succeed(True))
1261+ self.mock_power_system(self.desired_state, fail(SomeError()))
1262+ self.mocker.replay()
1263+ d = self.call_cobbler_method(self.method_name, "some-uid")
1264+ self.assertFailure(d, SomeError)
1265+ return d
1266+
1267+ def test_power_probably_success_cant_tell(self):
1268+ self.setup_mock()
1269+ self.mock_get_name(succeed(["some-name"]))
1270+ self.mock_get_system_handle(succeed("some-handle"))
1271+ self.mock_modify_system(succeed(True), "netboot_enabled", True)
1272+ self.mock_save_system(succeed(True))
1273+ self.mock_power_system(self.desired_state, succeed("ignored"))
1274+ self.mocker.replay()
1275+ return self.call_cobbler_method(self.method_name, "some-uid")
1276+
1277+
1278+class StartSystemTest(CobblerClientTestCase, PowerTestsMixin):
1279+
1280+ desired_state = "on"
1281+ method_name = "start_system"
1282+
1283+
1284+class StopSystemTest(CobblerClientTestCase, PowerTestsMixin):
1285+
1286+ desired_state = "off"
1287+ method_name = "stop_system"
1288+
1289+
1290+class DescribeSystemsTest(CobblerClientTestCase):
1291+
1292+ def test_error(self):
1293 self.setup_mock()
1294 self.mock_get_systems(fail(SomeError()))
1295 self.mocker.replay()
1296@@ -695,7 +762,7 @@
1297 self.assertFailure(d, SomeError)
1298 return d
1299
1300- def test_describe_systems_failure(self):
1301+ def test_failure(self):
1302 self.setup_mock()
1303 self.mock_get_systems(succeed([
1304 {"uid": "something-else", "mgmt_classes": "acquired"}]))
1305@@ -703,7 +770,7 @@
1306 d = self.call_cobbler_method("describe_systems", "something")
1307 return self.check_not_found(d, ["something"])
1308
1309- def test_describe_systems_success_all(self):
1310+ def test_success_all(self):
1311 self.setup_mock()
1312 self.mock_get_systems(succeed([
1313 {"uid": "bar", "mgmt_classes": ["acquired"]},
1314@@ -719,7 +786,7 @@
1315 d.addCallback(verify)
1316 return d
1317
1318- def test_describe_systems_not_acquired_some(self):
1319+ def test_not_acquired_some(self):
1320 self.setup_mock()
1321 self.mock_get_systems(succeed([
1322 {"uid": "bar", "mgmt_classes": ["irrelevant"]},
1323@@ -729,7 +796,7 @@
1324 d = self.call_cobbler_method("describe_systems", "foo", "baz")
1325 return self.check_not_found(d, ["foo"])
1326
1327- def test_describe_systems_success_some(self):
1328+ def test_success_some(self):
1329 self.setup_mock()
1330 self.mock_get_systems(succeed([
1331 {"uid": "bar", "mgmt_classes": ["ignored"]},
1332@@ -745,7 +812,7 @@
1333 d.addCallback(verify)
1334 return d
1335
1336- def test_describe_systems_success_none(self):
1337+ def test_success_none(self):
1338 self.setup_mock()
1339 self.mock_get_systems(succeed([]))
1340 self.mocker.replay()
1341
1342=== modified file 'ensemble/providers/orchestra/tests/test_getmachines.py'
1343--- ensemble/providers/orchestra/tests/test_getmachines.py 2011-08-12 19:28:37 +0000
1344+++ ensemble/providers/orchestra/tests/test_getmachines.py 2011-08-23 21:41:27 +0000
1345@@ -97,4 +97,3 @@
1346 d = provider.get_machine("foo")
1347 self.assertFailure(d, SomeError)
1348 return d
1349-
1350
1351=== modified file 'ensemble/providers/orchestra/tests/test_launch.py'
1352--- ensemble/providers/orchestra/tests/test_launch.py 2011-08-11 04:00:26 +0000
1353+++ ensemble/providers/orchestra/tests/test_launch.py 2011-08-23 21:41:27 +0000
1354@@ -1,3 +1,5 @@
1355+from twisted.internet.defer import succeed
1356+
1357 from ensemble.errors import EnvironmentNotFound, ProviderError
1358 from ensemble.lib.testing import TestCase
1359 from ensemble.providers.orchestra.machine import OrchestraMachine
1360@@ -54,13 +56,17 @@
1361 self.mock_set_ks_meta(
1362 self.get_verify_ks_meta(42, "launch_late_command"))
1363 self.mock_start_system()
1364- self.mock_describe_system()
1365+ self.mock_describe_systems(succeed([{
1366+ "uid": "winston-uid",
1367+ "name": "winston",
1368+ "mgmt_classes": ["acquired"]}]))
1369 self.mocker.replay()
1370
1371 def verify_machines(machines):
1372 (machine,) = machines
1373 self.assertTrue(isinstance(machine, OrchestraMachine))
1374 self.assertEquals(machine.instance_id, "winston-uid")
1375+ self.assertEquals(machine.dns_name, "winston")
1376 d = self.get_provider().start_machine({"machine-id": "42"})
1377 d.addCallback(verify_machines)
1378 return d
1379
1380=== added file 'ensemble/providers/orchestra/tests/test_shutdown.py'
1381--- ensemble/providers/orchestra/tests/test_shutdown.py 1970-01-01 00:00:00 +0000
1382+++ ensemble/providers/orchestra/tests/test_shutdown.py 2011-08-23 21:41:27 +0000
1383@@ -0,0 +1,195 @@
1384+from twisted.internet.defer import fail, succeed
1385+
1386+from ensemble.errors import MachinesNotFound
1387+from ensemble.lib.testing import TestCase
1388+from ensemble.providers.orchestra.machine import OrchestraMachine
1389+
1390+from .common import OrchestraTestMixin
1391+
1392+
1393+class SomeError(Exception):
1394+ pass
1395+
1396+
1397+class ShutdownTest(OrchestraTestMixin, TestCase):
1398+
1399+ def assert_machine(self, machine, uid, name):
1400+ self.assertTrue(isinstance(machine, OrchestraMachine))
1401+ self.assertEquals(machine.instance_id, uid)
1402+ self.assertEquals(machine.dns_name, name)
1403+
1404+ def assert_missing(self, d, instance_ids):
1405+ self.assertFailure(d, MachinesNotFound)
1406+
1407+ def verify(error):
1408+ self.assertEquals(error.instance_ids, instance_ids)
1409+ d.addCallback(verify)
1410+ return d
1411+
1412+ def mock_get_systems(self, *systems):
1413+ self.proxy_m.callRemote("get_systems")
1414+ self.mocker.result(succeed([
1415+ {"uid": uid, "name": name, "mgmt_classes": ["keep", cls]}
1416+ for (uid, name, cls) in systems]))
1417+
1418+ def mock_shutdown_release(self, uid, name):
1419+ self.proxy_m.callRemote("find_system", {"uid": uid})
1420+ self.mocker.result(succeed([name]))
1421+ self.proxy_m.callRemote("get_system_handle", name, "")
1422+ self.mocker.result(succeed("some-handle"))
1423+ self.proxy_m.callRemote(
1424+ "modify_system", "some-handle", "netboot_enabled", True, "")
1425+ self.mocker.result(succeed(True))
1426+ self.proxy_m.callRemote("save_system", "some-handle", "")
1427+ self.mocker.result(succeed(True))
1428+ self.proxy_m.callRemote(
1429+ "background_power_system", {"power": "off", "systems": [name]}, "")
1430+ self.mocker.result(succeed("ignored"))
1431+ self.mock_get_systems((uid, name, "acquired"))
1432+ self.proxy_m.callRemote("find_system", {"uid": uid})
1433+ self.mocker.result(succeed([name]))
1434+ self.proxy_m.callRemote("get_system_handle", name, "")
1435+ self.mocker.result(succeed("some-handle"))
1436+ self.proxy_m.callRemote(
1437+ "modify_system", "some-handle",
1438+ "mgmt_classes", ["keep", "available"], "")
1439+ self.mocker.result(succeed(True))
1440+ self.proxy_m.callRemote("save_system", "some-handle", "")
1441+ self.mocker.result(succeed(True))
1442+
1443+ def check_shutdown_all(self, method_name):
1444+ self.mock_get_systems(
1445+ ("i-amok", "ok", "acquired"),
1446+ ("i-amalien", "alien", "available"),
1447+ ("i-amoktoo", "oktoo", "acquired"))
1448+ self.mock_get_systems(
1449+ ("i-amok", "ok", "acquired"),
1450+ ("i-amalien", "alien", "available"),
1451+ ("i-amoktoo", "oktoo", "acquired"))
1452+ self.mock_shutdown_release("i-amok", "ok")
1453+ self.mock_shutdown_release("i-amoktoo", "oktoo")
1454+ self.mocker.replay()
1455+
1456+ provider = self.get_provider()
1457+ method = getattr(provider, method_name)
1458+ d = method()
1459+
1460+ def verify(machines):
1461+ (ok, oktoo) = machines
1462+ self.assert_machine(ok, "i-amok", "ok")
1463+ self.assert_machine(oktoo, "i-amoktoo", "oktoo")
1464+ d.addCallback(verify)
1465+ return d
1466+
1467+ def test_shutdown_machine(self):
1468+ self.setup_mocks()
1469+ self.mock_get_systems(("i-amhere", "blah", "acquired"))
1470+ self.mock_shutdown_release("i-amhere", "blah")
1471+ self.mocker.replay()
1472+
1473+ provider = self.get_provider()
1474+ d = provider.shutdown_machine(OrchestraMachine("i-amhere"))
1475+ d.addCallback(self.assert_machine, "i-amhere", "blah")
1476+ return d
1477+
1478+ def test_shutdown_machine_missing(self):
1479+ self.setup_mocks()
1480+ self.mock_get_systems(("i-amirrelevant", "blah", "acquired"))
1481+ self.mocker.replay()
1482+
1483+ provider = self.get_provider()
1484+ d = provider.shutdown_machine(OrchestraMachine("i-ammissing"))
1485+ return self.assert_missing(d, ["i-ammissing"])
1486+
1487+ def test_shutdown_machine_unowned(self):
1488+ self.setup_mocks()
1489+ self.mock_get_systems(("i-amalien", "blah", "available"))
1490+ self.mocker.replay()
1491+
1492+ provider = self.get_provider()
1493+ d = provider.shutdown_machine(OrchestraMachine("i-amalien"))
1494+ return self.assert_missing(d, ["i-amalien"])
1495+
1496+ def test_shutdown_machines_none(self):
1497+ self.mocker.replay()
1498+ provider = self.get_provider()
1499+ d = provider.shutdown_machines([])
1500+ d.addCallback(self.assertEquals, [])
1501+ return d
1502+
1503+ def test_shutdown_machines_some_good(self):
1504+ self.setup_mocks()
1505+ self.mock_get_systems(
1506+ ("i-amok", "ok", "acquired"),
1507+ ("i-amalien", "alien", "available"),
1508+ ("i-amoktoo", "oktoo", "acquired"))
1509+ self.mock_shutdown_release("i-amok", "ok")
1510+ self.mock_shutdown_release("i-amoktoo", "oktoo")
1511+ self.mocker.replay()
1512+
1513+ provider = self.get_provider()
1514+ d = provider.shutdown_machines([
1515+ OrchestraMachine("i-amok"),
1516+ OrchestraMachine("i-amoktoo")])
1517+
1518+ def verify(machines):
1519+ (ok, oktoo) = machines
1520+ self.assert_machine(ok, "i-amok", "ok")
1521+ self.assert_machine(oktoo, "i-amoktoo", "oktoo")
1522+ d.addCallback(verify)
1523+ return d
1524+
1525+ def test_shutdown_machines_some_missing(self):
1526+ self.setup_mocks()
1527+ self.mock_get_systems(
1528+ ("i-amok", "ok", "acquired"),
1529+ ("i-amalien", "alien", "available"),
1530+ ("i-amoktoo", "oktoo", "acquired"))
1531+ self.mocker.replay()
1532+
1533+ provider = self.get_provider()
1534+ d = provider.shutdown_machines([
1535+ OrchestraMachine("i-amok"),
1536+ OrchestraMachine("i-ammissing")])
1537+ return self.assert_missing(d, ["i-ammissing"])
1538+
1539+ def test_shutdown_machines_some_unowned(self):
1540+ self.setup_mocks()
1541+ self.mock_get_systems(
1542+ ("i-amok", "ok", "acquired"),
1543+ ("i-amalien", "alien", "available"),
1544+ ("i-amoktoo", "oktoo", "acquired"))
1545+ self.mocker.replay()
1546+
1547+ provider = self.get_provider()
1548+ d = provider.shutdown_machines([
1549+ OrchestraMachine("i-amok"),
1550+ OrchestraMachine("i-amalien")])
1551+ return self.assert_missing(d, ["i-amalien"])
1552+
1553+ def test_destroy_environment(self):
1554+ self.setup_mocks()
1555+ self.getPage("http://somewhe.re/webdav/provider-state",
1556+ method="PUT", postdata="{}\n")
1557+ self.mocker.result(succeed(True))
1558+ return self.check_shutdown_all("destroy_environment")
1559+
1560+ def test_destroy_environment_no_machines(self):
1561+ self.setup_mocks()
1562+ self.getPage("http://somewhe.re/webdav/provider-state",
1563+ method="PUT", postdata="{}\n")
1564+ self.mocker.result(succeed(True))
1565+ self.mock_get_systems()
1566+ self.mocker.replay()
1567+
1568+ provider = self.get_provider()
1569+ d = provider.destroy_environment()
1570+ d.addCallback(self.assertEquals, [])
1571+ return d
1572+
1573+ def test_destroy_environment_unwritable(self):
1574+ self.setup_mocks()
1575+ self.getPage("http://somewhe.re/webdav/provider-state",
1576+ method="PUT", postdata="{}\n")
1577+ self.mocker.result(fail(SomeError()))
1578+ return self.check_shutdown_all("destroy_environment")

Subscribers

People subscribed via source and target branches

to status/vote changes: