Example #1
0
    def test_takes_lock_when_running(self):
        clock = Clock()
        deferToThread = self.patch(boot_images, "deferToThread")
        deferToThread.return_value = pause(1, clock)

        # Lock is acquired when import is started.
        import_boot_images(sentinel.sources, factory.make_simple_http_url())
        self.assertTrue(concurrency.boot_images.locked)

        # Lock is released once the download is done.
        clock.advance(1)
        self.assertFalse(concurrency.boot_images.locked)
 def test_restarts_maas_rackd_service(self):
     url = factory.make_simple_http_url()
     secret = factory.make_bytes()
     register_command.run(self.make_args(url=url, secret=to_hex(secret)))
     self.assertThat(
         self.mock_call_and_check,
         MockCallsMatch(
             call(["systemctl", "stop", "maas-rackd"]),
             call(["systemctl", "enable", "maas-rackd"]),
             call(["systemctl", "start", "maas-rackd"]),
         ),
     )
Example #3
0
    def test__prompts_user_for_secret(self):
        url = factory.make_simple_http_url()
        expected_previous_value = factory.make_bytes()
        set_shared_secret_on_filesystem(expected_previous_value)
        InstallSharedSecretScript_mock = self.patch(
            register_command, "InstallSharedSecretScript")
        args = self.make_args(url=url, secret=None)
        register_command.run(args)
        observed = get_shared_secret_from_filesystem()

        self.expectThat(expected_previous_value, Equals(observed))
        self.expectThat(InstallSharedSecretScript_mock.run,
                        MockCalledOnceWith(args))
    def test_download_is_initiated_in_new_thread(self):
        clock = Clock()
        maas_meta_last_modified = self.patch(
            tftppath, "maas_meta_last_modified"
        )
        one_week = timedelta(minutes=15).total_seconds()
        maas_meta_last_modified.return_value = clock.seconds() - one_week
        http_proxy = factory.make_simple_http_url()
        https_proxy = factory.make_simple_http_url()
        rpc_client = Mock()
        client_call = Mock()
        client_call.side_effect = [
            defer.succeed(dict(sources=sentinel.sources)),
            defer.succeed(
                dict(http=urlparse(http_proxy), https=urlparse(https_proxy))
            ),
        ]
        rpc_client.getClientNow.return_value = defer.succeed(client_call)
        rpc_client.maas_url = factory.make_simple_http_url()

        # We could patch out 'import_boot_images' instead here but I
        # don't do that for 2 reasons:
        # 1. It requires spinning the reactor again before being able to
        # test the result.
        # 2. It means there's no thread to clean up after the test.
        deferToThread = self.patch(boot_images, "deferToThread")
        deferToThread.return_value = defer.succeed(None)
        service = ImageDownloadService(rpc_client, sentinel.tftp_root, clock)
        service.startService()
        self.assertThat(
            deferToThread,
            MockCalledOnceWith(
                _run_import,
                sentinel.sources,
                rpc_client.maas_url,
                http_proxy=http_proxy,
                https_proxy=https_proxy,
            ),
        )
Example #5
0
 def test_update_last_image_sync_end_to_end_import_not_performed(self):
     fixture = self.useFixture(MockLiveClusterToRegionRPCFixture())
     protocol, connecting = fixture.makeEventLoop(
         region.UpdateLastImageSync)
     protocol.UpdateLastImageSync.return_value = succeed({})
     self.addCleanup((yield connecting))
     self.patch_autospec(boot_resources, 'import_images')
     boot_resources.import_images.return_value = False
     sources, hosts = make_sources()
     maas_url = factory.make_simple_http_url()
     yield boot_images.import_boot_images(sources, maas_url)
     self.assertThat(
         boot_resources.import_images,
         MockCalledOnceWith(fix_sources_for_cluster(sources, maas_url)))
     self.assertThat(protocol.UpdateLastImageSync, MockNotCalled())
Example #6
0
 def test_process_node_tags_integration(self):
     self.useFixture(
         ClusterConfigurationFixture(
             maas_url=factory.make_simple_http_url()))
     get_hw_system1 = factory.make_response(
         http.client.OK,
         bson.BSON.encode({"lshw": b"<node />"}),
         "application/bson",
     )
     get_hw_system2 = factory.make_response(
         http.client.OK,
         bson.BSON.encode({"lshw": b"<not-node />"}),
         "application/bson",
     )
     mock_get = self.patch(MAASClient, "get")
     mock_get.side_effect = [get_hw_system1, get_hw_system2]
     mock_post = self.patch(MAASClient, "post")
     mock_post.return_value = factory.make_response(
         http.client.OK, b'{"added": 1, "removed": 1}', "application/json")
     tag_name = factory.make_name("tag")
     tag_definition = "//lshw:node"
     tag_nsmap = {"lshw": "lshw"}
     rack_id = factory.make_name("rack")
     tags.process_node_tags(
         rack_id,
         [{
             "system_id": "system-id1"
         }, {
             "system_id": "system-id2"
         }],
         tag_name,
         tag_definition,
         tag_nsmap,
         self.fake_client(),
     )
     tag_url = "/MAAS/api/2.0/tags/%s/" % (tag_name, )
     self.assertThat(
         mock_post,
         MockCalledOnceWith(
             tag_url,
             as_json=True,
             op="update_nodes",
             rack_controller=rack_id,
             definition=tag_definition,
             add=["system-id1"],
             remove=["system-id2"],
         ),
     )
Example #7
0
 def test__add_to_waiting_if_lock_already_held(self):
     yield concurrency.boot_images.acquire()
     deferToThread = self.patch(boot_images, 'deferToThread')
     deferToThread.return_value = defer.succeed(None)
     maas_url = factory.make_simple_http_url()
     d = import_boot_images(sentinel.sources, maas_url)
     self.assertEqual(1, len(concurrency.boot_images.waiting))
     concurrency.boot_images.release()
     yield d
     self.assertThat(
         deferToThread,
         MockCalledOnceWith(_run_import,
                            sentinel.sources,
                            maas_url,
                            http_proxy=None,
                            https_proxy=None))
Example #8
0
    def test___prompts_user_for_url(self):
        expected_url = factory.make_simple_http_url()
        secret = factory.make_bytes()

        stdin = self.patch(register_command, "stdin")
        stdin.isatty.return_value = True

        input = self.patch(register_command, "input")
        input.return_value = expected_url

        register_command.run(self.make_args(url=None, secret=to_hex(secret)))
        with ClusterConfiguration.open() as config:
            observed = config.maas_url

        self.expectThat(input,
                        MockCalledOnceWith("MAAS region controller URL: "))
        self.expectThat([expected_url], Equals(observed))
Example #9
0
 def test_update_last_image_sync_always_updated(self):
     get_maas_id = self.patch(boot_images, "get_maas_id")
     get_maas_id.return_value = factory.make_string()
     getRegionClient = self.patch(boot_images, "getRegionClient")
     _run_import = self.patch_autospec(boot_images, '_run_import')
     _run_import.return_value = False
     maas_url = factory.make_simple_http_url()
     yield boot_images._import_boot_images(sentinel.sources, maas_url)
     self.assertThat(
         _run_import,
         MockCalledOnceWith(sentinel.sources, maas_url, None, None))
     self.assertThat(getRegionClient, MockCalledOnceWith())
     self.assertThat(get_maas_id, MockCalledOnceWith())
     client = getRegionClient.return_value
     self.assertThat(
         client,
         MockCalledOnceWith(UpdateLastImageSync, system_id=get_maas_id()))
Example #10
0
 def test_never_more_than_one_waiting(self):
     yield concurrency.boot_images.acquire()
     deferToThread = self.patch(boot_images, "deferToThread")
     deferToThread.return_value = defer.succeed(None)
     maas_url = factory.make_simple_http_url()
     d = import_boot_images(sentinel.sources, maas_url)
     self.assertIsNone(import_boot_images(sentinel.sources, maas_url))
     self.assertEqual(1, len(concurrency.boot_images.waiting))
     concurrency.boot_images.release()
     yield d
     self.assertThat(
         deferToThread,
         MockCalledOnceWith(
             _run_import,
             sentinel.sources,
             maas_url,
             http_proxy=None,
             https_proxy=None,
         ),
     )
Example #11
0
 def test_process_node_tags_integration(self):
     self.useFixture(
         ClusterConfigurationFixture(
             maas_url=factory.make_simple_http_url()))
     get_hw_system1 = factory.make_response(
         http.client.OK,
         bson.BSON.encode({'lshw': b'<node />'}),
         'application/bson',
     )
     get_hw_system2 = factory.make_response(
         http.client.OK,
         bson.BSON.encode({'lshw': b'<not-node />'}),
         'application/bson',
     )
     mock_get = self.patch(MAASClient, 'get')
     mock_get.side_effect = [get_hw_system1, get_hw_system2]
     mock_post = self.patch(MAASClient, 'post')
     mock_post.return_value = factory.make_response(
         http.client.OK,
         b'{"added": 1, "removed": 1}',
         'application/json',
     )
     tag_name = factory.make_name('tag')
     tag_definition = '//lshw:node'
     tag_nsmap = {"lshw": "lshw"}
     rack_id = factory.make_name('rack')
     tags.process_node_tags(rack_id, [{
         "system_id": "system-id1"
     }, {
         "system_id": "system-id2"
     }], tag_name, tag_definition, tag_nsmap, self.fake_client())
     tag_url = '/MAAS/api/2.0/tags/%s/' % (tag_name, )
     self.assertThat(
         mock_post,
         MockCalledOnceWith(tag_url,
                            as_json=True,
                            op='update_nodes',
                            rack_controller=rack_id,
                            definition=tag_definition,
                            add=['system-id1'],
                            remove=['system-id2']))
Example #12
0
 def test_update_last_image_sync_end_to_end(self):
     get_maas_id = self.patch(boot_images, "get_maas_id")
     get_maas_id.return_value = factory.make_string()
     fixture = self.useFixture(MockLiveClusterToRegionRPCFixture())
     protocol, connecting = fixture.makeEventLoop(
         region.UpdateLastImageSync)
     protocol.UpdateLastImageSync.return_value = succeed({})
     self.addCleanup((yield connecting))
     self.patch_autospec(boot_resources, "import_images")
     boot_resources.import_images.return_value = True
     sources, hosts = make_sources()
     maas_url = factory.make_simple_http_url()
     yield boot_images.import_boot_images(sources, maas_url)
     self.assertThat(
         boot_resources.import_images,
         MockCalledOnceWith(fix_sources_for_cluster(sources, maas_url)),
     )
     self.assertThat(
         protocol.UpdateLastImageSync,
         MockCalledOnceWith(protocol, system_id=get_maas_id()),
     )
Example #13
0
 def test__show_service_start_error(self):
     url = factory.make_simple_http_url()
     secret = factory.make_bytes()
     register_command.run(self.make_args(url=url, secret=to_hex(secret)))
     mock_call_and_check = self.patch(register_command, 'call_and_check')
     mock_call_and_check.side_effect = [
         call(),
         call(),
         ExternalProcessError(1, 'systemctl start', 'mock error'),
     ]
     mock_stderr = self.patch(register_command.stderr, 'write')
     with ExpectedException(SystemExit):
         register_command.run(self.make_args(url=url,
                                             secret=to_hex(secret)))
     self.assertThat(
         mock_stderr,
         MockCallsMatch(
             call('Unable to enable and start the maas-rackd service.'),
             call('\n'),
             call('Failed with error: mock error.'),
             call('\n'),
         ))
Example #14
0
 def test__show_service_stop_error(self):
     url = factory.make_simple_http_url()
     secret = factory.make_bytes()
     register_command.run(self.make_args(url=url, secret=to_hex(secret)))
     mock_call_and_check = self.patch(register_command, "call_and_check")
     mock_call_and_check.side_effect = [
         ExternalProcessError(1, "systemctl stop", "mock error"),
         call(),
         call(),
     ]
     mock_stderr = self.patch(register_command.stderr, "write")
     with ExpectedException(SystemExit):
         register_command.run(self.make_args(url=url,
                                             secret=to_hex(secret)))
     self.assertThat(
         mock_stderr,
         MockCallsMatch(
             call("Unable to stop maas-rackd service."),
             call("\n"),
             call("Failed with error: mock error."),
             call("\n"),
         ),
     )
Example #15
0
    def test_accepts_all_args(self):
        all_test_arguments = cluster_config_command.all_arguments

        default_arg_values = {
            '--region-url': None,
            '--uuid': None,
            '--init': False,
            '--tftp-port': None,
            '--tftp-root': None,
            '--debug': None,
        }

        failures = {}

        # Try all cardinalities of combinations of arguments
        for r in range(len(all_test_arguments) + 1):
            for test_arg_names in combinations(all_test_arguments, r):
                test_values = {
                    '--region-url': factory.make_simple_http_url(),
                    '--uuid': str(uuid.uuid4()),
                    '--init': '',
                    '--tftp-port': str(factory.pick_port()),
                    '--tftp-root': factory.make_string(),
                    '--debug': str(factory.pick_bool()),
                }

                # Build a query dictionary for the given combination of args
                args_under_test = []
                for param_name in test_arg_names:
                    args_under_test.append(param_name)
                    if param_name != '--init':
                        args_under_test.append(test_values[param_name])

                parser = ArgumentParser()
                cluster_config_command.add_arguments(parser)

                # If both init and uuid are passed, argparse will generate
                # a nice ArgumentError exception, which unfortunately,
                # gets caught and sent to exit.
                if '--init' in test_arg_names and '--uuid' in test_arg_names:
                    expected_exception = ExpectedException(SystemExit, '2')
                    with expected_exception, patch('sys.stderr'):
                        parser.parse_known_args(args_under_test)

                else:
                    # Otherwise, parsed args with defaults as usual
                    observed_args = vars(parser.parse_args(args_under_test))

                    expected_args = {}
                    for param_name in all_test_arguments:
                        parsed_param_name = param_name[2:].replace('-', '_')

                        if param_name not in test_arg_names:
                            expected_args[parsed_param_name] = \
                                default_arg_values[param_name]
                        else:
                            expected_args[parsed_param_name] = \
                                observed_args[parsed_param_name]

                    if expected_args != observed_args:
                        failures[str(test_arg_names)] = {
                            'expected_args': expected_args,
                            'observed_args': observed_args,
                        }

        error_message = io.StringIO()
        error_message.write("One or more key / value argument list(s)"
                            "passed in the query string (expected_args)"
                            "to the API do not match the values in "
                            "the returned query string. This "
                            "means that some arguments were "
                            "dropped / added / changed by the "
                            "the function, which is incorrect "
                            "behavior. The list of incorrect "
                            "arguments is as follows: \n")
        pp = pprint.PrettyPrinter(depth=3, stream=error_message)
        pp.pprint(failures)
        self.assertDictEqual({}, failures, error_message.getvalue())
Example #16
0
 def test_config_set_maas_url_sets_url(self):
     expected = factory.make_simple_http_url()
     cluster_config_command.run(self.make_args(region_url=expected))
     with ClusterConfiguration.open() as config:
         observed = config.maas_url
     self.assertEqual([expected], observed)
Example #17
0
 def test__deletes_maas_id_file(self):
     self.useFixture(MAASIDFixture(factory.make_string()))
     url = factory.make_simple_http_url()
     secret = factory.make_bytes()
     register_command.run(self.make_args(url=url, secret=to_hex(secret)))
     self.assertIsNone(get_maas_id())
Example #18
0
 def setUp(self):
     super().setUp()
     self.mock_url = factory.make_simple_http_url()
Example #19
0
 def test___sets_secret(self):
     url = factory.make_simple_http_url()
     expected = factory.make_bytes()
     register_command.run(self.make_args(url=url, secret=to_hex(expected)))
     observed = get_shared_secret_from_filesystem()
     self.assertEqual(expected, observed)
Example #20
0
 def test_set_maas_url_accepts_hostnames(self):
     config = ClusterConfiguration({})
     example_url = factory.make_simple_http_url()
     config.maas_url = example_url
     self.assertEqual([example_url], config.maas_url)
     self.assertEqual({"maas_url": [example_url]}, config.store)
Example #21
0
 def setUp(self):
     super(TestEvaluateTag, self).setUp()
     self.mock_url = factory.make_simple_http_url()
Example #22
0
 def setUp(self):
     super(TestEvaluateTag, self).setUp()
     self.mock_url = factory.make_simple_http_url()
     self.useFixture(ClusterConfigurationFixture(maas_url=self.mock_url))
Example #23
0
 def fake_client(self):
     return MAASClient(None, None, factory.make_simple_http_url())
Example #24
0
 def test_allows_ipv4_addresses_in_ipv6_format(self):
     name = "[::ffff:%s]" % factory.make_ipv4_address()
     url = factory.make_simple_http_url(netloc=name,
                                        port=factory.pick_bool())
     self.assertEqual(url, self.validator.to_python(url), "url: %s" % url)
Example #25
0
 def test_run_import_sets_GPGHOME(self):
     home = factory.make_name("home")
     self.patch(boot_images, "get_maas_user_gpghome").return_value = home
     fake = self.patch_boot_resources_function()
     _run_import(sources=[], maas_url=factory.make_simple_http_url())
     self.assertEqual(home, fake.env["GNUPGHOME"])
Example #26
0
 def test_set_maas_url_accepts_hostnames(self):
     config = RegionConfiguration({})
     example_url = factory.make_simple_http_url()
     config.maas_url = example_url
     self.assertEqual(example_url, config.maas_url)
     self.assertEqual({"maas_url": example_url}, config.store)
Example #27
0
 def test_run_import_accepts_sources_parameter(self):
     fake = self.patch(boot_resources, "import_images")
     sources, _ = make_sources()
     _run_import(sources=sources, maas_url=factory.make_simple_http_url())
     self.assertThat(fake, MockCalledOnceWith(sources))
Example #28
0
 def test_run_import_calls_reload_boot_images(self):
     fake_reload = self.patch(boot_images, "reload_boot_images")
     self.patch(boot_resources, "import_images")
     sources, _ = make_sources()
     _run_import(sources=sources, maas_url=factory.make_simple_http_url())
     self.assertThat(fake_reload, MockCalledOnceWith())
Example #29
0
 def test_set_maas_url_rejects_bare_ipv6_addresses(self):
     config = RegionConfiguration({})
     example_url = factory.make_simple_http_url(
         netloc=factory.make_ipv6_address())
     with ExpectedException(formencode.api.Invalid):
         config.maas_url = example_url
Example #30
0
 def test_get_dns_server_address_raises_if_hostname_doesnt_resolve(self):
     url = maastesting_factory.make_simple_http_url()
     self.useFixture(RegionConfigurationFixture(maas_url=url))
     self.patch(zonegenerator, 'get_maas_facing_server_addresses',
                FakeMethod(failure=socket.error))
     self.assertRaises(UnresolvableHost, get_dns_server_address)