~ahasenack/landscape-client/landscape-client-11.02

« back to all changes in this revision

Viewing changes to landscape/broker/tests/test_registration.py

  • Committer: Bazaar Package Importer
  • Author(s): Free Ekanayaka
  • Date: 2010-07-28 08:14:02 UTC
  • mfrom: (1.1.18 upstream)
  • Revision ID: james.westby@ubuntu.com-20100728081402-2ygupluqwc2bbe8j
Tags: 1.5.4-0ubuntu0.10.10.0
* New upstream version (LP: #610744):

  - The Eucalyptus management plugin reports the output of the
    'euca-describe-availability-zones verbose' command, which includes
    information about the available instance types and the maximum
    number of each instance type that the cloud can support (LP: #599338)

  - Check if the package directory exists before trying to check the
    package changer lock in the dbus-proxy. This fixes a bug when upgrading
    a dbus-landscape which never registered (LP: #603514).

  - Allow an LDS server to bootstrap new cloud instances with its own CA,
    which is picked up by the client, written to a file on the instance, and
    used in subsequent exchanges with the server (LP: #605079).

  - Skip loopback interface when reporting device info (LP: #608314)

  - Disable landscape-sysinfo when load is more than 1 (LP: #608278)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import os
1
2
import logging
2
3
import pycurl
3
4
import socket
15
16
from landscape.lib.bpickle import dumps
16
17
from landscape.lib.fetch import HTTPCodeError, FetchError
17
18
from landscape.lib.persist import Persist
 
19
from landscape.configuration import print_text
18
20
 
19
21
 
20
22
class IdentityTest(LandscapeTest):
28
30
 
29
31
    def check_persist_property(self, attr, persist_name):
30
32
        value = "VALUE"
31
 
        self.assertEquals(getattr(self.identity, attr), None,
32
 
                          "%r attribute should default to None, not %r" %
33
 
                          (attr, getattr(self.identity, attr)))
 
33
        self.assertEqual(getattr(self.identity, attr), None,
 
34
                         "%r attribute should default to None, not %r" %
 
35
                         (attr, getattr(self.identity, attr)))
34
36
        setattr(self.identity, attr, value)
35
 
        self.assertEquals(getattr(self.identity, attr), value,
36
 
                          "%r attribute should be %r, not %r" %
37
 
                          (attr, value, getattr(self.identity, attr)))
38
 
        self.assertEquals(
 
37
        self.assertEqual(getattr(self.identity, attr), value,
 
38
                         "%r attribute should be %r, not %r" %
 
39
                         (attr, value, getattr(self.identity, attr)))
 
40
        self.assertEqual(
39
41
            self.persist.get(persist_name), value,
40
42
            "%r not set to %r in persist" % (persist_name, value))
41
43
 
42
44
    def check_config_property(self, attr):
43
45
        value = "VALUE"
44
46
        setattr(self.config, attr, value)
45
 
        self.assertEquals(getattr(self.identity, attr), value,
46
 
                          "%r attribute should be %r, not %r" %
47
 
                          (attr, value, getattr(self.identity, attr)))
 
47
        self.assertEqual(getattr(self.identity, attr), value,
 
48
                         "%r attribute should be %r, not %r" %
 
49
                         (attr, value, getattr(self.identity, attr)))
48
50
 
49
51
    def test_secure_id(self):
50
52
        self.check_persist_property("secure_id",
88
90
        """
89
91
        self.exchanger.handle_message(
90
92
            {"type": "set-id", "id": "abc", "insecure-id": "def"})
91
 
        self.assertEquals(self.identity.secure_id, "abc")
92
 
        self.assertEquals(self.identity.insecure_id, "def")
 
93
        self.assertEqual(self.identity.secure_id, "abc")
 
94
        self.assertEqual(self.identity.insecure_id, "def")
93
95
 
94
96
    def test_registration_done_event(self):
95
97
        """
107
109
        self.identity.insecure_id = "old_id"
108
110
        self.mstore.set_accepted_types(["register"])
109
111
        self.exchanger.handle_message({"type": "unknown-id"})
110
 
        self.assertEquals(self.identity.secure_id, None)
111
 
        self.assertEquals(self.identity.insecure_id, None)
 
112
        self.assertEqual(self.identity.secure_id, None)
 
113
        self.assertEqual(self.identity.insecure_id, None)
112
114
 
113
115
    def test_should_register(self):
114
116
        self.mstore.set_accepted_types(["register"])
153
155
                              "registration_password": None,
154
156
                              "hostname": "ooga.local",
155
157
                              "tags": None}])
156
 
        self.assertEquals(self.logfile.getvalue().strip(),
157
 
                          "INFO: Queueing message to register with account "
158
 
                          "'account_name' without a password.")
 
158
        self.assertEqual(self.logfile.getvalue().strip(),
 
159
                         "INFO: Queueing message to register with account "
 
160
                         "'account_name' without a password.")
159
161
 
160
162
    def test_queue_message_on_exchange_with_password(self):
161
163
        """If a registration password is available, we pass it on!"""
171
173
                              "registration_password": "SEKRET",
172
174
                              "hostname": "ooga.local",
173
175
                              "tags": None}])
174
 
        self.assertEquals(self.logfile.getvalue().strip(),
175
 
                          "INFO: Queueing message to register with account "
176
 
                          "'account_name' with a password.")
 
176
        self.assertEqual(self.logfile.getvalue().strip(),
 
177
                         "INFO: Queueing message to register with account "
 
178
                         "'account_name' with a password.")
177
179
 
178
180
    def test_queue_message_on_exchange_with_tags(self):
179
181
        """
193
195
                              "registration_password": "SEKRET",
194
196
                              "hostname": "ooga.local",
195
197
                              "tags": u"computer,tag"}])
196
 
        self.assertEquals(self.logfile.getvalue().strip(),
197
 
                          "INFO: Queueing message to register with account "
198
 
                          "'account_name' and tags computer,tag "
199
 
                          "with a password.")
 
198
        self.assertEqual(self.logfile.getvalue().strip(),
 
199
                         "INFO: Queueing message to register with account "
 
200
                         "'account_name' and tags computer,tag "
 
201
                         "with a password.")
200
202
 
201
203
    def test_queue_message_on_exchange_with_invalid_tags(self):
202
204
        """
218
220
                              "registration_password": "SEKRET",
219
221
                              "hostname": "ooga.local",
220
222
                              "tags": None}])
221
 
        self.assertEquals(self.logfile.getvalue().strip(),
222
 
                          "ERROR: Invalid tags provided for cloud "
223
 
                          "registration.\n    "
224
 
                          "INFO: Queueing message to register with account "
225
 
                          "'account_name' with a password.")
 
223
        self.assertEqual(self.logfile.getvalue().strip(),
 
224
                         "ERROR: Invalid tags provided for cloud "
 
225
                         "registration.\n    "
 
226
                         "INFO: Queueing message to register with account "
 
227
                         "'account_name' with a password.")
226
228
 
227
229
    def test_queue_message_on_exchange_with_unicode_tags(self):
228
230
        """
243
245
              "registration_password": "SEKRET",
244
246
              "hostname": "ooga.local",
245
247
              "tags": u"prova\N{LATIN SMALL LETTER J WITH CIRCUMFLEX}o"}])
246
 
        self.assertEquals(self.logfile.getvalue().strip(),
247
 
                          "INFO: Queueing message to register with account "
248
 
                          "'account_name' and tags prova\xc4\xb5o "
249
 
                          "with a password.")
 
248
        self.assertEqual(self.logfile.getvalue().strip(),
 
249
                         "INFO: Queueing message to register with account "
 
250
                         "'account_name' and tags prova\xc4\xb5o "
 
251
                         "with a password.")
250
252
 
251
253
    def test_queueing_registration_message_resets_message_store(self):
252
254
        """
260
262
        self.config.account_name = "account_name"
261
263
        self.reactor.fire("pre-exchange")
262
264
        messages = self.mstore.get_pending_messages()
263
 
        self.assertEquals(len(messages), 1)
264
 
        self.assertEquals(messages[0]["type"], "register")
 
265
        self.assertEqual(len(messages), 1)
 
266
        self.assertEqual(messages[0]["type"], "register")
265
267
 
266
268
    def test_no_message_when_should_register_is_false(self):
267
269
        """If we already have a secure id, do not queue a register message.
314
316
        self.identity.secure_id = "foo"
315
317
        self.identity.insecure_id = "bar"
316
318
        self.handler.register()
317
 
        self.assertEquals(self.identity.secure_id, None)
318
 
        self.assertEquals(self.identity.insecure_id, None)
 
319
        self.assertEqual(self.identity.secure_id, None)
 
320
        self.assertEqual(self.identity.insecure_id, None)
319
321
 
320
322
    def test_register_calls_urgent_exchange(self):
321
323
        exchanger_mock = self.mocker.patch(self.exchanger)
332
334
        d = self.handler.register()
333
335
 
334
336
        def add_call(result):
335
 
            self.assertEquals(result, None)
 
337
            self.assertEqual(result, None)
336
338
            calls[0] += 1
337
339
 
338
340
        d.addCallback(add_call)
341
343
        self.exchanger.handle_message(
342
344
            {"type": "set-id", "id": "abc", "insecure-id": "def"})
343
345
 
344
 
        self.assertEquals(calls, [1])
 
346
        self.assertEqual(calls, [1])
345
347
 
346
348
        # Doing it again to ensure that the deferred isn't called twice.
347
349
        self.exchanger.handle_message(
348
350
            {"type": "set-id", "id": "abc", "insecure-id": "def"})
349
351
 
350
 
        self.assertEquals(calls, [1])
 
352
        self.assertEqual(calls, [1])
351
353
 
352
 
        self.assertEquals(self.logfile.getvalue(), "")
 
354
        self.assertEqual(self.logfile.getvalue(), "")
353
355
 
354
356
    def test_resynchronize_fired_when_registration_done(self):
355
357
 
366
368
        self.exchanger.handle_message(
367
369
            {"type": "set-id", "id": "abc", "insecure-id": "def"})
368
370
 
369
 
        self.assertEquals(results, [True])
 
371
        self.assertEqual(results, [True])
370
372
 
371
373
    def test_register_deferred_called_on_failed(self):
372
374
        # We don't want informational messages.
386
388
        self.exchanger.handle_message(
387
389
            {"type": "registration", "info": "unknown-account"})
388
390
 
389
 
        self.assertEquals(calls, [1])
 
391
        self.assertEqual(calls, [1])
390
392
 
391
393
        # Doing it again to ensure that the deferred isn't called twice.
392
394
        self.exchanger.handle_message(
393
395
            {"type": "registration", "info": "unknown-account"})
394
396
 
395
 
        self.assertEquals(calls, [1])
 
397
        self.assertEqual(calls, [1])
396
398
 
397
 
        self.assertEquals(self.logfile.getvalue(), "")
 
399
        self.assertEqual(self.logfile.getvalue(), "")
398
400
 
399
401
    def test_exchange_done_calls_exchange(self):
400
402
        exchanger_mock = self.mocker.patch(self.exchanger)
453
455
 
454
456
    def get_user_data(self, otps=None,
455
457
                      exchange_url="https://example.com/message-system",
456
 
                      ping_url="http://example.com/ping"):
 
458
                      ping_url="http://example.com/ping",
 
459
                      ssl_ca_certificate=None):
457
460
        if otps is None:
458
461
            otps = ["otp1"]
459
 
        return {"otps": otps, "exchange-url": exchange_url,
460
 
                "ping-url": ping_url}
 
462
        user_data = {"otps": otps, "exchange-url": exchange_url,
 
463
                     "ping-url": ping_url}
 
464
        if ssl_ca_certificate is not None:
 
465
            user_data["ssl-ca-certificate"] = ssl_ca_certificate
 
466
        return user_data
461
467
 
462
468
    def prepare_query_results(
463
469
        self, user_data=None, instance_key="key1", launch_index=0,
464
470
        local_hostname="ooga.local", public_hostname="ooga.amazon.com",
465
471
        reservation_key=u"res1", ramdisk_key=u"ram1", kernel_key=u"kernel1",
466
 
        image_key=u"image1"):
 
472
        image_key=u"image1", ssl_ca_certificate=None):
467
473
        if user_data is None:
468
 
            user_data = self.get_user_data()
 
474
            user_data = self.get_user_data(
 
475
                ssl_ca_certificate=ssl_ca_certificate)
469
476
        if not isinstance(user_data, Exception):
470
477
            user_data = dumps(user_data)
471
478
        api_base = "http://169.254.169.254/latest"
537
544
        self.reactor.fire("run")
538
545
 
539
546
        # And the metadata returned determines the URLs that are used
540
 
        self.assertEquals(self.transport.get_url(),
541
 
                          "https://example.com/message-system")
542
 
        self.assertEquals(self.pinger.get_url(),
543
 
                          "http://example.com/ping")
544
 
        # Let's make sure those values were written back to the config file
 
547
        self.assertEqual(self.transport.get_url(),
 
548
                         "https://example.com/message-system")
 
549
        self.assertEqual(self.pinger.get_url(),
 
550
                         "http://example.com/ping")
 
551
        # Lets make sure those values were written back to the config file
545
552
        new_config = BrokerConfiguration()
546
553
        new_config.load_configuration_file(self.config_filename)
547
 
        self.assertEquals(new_config.url, "https://example.com/message-system")
548
 
        self.assertEquals(new_config.ping_url, "http://example.com/ping")
 
554
        self.assertEqual(new_config.url, "https://example.com/message-system")
 
555
        self.assertEqual(new_config.ping_url, "http://example.com/ping")
549
556
 
550
557
        # Okay! Exchange should cause the registration to happen.
551
558
        self.exchanger.exchange()
552
559
        # This *should* be asynchronous, but I think a billion tests are
553
560
        # written like this
554
 
        self.assertEquals(len(self.transport.payloads), 1)
 
561
        self.assertEqual(len(self.transport.payloads), 1)
555
562
        self.assertMessages(
556
563
            self.transport.payloads[0]["messages"],
557
564
            [self.get_expected_cloud_message(tags=u"server,london")])
569
576
        # metadata is fetched and stored at reactor startup:
570
577
        self.reactor.fire("run")
571
578
        self.exchanger.exchange()
572
 
        self.assertEquals(len(self.transport.payloads), 1)
 
579
        self.assertEqual(len(self.transport.payloads), 1)
573
580
        self.assertMessages(self.transport.payloads[0]["messages"],
574
581
                            [self.get_expected_cloud_message(tags=None)])
575
 
        self.assertEquals(self.logfile.getvalue().strip(),
576
 
                          "ERROR: Invalid tags provided for cloud "
577
 
                          "registration.\n    "
578
 
                          "INFO: Queueing message to register with OTP\n    "
579
 
                          "INFO: Starting message exchange with "
580
 
                          "https://example.com/message-system.\n    "
581
 
                          "INFO: Message exchange completed in 0.00s.")
 
582
        self.assertEqual(self.logfile.getvalue().strip(),
 
583
                         "ERROR: Invalid tags provided for cloud "
 
584
                         "registration.\n    "
 
585
                         "INFO: Queueing message to register with OTP\n    "
 
586
                         "INFO: Starting message exchange with "
 
587
                         "https://example.com/message-system.\n    "
 
588
                         "INFO: Message exchange completed in 0.00s.")
 
589
 
 
590
    def test_cloud_registration_with_ssl_ca_certificate(self):
 
591
        """
 
592
        If we have an SSL certificate CA included in the user-data, this should
 
593
        be written out, and the configuration updated to reflect this.
 
594
        """
 
595
        key_filename = os.path.join(self.config.data_path,
 
596
            "%s.ssl_public_key" % os.path.basename(self.config_filename))
 
597
 
 
598
        print_text_mock = self.mocker.replace(print_text)
 
599
        print_text_mock("Writing SSL CA certificate to %s..." %
 
600
                        key_filename)
 
601
        self.mocker.replay()
 
602
        self.prepare_query_results(ssl_ca_certificate=u"1234567890")
 
603
        self.prepare_cloud_registration(tags=u"server,london")
 
604
        # metadata is fetched and stored at reactor startup:
 
605
        self.reactor.fire("run")
 
606
        # And the metadata returned determines the URLs that are used
 
607
        self.assertEqual("https://example.com/message-system",
 
608
                         self.transport.get_url())
 
609
        self.assertEqual(key_filename, self.transport.pubkey)
 
610
        self.assertEqual("http://example.com/ping",
 
611
                         self.pinger.get_url())
 
612
        # Let's make sure those values were written back to the config file
 
613
        new_config = BrokerConfiguration()
 
614
        new_config.load_configuration_file(self.config_filename)
 
615
        self.assertEqual("https://example.com/message-system", new_config.url)
 
616
        self.assertEqual("http://example.com/ping", new_config.ping_url)
 
617
        self.assertEqual(key_filename, new_config.ssl_public_key)
 
618
        self.assertEqual("1234567890", open(key_filename, "r").read())
582
619
 
583
620
    def test_wrong_user_data(self):
584
621
        self.prepare_query_results(user_data="other stuff, not a bpickle")
642
679
        self.reactor.fire("run")
643
680
        self.exchanger.exchange()
644
681
 
645
 
        self.assertEquals(len(self.transport.payloads), 1)
 
682
        self.assertEqual(len(self.transport.payloads), 1)
646
683
        self.assertMessages(self.transport.payloads[0]["messages"],
647
684
                            [self.get_expected_cloud_message(
648
685
                                otp=None,
649
686
                                account_name=u"onward",
650
687
                                registration_password=u"password",
651
688
                                tags=u"london,server")])
652
 
        self.assertEquals(self.logfile.getvalue().strip(),
 
689
        self.assertEqual(self.logfile.getvalue().strip(),
653
690
           "INFO: Queueing message to register with account u'onward' and "
654
691
           "tags london,server as an EC2 instance.\n    "
655
692
           "INFO: Starting message exchange with http://localhost:91919.\n    "
673
710
        self.reactor.fire("pre-exchange")
674
711
 
675
712
        messages = self.mstore.get_pending_messages()
676
 
        self.assertEquals(len(messages), 1)
677
 
        self.assertEquals(messages[0]["type"], "register-cloud-vm")
 
713
        self.assertEqual(len(messages), 1)
 
714
        self.assertEqual(messages[0]["type"], "register-cloud-vm")
678
715
 
679
716
    def test_cloud_registration_fetch_errors(self):
680
717
        """
703
740
        self.log_helper.ignore_errors("Got error while fetching meta-data")
704
741
        self.reactor.fire("run")
705
742
        self.exchanger.exchange()
706
 
        self.assertEquals(failed, [True])
 
743
        self.assertEqual(failed, [True])
707
744
        self.assertIn('error: (7, "couldn\'t connect to host")',
708
745
                      self.logfile.getvalue())
709
746
 
721
758
        self.exchanger.exchange()
722
759
        self.assertIn("HTTPCodeError: Server returned HTTP code 404",
723
760
                      self.logfile.getvalue())
724
 
        self.assertEquals(len(self.transport.payloads), 1)
 
761
        self.assertEqual(len(self.transport.payloads), 1)
725
762
        self.assertMessages(self.transport.payloads[0]["messages"],
726
763
                            [self.get_expected_cloud_message(
727
764
                                otp=None,
741
778
        self.exchanger.exchange()
742
779
        self.assertIn("HTTPCodeError: Server returned HTTP code 404",
743
780
                      self.logfile.getvalue())
744
 
        self.assertEquals(len(self.transport.payloads), 1)
 
781
        self.assertEqual(len(self.transport.payloads), 1)
745
782
        self.assertMessages(self.transport.payloads[0]["messages"],
746
783
                            [self.get_expected_cloud_message(
747
784
                                ramdisk_key=None)])
762
799
        self.exchanger.exchange()
763
800
        self.assertIn("HTTPCodeError: Server returned HTTP code 404",
764
801
                      self.logfile.getvalue())
765
 
        self.assertEquals(len(self.transport.payloads), 1)
 
802
        self.assertEqual(len(self.transport.payloads), 1)
766
803
        self.assertMessages(self.transport.payloads[0]["messages"],
767
804
                            [{"type": "register",
768
805
                              "computer_title": u"whatever",
800
837
 
801
838
        self.reactor.fire("run")
802
839
        self.exchanger.exchange()
803
 
        self.assertEquals(len(self.transport.payloads), 1)
 
840
        self.assertEqual(len(self.transport.payloads), 1)
804
841
        self.assertMessages(self.transport.payloads[0]["messages"],
805
842
                            [self.get_expected_cloud_message(otp=otp,
806
843
                                                             launch_index=1)])
864
901
        self.mocker.replay()
865
902
 
866
903
        self.assertTrue(is_cloud_managed(self.fake_fetch))
867
 
        self.assertEquals(
 
904
        self.assertEqual(
868
905
            self.urls,
869
906
            [(EC2_API + "/user-data", 5),
870
907
             (EC2_API + "/meta-data/ami-launch-index", 5)])