2
from getpass import getpass
4
from twisted.internet.defer import Deferred, succeed, fail
5
from twisted.internet import reactor
7
from landscape.configuration import (
8
print_text, LandscapeSetupScript, LandscapeSetupConfiguration,
9
register, setup, main, setup_init_script_and_start_client,
10
stop_client_and_disable_init_script, ConfigurationError)
11
from landscape.broker.registration import InvalidCredentialsError
12
from landscape.sysvconfig import SysVConfig, ProcessError
13
from landscape.tests.helpers import (LandscapeTest, LandscapeIsolatedTest,
14
RemoteBrokerHelper, EnvironSaverHelper)
15
from landscape.tests.mocker import ARGS, KWARGS, ANY, MATCH, CONTAINS, expect
18
class PrintTextTest(LandscapeTest):
20
def test_default(self):
21
stdout_mock = self.mocker.replace("sys.stdout")
24
stdout_mock.write("Hi!\n")
28
# Trial likes to flush things inside run().
30
self.mocker.count(0, None)
37
stderr_mock = self.mocker.replace("sys.stderr")
40
stderr_mock.write("Hi!\n")
44
# Trial likes to flush things inside run().
46
self.mocker.count(0, None)
50
print_text("Hi!", error=True)
53
stdout_mock = self.mocker.replace("sys.stdout")
56
stdout_mock.write("Hi!END")
60
# Trial likes to flush things inside run().
62
self.mocker.count(0, None)
66
print_text("Hi!", "END")
69
class LandscapeSetupScriptTest(LandscapeTest):
72
super(LandscapeSetupScriptTest, self).setUp()
73
self.config_filename = self.makeFile()
74
class MyLandscapeSetupConfiguration(LandscapeSetupConfiguration):
75
default_config_filenames = [self.config_filename]
76
self.config = MyLandscapeSetupConfiguration()
77
self.script = LandscapeSetupScript(self.config)
79
def test_show_help(self):
80
print_text_mock = self.mocker.replace(print_text)
81
print_text_mock("\nHello\n\nworld!\n")
86
self.script.show_help("\n\n \n Hello \n \n world! \n \n\n")
88
def test_prompt_simple(self):
89
mock = self.mocker.replace(raw_input, passthrough=False)
91
self.mocker.result("Desktop")
94
self.script.prompt("computer_title", "Message")
96
self.assertEquals(self.config.computer_title, "Desktop")
98
def test_prompt_with_default(self):
99
mock = self.mocker.replace(raw_input, passthrough=False)
100
mock("Message [default]: ")
101
self.mocker.result("")
104
self.config.computer_title = "default"
105
self.script.prompt("computer_title", "Message")
107
self.assertEquals(self.config.computer_title, "default")
109
def test_prompt_with_required(self):
111
raw_input_mock = self.mocker.replace(raw_input, passthrough=False)
112
script_mock = self.mocker.patch(self.script)
113
raw_input_mock("Message: ")
114
self.mocker.result("")
115
script_mock.show_help("This option is required to configure Landscape.")
116
raw_input_mock("Message: ")
117
self.mocker.result("Desktop")
120
self.script.prompt("computer_title", "Message", True)
122
self.assertEquals(self.config.computer_title, "Desktop")
124
def test_prompt_with_required_and_default(self):
126
raw_input_mock = self.mocker.replace(raw_input, passthrough=False)
127
script_mock = self.mocker.patch(self.script)
128
raw_input_mock("Message [Desktop]: ")
129
self.mocker.result("")
131
self.config.computer_title = "Desktop"
132
self.script.prompt("computer_title", "Message", True)
133
self.assertEquals(self.config.computer_title, "Desktop")
135
def test_prompt_for_unknown_variable(self):
137
It should be possible to prompt() defining a variable that doesn't
138
'exist' in the configuration, and still have it set there.
141
raw_input_mock = self.mocker.replace(raw_input, passthrough=False)
142
self.assertFalse(hasattr(self.config, "variable"))
143
self.expect(raw_input_mock("Variable: ")).result("Yay")
145
self.script.prompt("variable", "Variable")
146
self.assertEquals(self.config.variable, "Yay")
148
def test_password_prompt_simple_matching(self):
149
mock = self.mocker.replace(getpass, passthrough=False)
151
self.mocker.result("password")
152
mock("Please confirm: ")
153
self.mocker.result("password")
156
self.script.password_prompt("registration_password", "Password")
157
self.assertEquals(self.config.registration_password, "password")
159
def test_password_prompt_simple_non_matching(self):
160
mock = self.mocker.replace(getpass, passthrough=False)
162
self.mocker.result("password")
164
script_mock = self.mocker.patch(self.script)
165
script_mock.show_help("Passwords must match.")
167
mock("Please confirm: ")
168
self.mocker.result("")
170
self.mocker.result("password")
171
mock("Please confirm: ")
172
self.mocker.result("password")
174
self.script.password_prompt("registration_password", "Password")
175
self.assertEquals(self.config.registration_password, "password")
177
def test_password_prompt_simple_matching_required(self):
178
mock = self.mocker.replace(getpass, passthrough=False)
180
self.mocker.result("")
182
script_mock = self.mocker.patch(self.script)
183
script_mock.show_help("This option is required to configure Landscape.")
186
self.mocker.result("password")
187
mock("Please confirm: ")
188
self.mocker.result("password")
192
self.script.password_prompt("registration_password", "Password", True)
193
self.assertEquals(self.config.registration_password, "password")
195
def test_prompt_yes_no(self):
196
comparisons = [("Y", True),
207
raw_input_mock = self.mocker.replace(raw_input, passthrough=False)
208
for comparison in comparisons:
209
self.expect(raw_input_mock("Foo [Y/n]")).result(comparison[0])
211
for comparison in comparisons:
212
self.assertEquals(self.script.prompt_yes_no("Foo"), comparison[1])
214
def test_prompt_yes_no_default(self):
216
raw_input_mock = self.mocker.replace(raw_input, passthrough=False)
217
self.expect(raw_input_mock("Foo [y/N]")).result("")
219
self.assertFalse(self.script.prompt_yes_no("Foo", default=False))
221
def test_prompt_yes_no_invalid(self):
223
raw_input_mock = self.mocker.replace(raw_input, passthrough=False)
224
script_mock = self.mocker.patch(self.script)
225
self.expect(raw_input_mock("Foo [Y/n]")).result("x")
226
script_mock.show_help("Invalid input.")
227
self.expect(raw_input_mock("Foo [Y/n]")).result("n")
229
self.assertFalse(self.script.prompt_yes_no("Foo"))
231
def get_matcher(self, help_snippet):
232
def match_help(help):
233
return help.strip().startswith(help_snippet)
234
return MATCH(match_help)
236
def test_query_computer_title(self):
237
help_snippet = "The computer title you"
239
script_mock = self.mocker.patch(self.script)
240
script_mock.show_help(self.get_matcher(help_snippet))
241
script_mock.prompt("computer_title", "This computer's title", True)
244
self.script.query_computer_title()
246
def test_query_computer_title_defined_on_command_line(self):
247
raw_input_mock = self.mocker.replace(raw_input, passthrough=False)
248
self.expect(raw_input_mock(ANY)).count(0)
251
self.config.load_command_line(["-t", "Computer title"])
252
self.script.query_computer_title()
254
def test_query_account_name(self):
255
help_snippet = "You must now specify the name of the Landscape account"
257
script_mock = self.mocker.patch(self.script)
258
script_mock.show_help(self.get_matcher(help_snippet))
259
script_mock.prompt("account_name", "Account name", True)
262
self.script.query_account_name()
264
def test_query_account_name_defined_on_command_line(self):
265
raw_input_mock = self.mocker.replace(raw_input, passthrough=False)
266
self.expect(raw_input_mock(ANY)).count(0)
269
self.config.load_command_line(["-a", "Account name"])
270
self.script.query_account_name()
272
def test_query_registration_password(self):
273
help_snippet = "A registration password may be"
275
script_mock = self.mocker.patch(self.script)
276
script_mock.show_help(self.get_matcher(help_snippet))
277
script_mock.password_prompt("registration_password",
278
"Account registration password")
280
self.script.query_registration_password()
282
def test_query_registration_password_defined_on_command_line(self):
283
getpass_mock = self.mocker.replace("getpass.getpass", passthrough=False)
284
self.expect(getpass_mock(ANY)).count(0)
287
self.config.load_command_line(["-p", "shared-secret"])
288
self.script.query_registration_password()
290
def test_query_proxies(self):
291
help_snippet = "The Landscape client communicates"
293
script_mock = self.mocker.patch(self.script)
294
script_mock.show_help(self.get_matcher(help_snippet))
295
script_mock.prompt("http_proxy", "HTTP proxy URL")
296
script_mock.prompt("https_proxy", "HTTPS proxy URL")
298
self.script.query_proxies()
300
def test_query_proxies_defined_on_command_line(self):
301
raw_input_mock = self.mocker.replace(raw_input, passthrough=False)
302
self.expect(raw_input_mock(ANY)).count(0)
305
self.config.load_command_line(["--http-proxy", "localhost:8080",
306
"--https-proxy", "localhost:8443"])
307
self.script.query_proxies()
309
def test_query_http_proxy_defined_on_command_line(self):
310
help_snippet = "The Landscape client communicates"
312
script_mock = self.mocker.patch(self.script)
313
script_mock.show_help(self.get_matcher(help_snippet))
314
script_mock.prompt("https_proxy", "HTTPS proxy URL")
317
self.config.load_command_line(["--http-proxy", "localhost:8080"])
318
self.script.query_proxies()
320
def test_query_https_proxy_defined_on_command_line(self):
321
help_snippet = "The Landscape client communicates"
323
script_mock = self.mocker.patch(self.script)
324
script_mock.show_help(self.get_matcher(help_snippet))
325
script_mock.prompt("http_proxy", "HTTP proxy URL")
328
self.config.load_command_line(["--https-proxy", "localhost:8443"])
329
self.script.query_proxies()
331
def test_query_script_plugin_no(self):
332
help_snippet = "Landscape has a feature which enables administrators"
334
script_mock = self.mocker.patch(self.script)
335
script_mock.show_help(self.get_matcher(help_snippet))
336
script_mock.prompt_yes_no("Enable script execution?", default=False)
337
self.mocker.result(False)
339
self.script.query_script_plugin()
340
self.assertEquals(self.config.include_manager_plugins, "")
342
def test_query_script_plugin_yes(self):
344
If the user *does* want script execution, then the script asks which
345
users to enable it for.
347
help_snippet = "Landscape has a feature which enables administrators"
349
script_mock = self.mocker.patch(self.script)
350
script_mock.show_help(self.get_matcher(help_snippet))
351
script_mock.prompt_yes_no("Enable script execution?", default=False)
352
self.mocker.result(True)
353
script_mock.show_help(
354
self.get_matcher("By default, scripts are restricted"))
355
script_mock.prompt("script_users", "Script users")
357
self.script.query_script_plugin()
358
self.assertEquals(self.config.include_manager_plugins,
361
def test_disable_script_plugin(self):
363
Answering NO to enabling the script plugin while it's already enabled
366
self.config.include_manager_plugins = "ScriptExecution"
367
help_snippet = "Landscape has a feature which enables administrators"
369
script_mock = self.mocker.patch(self.script)
370
script_mock.show_help(self.get_matcher(help_snippet))
371
script_mock.prompt_yes_no("Enable script execution?", default=True)
372
self.mocker.result(False)
374
self.script.query_script_plugin()
375
self.assertEquals(self.config.include_manager_plugins, "")
377
def test_disabling_script_plugin_leaves_existing_inclusions(self):
379
Disabling the script execution plugin doesn't remove other included
382
self.config.include_manager_plugins = "FooPlugin, ScriptExecution"
384
script_mock = self.mocker.patch(self.script)
385
script_mock.show_help(ANY)
386
script_mock.prompt_yes_no("Enable script execution?", default=True)
387
self.mocker.result(False)
389
self.script.query_script_plugin()
390
self.assertEquals(self.config.include_manager_plugins, "FooPlugin")
392
def test_enabling_script_plugin_leaves_existing_inclusions(self):
394
Enabling the script execution plugin doesn't remove other included
397
self.config.include_manager_plugins = "FooPlugin"
399
script_mock = self.mocker.patch(self.script)
400
script_mock.show_help(ANY)
401
script_mock.prompt_yes_no("Enable script execution?", default=False)
402
self.mocker.result(True)
403
script_mock.show_help(ANY)
404
script_mock.prompt("script_users", "Script users")
406
self.script.query_script_plugin()
407
self.assertEquals(self.config.include_manager_plugins,
408
"FooPlugin, ScriptExecution")
410
def test_query_script_plugin_defined_on_command_line(self):
411
raw_input_mock = self.mocker.replace(raw_input, passthrough=False)
412
self.expect(raw_input_mock(ANY)).count(0)
415
self.config.load_command_line(
416
["--include-manager-plugins", "ScriptExecution",
417
"--script-users", "root, nobody"])
418
self.script.query_script_plugin()
419
self.assertEquals(self.config.include_manager_plugins,
421
self.assertEquals(self.config.script_users, "root, nobody")
423
def test_query_script_manager_plugins_defined_on_command_line(self):
424
self.config.include_manager_plugins = "FooPlugin"
426
script_mock = self.mocker.patch(self.script)
427
script_mock.show_help(ANY)
428
script_mock.prompt_yes_no("Enable script execution?", default=False)
429
self.mocker.result(True)
430
script_mock.show_help(ANY)
431
script_mock.prompt("script_users", "Script users")
434
self.config.load_command_line(
435
["--include-manager-plugins", "FooPlugin, ScriptExecution"])
436
self.script.query_script_plugin()
437
self.assertEquals(self.config.include_manager_plugins,
438
"FooPlugin, ScriptExecution")
440
def test_query_script_users_defined_on_command_line(self):
441
self.config.include_manager_plugins = "FooPlugin"
443
script_mock = self.mocker.patch(self.script)
444
script_mock.show_help(ANY)
445
script_mock.prompt_yes_no("Enable script execution?", default=False)
446
self.mocker.result(True)
447
script_mock.show_help(ANY)
448
raw_input_mock = self.mocker.replace(raw_input, passthrough=False)
449
self.expect(raw_input_mock(ANY)).count(0)
452
self.config.load_command_line(
453
["--script-users", "root, nobody, landscape"])
454
self.script.query_script_plugin()
455
self.assertEquals(self.config.script_users,
456
"root, nobody, landscape")
458
def test_show_header(self):
459
help_snippet = "This script will"
460
script_mock = self.mocker.patch(self.script)
461
script_mock.show_help(self.get_matcher(help_snippet))
464
self.script.show_header()
467
script_mock = self.mocker.patch(self.script)
468
script_mock.show_header()
469
script_mock.query_computer_title()
470
script_mock.query_account_name()
471
script_mock.query_registration_password()
472
script_mock.query_proxies()
473
script_mock.query_script_plugin()
479
class ConfigurationFunctionsTest(LandscapeTest):
481
helpers = [EnvironSaverHelper]
483
def get_config(self, args):
484
config = LandscapeSetupConfiguration()
488
def get_content(self, config):
489
"""Write C{config} to a file and return it's contents as a string."""
490
config_file = self.makeFile("")
491
original_config = config.config
493
config.config = config_file
495
return open(config.config, "r").read().strip() + "\n"
497
config.config = original_config
499
def test_setup(self):
500
filename = self.makeFile("[client]\n"
501
"computer_title = Old Title\n"
502
"account_name = Old Name\n"
503
"registration_password = Old Password\n"
504
"http_proxy = http://old.proxy\n"
505
"https_proxy = https://old.proxy\n"
507
"include_manager_plugins = ScriptExecution"
510
raw_input = self.mocker.replace("__builtin__.raw_input",
512
getpass = self.mocker.replace("getpass.getpass")
516
expect(raw_input(C("[Old Title]"))).result("New Title")
517
expect(raw_input(C("[Old Name]"))).result("New Name")
518
expect(getpass(C("registration password:"))).result("New Password")
519
expect(getpass(C("Please confirm:"))).result("New Password")
520
expect(raw_input(C("[http://old.proxy]"))).result("http://new.proxy")
521
expect(raw_input(C("[https://old.proxy]"))).result("https://new.proxy")
522
expect(raw_input(C("Enable script execution? [Y/n]"))).result("n")
524
# Negative assertion. We don't want it called in any other way.
525
expect(raw_input(ANY)).count(0)
527
# We don't care about these here, but don't show any output please.
528
print_text_mock = self.mocker.replace(print_text)
529
expect(print_text_mock(ANY)).count(0, None)
533
config = self.get_config(["--no-start", "--config", filename])
535
self.assertEquals(type(config), LandscapeSetupConfiguration)
537
# Reload it to ensure it was written down.
540
self.assertEquals(config.computer_title, "New Title")
541
self.assertEquals(config.account_name, "New Name")
542
self.assertEquals(config.registration_password, "New Password")
543
self.assertEquals(config.http_proxy, "http://new.proxy")
544
self.assertEquals(config.https_proxy, "https://new.proxy")
545
self.assertEquals(config.include_manager_plugins, "")
547
def test_silent_setup(self):
549
Only command-line options are used in silent mode and registration is
552
sysvconfig_mock = self.mocker.patch(SysVConfig)
553
sysvconfig_mock.set_start_on_boot(True)
554
sysvconfig_mock.restart_landscape()
557
filename = self.makeFile("""
559
url = https://landscape.canonical.com/message-system
561
config = self.get_config(["--config", filename, "--silent",
562
"-a", "account", "-t", "rex"])
564
self.assertEquals(self.get_content(config), """\
566
url = https://landscape.canonical.com/message-system
568
account_name = account
571
def test_silent_setup_without_computer_title(self):
572
"""A computer title is required."""
573
sysvconfig_mock = self.mocker.patch(SysVConfig)
574
sysvconfig_mock.set_start_on_boot(True)
577
filename = self.makeFile("""
579
url = https://landscape.canonical.com/message-system
581
config = self.get_config(["--config", filename, "--silent",
583
self.assertRaises(ConfigurationError, setup, config)
585
def test_silent_setup_without_account_name(self):
586
"""An account name is required."""
587
sysvconfig_mock = self.mocker.patch(SysVConfig)
588
sysvconfig_mock.set_start_on_boot(True)
591
filename = self.makeFile("""
593
url = https://landscape.canonical.com/message-system
595
config = self.get_config(["--config", filename, "--silent",
597
self.assertRaises(ConfigurationError, setup, config)
599
def test_silent_script_users_imply_script_execution_plugin(self):
601
If C{--script-users} is specified, without C{ScriptExecution} in the
602
list of manager plugins, it will be automatically added.
604
sysvconfig_mock = self.mocker.patch(SysVConfig)
605
sysvconfig_mock.set_start_on_boot(True)
606
sysvconfig_mock.restart_landscape()
607
self.mocker.result(True)
609
raw_input_mock = self.mocker.replace(raw_input, passthrough=False)
610
self.expect(raw_input_mock(ANY)).count(0)
613
filename = self.makeFile("""
615
url = https://localhost:8080/message-system
619
config = self.get_config(["--config", filename, "--silent",
620
"-a", "account", "-t", "rex",
621
"--script-users", "root, nobody"])
623
contents = open(filename, "r").read().strip() + "\n"
624
self.assertEquals(contents, """\
626
url = https://localhost:8080/message-system
629
include_manager_plugins = ScriptExecution
630
script_users = root, nobody
631
account_name = account
634
def test_silent_setup_with_ping_url(self):
635
sysvconfig_mock = self.mocker.patch(SysVConfig)
636
sysvconfig_mock.set_start_on_boot(True)
637
sysvconfig_mock.restart_landscape()
638
self.mocker.result(True)
641
filename = self.makeFile("""
643
url = https://landscape.canonical.com/message-system
644
ping_url = http://landscape.canonical.com/ping
645
registration_password = shared-secret
647
random_key = random_value
649
config = self.get_config(["--config", filename, "--silent",
650
"-a", "account", "-t", "rex",
651
"--ping-url", "http://localhost/ping"])
653
self.assertEquals(self.get_content(config), """\
656
registration_password = shared-secret
658
url = https://landscape.canonical.com/message-system
659
ping_url = http://localhost/ping
660
random_key = random_value
661
account_name = account
664
def test_setup_with_proxies_from_environment(self):
665
os.environ["http_proxy"] = "http://environ"
666
os.environ["https_proxy"] = "https://environ"
668
script_mock = self.mocker.patch(LandscapeSetupScript)
671
filename = self.makeFile("[client]\n"
672
"url = http://url\n")
676
config = self.get_config(["--no-start", "--config", filename])
679
# Reload it to ensure it was written down.
682
self.assertEquals(config.http_proxy, "http://environ")
683
self.assertEquals(config.https_proxy, "https://environ")
685
def test_silent_setup_with_proxies_from_environment(self):
687
Only command-line options are used in silent mode and registration is
690
os.environ["http_proxy"] = "http://environ"
691
os.environ["https_proxy"] = "https://environ"
692
sysvconfig_mock = self.mocker.patch(SysVConfig)
693
sysvconfig_mock.set_start_on_boot(True)
694
sysvconfig_mock.restart_landscape()
697
filename = self.makeFile("""
699
url = https://landscape.canonical.com/message-system
700
registration_password = shared-secret
702
config = self.get_config(["--config", filename, "--silent",
703
"-a", "account", "-t", "rex"])
705
self.assertEquals(self.get_content(config), """\
707
registration_password = shared-secret
709
http_proxy = http://environ
710
https_proxy = https://environ
711
url = https://landscape.canonical.com/message-system
712
account_name = account
715
def test_setup_prefers_proxies_from_config_over_environment(self):
716
os.environ["http_proxy"] = "http://environ"
717
os.environ["https_proxy"] = "https://environ"
719
script_mock = self.mocker.patch(LandscapeSetupScript)
722
filename = self.makeFile("[client]\n"
723
"http_proxy = http://config\n"
724
"https_proxy = https://config\n"
725
"url = http://url\n")
729
config = self.get_config(["--no-start", "--config", filename])
732
# Reload it to enusre it was written down.
735
self.assertEquals(config.http_proxy, "http://config")
736
self.assertEquals(config.https_proxy, "https://config")
738
def test_main_no_registration(self):
739
setup_mock = self.mocker.replace(setup)
742
raw_input_mock = self.mocker.replace(raw_input)
743
raw_input_mock("\nRequest a new registration for "
744
"this computer now? (Y/n): ")
745
self.mocker.result("n")
747
# This must not be called.
748
register_mock = self.mocker.replace(register, passthrough=False)
754
main(["-c", self.make_working_config()])
756
def make_working_config(self):
757
return self.makeFile("[client]\n"
758
"computer_title = Old Title\n"
759
"account_name = Old Name\n"
760
"registration_password = Old Password\n"
761
"http_proxy = http://old.proxy\n"
762
"https_proxy = https://old.proxy\n"
763
"url = http://url\n")
765
def test_register(self):
766
sysvconfig_mock = self.mocker.patch(SysVConfig)
767
sysvconfig_mock.is_configured_to_run()
768
self.mocker.result(False)
769
sysvconfig_mock.set_start_on_boot(True)
770
sysvconfig_mock.restart_landscape()
772
script_mock = self.mocker.patch(LandscapeSetupScript)
775
raw_input_mock = self.mocker.replace(raw_input)
776
raw_input_mock("\nRequest a new registration for "
777
"this computer now? (Y/n): ")
778
self.mocker.result("")
780
raw_input_mock("\nThe Landscape client must be started "
781
"on boot to operate correctly.\n\n"
782
"Start Landscape client on boot? (Y/n): ")
783
self.mocker.result("")
785
register_mock = self.mocker.replace(register, passthrough=False)
789
main(["--config", self.make_working_config()])
791
def test_main_with_register(self):
792
setup_mock = self.mocker.replace(setup)
794
raw_input_mock = self.mocker.replace(raw_input)
795
raw_input_mock("\nRequest a new registration for "
796
"this computer now? (Y/n): ")
797
self.mocker.result("")
799
register_mock = self.mocker.replace(register, passthrough=False)
803
main(["-c", self.make_working_config()])
805
def test_setup_init_script_and_start_client(self):
806
sysvconfig_mock = self.mocker.patch(SysVConfig)
807
sysvconfig_mock.set_start_on_boot(True)
810
setup_init_script_and_start_client()
812
def test_setup_init_script_and_start_client_silent(self):
813
sysvconfig_mock = self.mocker.patch(SysVConfig)
814
sysvconfig_mock.set_start_on_boot(True)
816
raw_input_mock = self.mocker.replace(raw_input, passthrough=False)
820
setup_init_script_and_start_client()
822
def test_register_silent(self):
824
Silent registration uses specified configuration to attempt a
825
registration with the server.
827
setup_mock = self.mocker.replace(setup)
829
# No interaction should be requested.
830
raw_input_mock = self.mocker.replace(raw_input)
834
# The registration logic should be called and passed the configuration
836
register_mock = self.mocker.replace(register, passthrough=False)
841
main(["--silent", "-c", self.make_working_config()])
843
def test_disable(self):
844
stop_client_and_disable_init_script_mock = self.mocker.replace(
845
stop_client_and_disable_init_script)
846
stop_client_and_disable_init_script_mock()
848
# No interaction should be requested.
849
raw_input_mock = self.mocker.replace(raw_input)
853
# Registration logic should not be invoked.
854
register_mock = self.mocker.replace(register, passthrough=False)
860
main(["--disable", "-c", self.make_working_config()])
862
def test_stop_client_and_disable_init_scripts(self):
863
sysvconfig_mock = self.mocker.patch(SysVConfig)
864
self.mocker.result(True)
865
sysvconfig_mock.set_start_on_boot(False)
866
sysvconfig_mock.stop_landscape()
869
main(["--disable", "-c", self.make_working_config()])
872
class RegisterFunctionTest(LandscapeIsolatedTest):
874
# Due to the way these tests run, the run() method on the reactor is called
875
# *before* any of the remote methods (reload, register) are called, because
876
# these tests "hold" the reactor until after the tests runs, then the
877
# reactor is given back control of the process, *then* all the remote calls
878
# in the dbus queue are fired.
880
helpers = [RemoteBrokerHelper]
882
def test_register_success(self):
883
service = self.broker_service
885
registration_mock = self.mocker.replace(service.registration)
886
config_mock = self.mocker.replace(service.config)
887
print_text_mock = self.mocker.replace(print_text)
888
reactor_mock = self.mocker.proxy("twisted.internet.reactor")
889
install_mock = self.mocker.replace("twisted.internet."
890
"glib2reactor.install")
892
# This must necessarily happen in the following order.
897
# This very informative message is printed out.
898
print_text_mock("Please wait... ", "")
900
time_mock = self.mocker.replace("time")
906
# After a nice dance the configuration is reloaded.
909
# The register() method is called. We fire the "registration-done"
910
# event after it's done, so that it cascades into a deferred callback.
912
def register_done(deferred_result):
913
service.reactor.fire("registration-done")
914
registration_mock.register()
915
self.mocker.passthrough(register_done)
917
# The deferred callback finally prints out this message.
918
print_text_mock("System successfully registered.")
922
self.mocker.call(lambda: result.callback(None))
924
# Nothing else is printed!
931
register(service.config, reactor_mock)
935
def test_register_failure(self):
937
When registration fails because of invalid credentials, a message will
938
be printed to the console and the program will exit.
940
service = self.broker_service
942
self.log_helper.ignore_errors(InvalidCredentialsError)
943
registration_mock = self.mocker.replace(service.registration)
944
config_mock = self.mocker.replace(service.config)
945
print_text_mock = self.mocker.replace(print_text)
946
reactor_mock = self.mocker.proxy("twisted.internet.reactor")
947
install_mock = self.mocker.replace("twisted.internet."
948
"glib2reactor.install")
950
# This must necessarily happen in the following order.
955
# This very informative message is printed out.
956
print_text_mock("Please wait... ", "")
958
time_mock = self.mocker.replace("time")
964
# After a nice dance the configuration is reloaded.
967
# The register() method is called. We fire the "registration-failed"
968
# event after it's done, so that it cascades into a deferred errback.
969
def register_done(deferred_result):
970
service.reactor.fire("registration-failed")
971
registration_mock.register()
972
self.mocker.passthrough(register_done)
974
# The deferred errback finally prints out this message.
975
print_text_mock("Invalid account name or registration password.",
980
self.mocker.call(lambda: result.callback(None))
982
# Nothing else is printed!
989
register(service.config, reactor_mock)
993
def test_register_exchange_failure(self):
995
When registration fails because the server couldn't be contacted, a
996
message is printed and the program quits.
998
service = self.broker_service
1000
registration_mock = self.mocker.replace(service.registration)
1001
config_mock = self.mocker.replace(service.config)
1002
print_text_mock = self.mocker.replace(print_text)
1003
reactor_mock = self.mocker.proxy("twisted.internet.reactor")
1004
install_mock = self.mocker.replace("twisted.internet."
1005
"glib2reactor.install")
1007
# This must necessarily happen in the following order.
1012
# This very informative message is printed out.
1013
print_text_mock("Please wait... ", "")
1015
time_mock = self.mocker.replace("time")
1016
time_mock.sleep(ANY)
1017
self.mocker.count(1)
1021
# After a nice dance the configuration is reloaded.
1022
config_mock.reload()
1024
def register_done(deferred_result):
1025
service.reactor.fire("exchange-failed")
1026
registration_mock.register()
1027
self.mocker.passthrough(register_done)
1029
# The deferred errback finally prints out this message.
1030
print_text_mock("We were unable to contact the server. "
1031
"Your internet connection may be down. "
1032
"The landscape client will continue to try and contact "
1033
"the server periodically.",
1039
self.mocker.call(lambda: result.callback(None))
1041
# Nothing else is printed!
1042
print_text_mock(ANY)
1043
self.mocker.count(0)
1045
self.mocker.replay()
1048
register(service.config, reactor_mock)
1052
def test_register_timeout_failure(self):
1053
# XXX This test will take about 30 seconds to run on some versions of
1054
# dbus, as it really is waiting for the dbus call to timeout. We can
1055
# remove it after it's possible for us to specify dbus timeouts on all
1056
# supported platforms (current problematic ones are edgy through gutsy)
1057
service = self.broker_service
1059
registration_mock = self.mocker.replace(service.registration)
1060
config_mock = self.mocker.replace(service.config)
1061
print_text_mock = self.mocker.replace(print_text)
1062
reactor_mock = self.mocker.proxy("twisted.internet.reactor")
1063
install_mock = self.mocker.replace("twisted.internet."
1064
"glib2reactor.install")
1066
# This must necessarily happen in the following order.
1071
# This very informative message is printed out.
1072
print_text_mock("Please wait... ", "")
1074
time_mock = self.mocker.replace("time")
1075
time_mock.sleep(ANY)
1076
self.mocker.count(1)
1080
# After a nice dance the configuration is reloaded.
1081
config_mock.reload()
1083
registration_mock.register()
1084
self.mocker.passthrough()
1086
# Nothing else is printed!
1087
print_text_mock(ANY)
1088
self.mocker.count(0)
1090
self.mocker.replay()
1094
reactor.addSystemEventTrigger("during",
1095
"landscape-registration-error",
1096
result.callback, None)
1098
register(service.config, reactor_mock)
1103
class RegisterFunctionNoServiceTest(LandscapeIsolatedTest):
1106
super(RegisterFunctionNoServiceTest, self).setUp()
1107
self.configuration = LandscapeSetupConfiguration()
1108
# Let's not mess about with the system bus
1109
self.configuration.load_command_line(["--bus", "session"])
1111
def test_register_dbus_error(self):
1113
When registration fails because of a DBUS error, a message is printed
1114
and the program exits.
1116
print_text_mock = self.mocker.replace(print_text)
1117
reactor_mock = self.mocker.proxy("twisted.internet.reactor")
1118
install_mock = self.mocker.replace("twisted.internet."
1119
"glib2reactor.install")
1122
print_text_mock("Please wait... ", "")
1124
print_text_mock("Error occurred contacting Landscape Client. "
1128
# WHOAH DUDE. This waits for callLater(0, reactor.stop).
1130
reactor_mock.callLater(0, ANY)
1131
self.mocker.call(lambda seconds, thingy: thingy())
1133
self.mocker.call(lambda: result.callback(None))
1136
self.mocker.replay()
1139
register(self.configuration, reactor_mock)
1143
def test_register_unknown_error(self):
1145
When registration fails because of an unknown error, a message is
1146
printed and the program exits.
1148
# We'll just mock the remote here to have it raise an exception.
1149
remote_broker_factory = self.mocker.replace(
1150
"landscape.broker.remote.RemoteBroker", passthrough=False)
1152
print_text_mock = self.mocker.replace(print_text)
1153
reactor_mock = self.mocker.proxy("twisted.internet.reactor")
1154
install_mock = self.mocker.replace("twisted.internet."
1155
"glib2reactor.install")
1156
# This is unordered. It's just way too much of a pain.
1159
print_text_mock("Please wait... ", "")
1160
time_mock = self.mocker.replace("time")
1161
time_mock.sleep(ANY)
1162
self.mocker.count(1)
1165
remote_broker = remote_broker_factory(ANY, retry_timeout=0)
1166
self.mocker.result(succeed(None))
1167
remote_broker.reload_configuration()
1168
self.mocker.result(succeed(None))
1169
remote_broker.connect_to_signal(ARGS, KWARGS)
1170
self.mocker.result(succeed(None))
1171
self.mocker.count(3)
1174
remote_broker.register()
1175
self.mocker.result(fail(ZeroDivisionError))
1177
print_text_mock(ANY, error=True)
1178
def check_logged_failure(text, error):
1179
self.assertTrue("ZeroDivisionError" in text)
1180
self.mocker.call(check_logged_failure)
1181
print_text_mock("Unknown error occurred.", error=True)
1183
# WHOAH DUDE. This waits for callLater(0, reactor.stop).
1185
reactor_mock.callLater(0, ANY)
1186
self.mocker.call(lambda seconds, thingy: thingy())
1188
self.mocker.call(lambda: result.callback(None))
1192
self.mocker.replay()
1194
register(self.configuration, reactor_mock)