def test_send_event_mac_address_stores_event_with_timestamp_received(self): # Use a random time in the recent past and coerce the responder to use # it as the time-stamp for the event. We'll check this later on. timestamp = datetime.now() - timedelta(seconds=randint(99, 99999)) self.patch(regionservice, "datetime").now.return_value = timestamp event_type = factory.make_name("type_name") yield deferToDatabase(self.create_event_type, event_type, "", 0) interface = yield deferToDatabase(self.make_interface) mac_address = interface.mac_address.get_raw() yield eventloop.start() try: yield call_responder( Region(), SendEventMACAddress, { "mac_address": mac_address, "type_name": event_type, "description": factory.make_name("description"), }, ) finally: yield eventloop.reset() event = yield deferToDatabase(self.get_event, mac_address, event_type) self.expectThat(event.created, Equals(timestamp))
def test_returns_proxy_configuration(self): def _db_work(): cidrs = [ factory.make_Subnet(allow_proxy=True).cidr for _ in range(3) ] for _ in range(3): factory.make_Subnet(allow_proxy=False) enabled = factory.pick_bool() Config.objects.set_config("enable_http_proxy", enabled) port = random.randint(1000, 8000) Config.objects.set_config("maas_proxy_port", port) prefer_v4_proxy = factory.pick_bool() Config.objects.set_config("prefer_v4_proxy", prefer_v4_proxy) return cidrs, enabled, port, prefer_v4_proxy cidrs, enabled, port, prefer_v4_proxy = yield deferToDatabase(_db_work) system_id = factory.make_name("id") response = yield call_responder( Region(), GetProxyConfiguration, {"system_id": system_id} ) self.assertThat( response, Equals( { "enabled": enabled, "port": port, "allowed_cidrs": cidrs, "prefer_v4_proxy": prefer_v4_proxy, } ), )
def test_calls_create_node_function(self): create_node_function = self.patch(regionservice, "create_node") create_node_function.return_value = yield deferToDatabase( self.create_node ) params = { "architecture": factory.make_name("arch"), "power_type": factory.make_name("power_type"), "power_parameters": dumps({}), "mac_addresses": [factory.make_mac_address()], "domain": factory.make_name("domain"), "hostname": None, } response = yield call_responder(Region(), CreateNode, params) self.assertIsNotNone(response) self.assertThat( create_node_function, MockCalledOnceWith( params["architecture"], params["power_type"], params["power_parameters"], params["mac_addresses"], domain=params["domain"], hostname=params["hostname"], ), ) self.assertEqual( create_node_function.return_value.system_id, response["system_id"] )
def test_calls_update_services_in_database_thread(self): system_id = factory.make_name("system_id") services = [ { "name": factory.make_name("service"), "status": factory.make_name("status"), "status_info": factory.make_name("status_info"), } ] mock_deferToDatabase = self.patch(regionservice, "deferToDatabase") mock_deferToDatabase.return_value = succeed({}) yield eventloop.start() try: yield call_responder( Region(), UpdateServices, {"system_id": system_id, "services": services}, ) finally: yield eventloop.reset() self.assertThat( mock_deferToDatabase, MockCalledWith(update_services, system_id, services), )
def test_report_boot_images_with_real_things_to_report(self): # tftppath.report_boot_images()'s return value matches the # arguments schema that ReportBootImages declares, and is # serialised correctly. # Example boot image definitions. archs = "i386", "amd64" subarchs = "generic", "special" releases = "precise", "trusty" purposes = "commission", "install" # Create a TFTP file tree with a variety of subdirectories. tftpdir = self.make_dir() for options in product(archs, subarchs, releases, purposes): os.makedirs(os.path.join(tftpdir, *options)) # Ensure that report_boot_images() uses the above TFTP file tree. self.useFixture(ClusterConfigurationFixture(tftp_root=tftpdir)) images = [ {"architecture": arch, "subarchitecture": subarch, "release": release, "purpose": purpose} for arch, subarch, release, purpose in product( archs, subarchs, releases, purposes) ] d = call_responder(Region(), ReportBootImages, { "uuid": factory.make_name("uuid"), "images": images, }) def check(response): self.assertEqual({}, response) return d.addCallback(check)
def test_calls_request_node_info_by_mac_address_function(self): purpose = factory.make_name('purpose') node = yield deferToDatabase(self.create_node) node_info_function = self.patch(regionservice, 'request_node_info_by_mac_address') node_info_function.return_value = (node, purpose) interface = yield deferToDatabase(self.make_interface, node) params = { 'mac_address': interface.mac_address.get_raw(), } response = yield call_responder(Region(), RequestNodeInfoByMACAddress, params) self.assertIsNotNone(response) self.assertThat(node_info_function, MockCalledOnceWith(params['mac_address'])) response_purpose = response.pop('purpose') self.assertEqual(purpose, response_purpose) # Remove the boot_type from the response as node no longer has that # attribute. copy_response = dict(response) del copy_response["boot_type"] self.assertAttributes(node, copy_response) self.assertEquals("fastpath", response["boot_type"])
def test_send_event_logs_if_unknown_node(self): log = self.patch(events_module, 'log') name = factory.make_name('type_name') description = factory.make_name('description') level = random.randint(0, 100) yield deferToDatabase(self.create_event_type, name, description, level) system_id = factory.make_name('system_id') event_description = factory.make_name('event-description') yield eventloop.start() try: yield call_responder( Region(), SendEvent, { 'system_id': system_id, 'type_name': name, 'description': event_description, }) finally: yield eventloop.reset() self.assertThat( log.debug, MockCalledOnceWith( "Event '{type}: {description}' sent for " "non-existent node '{node_id}'.", type=name, description=event_description, node_id=system_id))
def test_send_event_mac_address_does_not_fail_if_unknown_type(self): name = factory.make_name('type_name') mac_address = factory.make_mac_address() description = factory.make_name('description') logger = self.useFixture(TwistedLoggerFixture()) yield eventloop.start() try: yield call_responder( Region(), SendEventMACAddress, { 'mac_address': mac_address, 'type_name': name, 'description': description, }) finally: yield eventloop.reset() # The log records the issue. FIXME: Why reject logs if the type is not # registered? Seems like the region should record all logs and figure # out how to present them. self.assertDocTestMatches( """\ Unhandled failure in database task. Traceback (most recent call last): ... provisioningserver.rpc.exceptions.NoSuchEventType: ... """, logger.output)
def test_identify_reports_event_loop_name(self): d = call_responder(Region(), Identify, {}) def check(response): self.assertEqual({"ident": eventloop.loop.name}, response) return d.addCallback(check)
def test_get_archive_mirrors_with_main_archive_port_archive_default(self): response = yield call_responder(Region(), GetArchiveMirrors, {}) self.assertEqual( { "main": urlparse("http://archive.ubuntu.com/ubuntu"), "ports": urlparse("http://ports.ubuntu.com/ubuntu-ports") }, response)
def test_send_event_stores_event(self): name = factory.make_name('type_name') description = factory.make_name('description') level = random.randint(0, 100) yield deferToDatabase(self.create_event_type, name, description, level) system_id = yield deferToDatabase(self.create_node) event_description = factory.make_name('description') yield eventloop.start() try: response = yield call_responder( Region(), SendEvent, { 'system_id': system_id, 'type_name': name, 'description': event_description, }) finally: yield eventloop.reset() self.assertEqual({}, response) event = yield deferToDatabase(self.get_event, system_id, name) self.expectThat(event.node.system_id, Equals(system_id)) self.expectThat(event.description, Equals(event_description)) self.expectThat(event.type.name, Equals(name))
def test__returns_correct_arguments(self): rack = yield deferToDatabase(self.create_rack_controller, power_type='') nodes = [] for _ in range(3): node = yield deferToDatabase(self.create_node, power_type="virsh", power_state_updated=None, bmc_connected_to=rack) power_params = yield deferToDatabase( self.get_node_power_parameters, node) nodes.append({ 'system_id': node.system_id, 'hostname': node.hostname, 'power_state': node.power_state, 'power_type': node.get_effective_power_type(), 'context': power_params, }) # Create a node with an invalid power type (i.e. the empty string). # This will not be reported by the call to ListNodePowerParameters. yield deferToDatabase(self.create_node, power_type="", power_state_updated=None) response = yield call_responder(Region(), ListNodePowerParameters, {'uuid': rack.system_id}) self.maxDiff = None self.assertItemsEqual(nodes, response['nodes'])
def test_calls_create_node_function(self): create_node_function = self.patch(regionservice, 'create_node') create_node_function.return_value = yield deferToDatabase( self.create_node) params = { 'architecture': factory.make_name('arch'), 'power_type': factory.make_name('power_type'), 'power_parameters': dumps({}), 'mac_addresses': [factory.make_mac_address()], 'domain': factory.make_name('domain'), 'hostname': None, } response = yield call_responder(Region(), CreateNode, params) self.assertIsNotNone(response) self.assertThat( create_node_function, MockCalledOnceWith(params['architecture'], params['power_type'], params['power_parameters'], params['mac_addresses'], domain=params['domain'], hostname=params['hostname'])) self.assertEqual(create_node_function.return_value.system_id, response['system_id'])
def test_send_event_mac_address_stores_event(self): name = factory.make_name('type_name') description = factory.make_name('description') level = random.randint(0, 100) yield deferToDatabase(self.create_event_type, name, description, level) interface = yield deferToDatabase(self.make_interface) mac_address = interface.mac_address event_description = factory.make_name('description') yield eventloop.start() try: response = yield call_responder( Region(), SendEventMACAddress, { 'mac_address': mac_address.get_raw(), 'type_name': name, 'description': event_description, }) finally: yield eventloop.reset() self.assertEqual({}, response) event = yield deferToDatabase(self.get_event, mac_address, name) self.expectThat(event.node.system_id, Equals(interface.node.system_id)) self.expectThat(event.description, Equals(event_description)) self.expectThat(event.type.name, Equals(name))
def test_register_sets_hostIsRemote_calls_rpcRegisterConnection(self): yield self.installFakeRegion() rack_controller = yield deferToDatabase(factory.make_RackController) ipcWorker = MagicMock() protocol = self.make_Region(ipcWorker) protocol.transport = MagicMock() host = IPv4Address( type="TCP", host=factory.make_ipv4_address(), port=random.randint(1, 400), ) protocol.transport.getHost.return_value = host mock_deferToDatabase = self.patch(regionservice, "deferToDatabase") mock_deferToDatabase.side_effect = [succeed(rack_controller)] yield call_responder( protocol, RegisterRackController, { "system_id": rack_controller.system_id, "hostname": rack_controller.hostname, "interfaces": {}, }, ) self.assertTrue(sentinel.host, protocol.hostIsRemote) self.assertThat( ipcWorker.rpcRegisterConnection, MockCalledOnceWith(protocol.connid, protocol.ident, host.host, host.port), )
def test_register_updates_interfaces(self): yield self.installFakeRegion() rack_controller = yield deferToDatabase(factory.make_RackController) protocol = self.make_Region() protocol.transport = MagicMock() nic_name = factory.make_name("eth0") interfaces = { nic_name: { "type": "physical", "mac_address": factory.make_mac_address(), "parents": [], "links": [], "enabled": True, } } response = yield call_responder( protocol, RegisterRackController, { "system_id": rack_controller.system_id, "hostname": rack_controller.hostname, "interfaces": interfaces, }, ) @transactional def has_interface(system_id, nic_name): rack_controller = RackController.objects.get(system_id=system_id) interfaces = rack_controller.interface_set.filter(name=nic_name) self.assertThat(interfaces, HasLength(1)) yield deferToDatabase(has_interface, response["system_id"], nic_name)
def test_get_boot_config_returns_expected_result(self): rack_controller = yield deferToDatabase( transactional(factory.make_RackController)) yield deferToDatabase(make_usable_architecture, self) local_ip = factory.make_ip_address() remote_ip = factory.make_ip_address() response = yield call_responder( Region(), GetBootConfig, { "system_id": rack_controller.system_id, "local_ip": local_ip, "remote_ip": remote_ip, }) self.assertThat( response, ContainsAll([ "arch", "subarch", "osystem", "release", "kernel", "initrd", "boot_dtb", "purpose", "hostname", "domain", "preseed_url", "fs_host", "log_host", "extra_opts", ]))
def test_send_event_mac_address_logs_if_unknown_node(self): log = self.patch(events_module, 'log') name = factory.make_name('type_name') description = factory.make_name('description') level = random.randint(0, 100) yield deferToDatabase(self.create_event_type, name, description, level) mac_address = factory.make_mac_address() event_description = factory.make_name('event-description') yield eventloop.start() try: yield call_responder( Region(), SendEventMACAddress, { 'mac_address': mac_address, 'type_name': name, 'description': event_description, }) finally: yield eventloop.reset() self.assertThat( log.debug, MockCalledOnceWith( "Event '{type}: {description}' sent for non-existent node " "with MAC address '{mac}'.", type=name, description=event_description, mac=mac_address))
def test_register_event_type_does_not_error_for_existing_event_types(self): # This is a regression test for bug 1373357. name = factory.make_name('name') old_description = factory.make_name('old-description') level = random.randint(0, 100) response = yield call_responder( Region(), RegisterEventType, {'name': name, 'description': old_description, 'level': level}) self.assertEqual({}, response) new_description = factory.make_name('new-description') response = yield call_responder( Region(), RegisterEventType, {'name': name, 'description': new_description, 'level': level}) # If we get this far, no error has been raised, even though we # sent a duplicate request for registration. self.assertEqual({}, response)
def test__raises_exception_if_nodegroup_doesnt_exist(self): uuid = factory.make_UUID() d = call_responder( Region(), ListNodePowerParameters, {'uuid': uuid}) return assert_fails_with(d, NoSuchCluster)
def test_calls_refresh(self): rack = yield deferToDatabase(factory.make_RackController) self.patch(regionservice, 'deferToDatabase').return_value = succeed(rack) mock_refresh = self.patch(rack, 'refresh') response = yield call_responder(Region(), RequestRackRefresh, {'system_id': rack.system_id}) self.assertIsNotNone(response) self.assertThat(mock_refresh, MockCalledOnce())
def test_get_proxies_with_http_proxy_not_set(self): # Disable boot source cache signals. self.addCleanup(bootsources.signals.enable) bootsources.signals.disable() yield deferToDatabase(self.set_http_proxy, None) response = yield call_responder(Region(), GetProxies, {}) self.assertEqual({"http": None, "https": None}, response)
def test_get_boot_sources_v2_returns_simplestreams_endpoint(self): uuid = factory.make_name("uuid") d = call_responder(Region(), GetBootSourcesV2, {"uuid": uuid}) def check(response): self.assertEqual({"sources": [get_simplestream_endpoint()]}, response) return d.addCallback(check)
def test_register_creates_new_rack(self): yield self.installFakeRegion() protocol = self.make_Region() protocol.transport = MagicMock() hostname = factory.make_hostname() yield call_responder(protocol, RegisterRackController, { "system_id": None, "hostname": hostname, "interfaces": {}, }) yield deferToDatabase(RackController.objects.get, hostname=hostname)
def test_get_proxies_with_http_proxy_set(self): # Disable boot source cache signals. self.addCleanup(bootsources.signals.enable) bootsources.signals.disable() url = factory.make_parsed_url() yield deferToDatabase(self.set_http_proxy, url.geturl()) response = yield call_responder(Region(), GetProxies, {}) self.assertEqual({"http": url, "https": url}, response)
def test_authenticate_calculates_digest_with_salt(self): message = factory.make_bytes() secret = yield get_shared_secret() args = {"message": message} response = yield call_responder(Region(), Authenticate, args) digest = response["digest"] salt = response["salt"] expected_digest = HMAC(secret, message + salt, sha256).digest() self.assertEqual(expected_digest, digest) self.assertThat(salt, HasLength(16))
def test__changes_power_state(self): power_state = factory.pick_enum(POWER_STATE) node = yield deferToDatabase(self.create_node, power_state) new_state = factory.pick_enum(POWER_STATE, but_not=power_state) yield call_responder( Region(), UpdateNodePowerState, {'system_id': node.system_id, 'power_state': new_state}) db_state = yield deferToDatabase( self.get_node_power_state, node.system_id) self.assertEqual(new_state, db_state)
def test_register_sets_ident(self): yield self.installFakeRegion() rack_controller = yield deferToDatabase(factory.make_RackController) protocol = self.make_Region() protocol.transport = MagicMock() yield call_responder( protocol, RegisterRackController, { "system_id": rack_controller.system_id, "hostname": rack_controller.hostname, "interfaces": {}, }) self.assertEquals(rack_controller.system_id, protocol.ident)
def test_calls_get_controller_type(self): example_response = { "is_region": factory.pick_bool(), "is_rack": factory.pick_bool(), } deferToDatabase = self.patch(regionservice, 'deferToDatabase') deferToDatabase.return_value = succeed(example_response) system_id = factory.make_name("id") response = yield call_responder(Region(), GetControllerType, {'system_id': system_id}) self.assertThat(response, Equals(example_response)) self.assertThat(deferToDatabase, MockCalledOnceWith(get_controller_type, system_id))
def test_StartTLS_returns_nothing(self): # The StartTLS command does some funky things - see _TLSBox and # _LocalArgument for an idea - so the parameters returned from # get_tls_parameters() - the registered responder - don't end up # travelling over the wire as part of an AMP message. However, # the responder is not aware of this, and is called just like # any other. d = call_responder(Region(), amp.StartTLS, {}) def check(response): self.assertEqual({}, response) return d.addCallback(check)