def test_details_refuses_nonworker(self): log_in_as_normal_user(self.client) nodegroup = factory.make_node_group() response = self.make_details_request(self.client, nodegroup) self.assertEqual( httplib.FORBIDDEN, response.status_code, explain_unexpected_response(httplib.FORBIDDEN, response))
def test__accounts_for_reserved_ip_address(self): subnet = factory.make_Subnet(dns_servers=[], gateway_ip="") ip = factory.pick_ip_in_network(subnet.get_ipnetwork()) factory.make_StaticIPAddress( ip=ip, alloc_type=IPADDRESS_TYPE.AUTO, subnet=subnet ) response = self.client.get( get_subnet_uri(subnet), {"op": "reserved_ip_ranges"} ) self.assertEqual( http.client.OK, response.status_code, explain_unexpected_response(http.client.OK, response), ) result = json.loads(response.content.decode(settings.DEFAULT_CHARSET)) self.assertThat( result, Contains( { "start": ip, "end": ip, "purpose": ["assigned-ip"], "num_addresses": 1, } ), )
def test__returns_full_list_for_empty_subnet(self): subnet = factory.make_Subnet( cidr=factory.make_ipv4_network(), dns_servers=[], gateway_ip='') network = subnet.get_ipnetwork() response = self.client.get( get_subnet_uri(subnet), {'op': 'unreserved_ip_ranges'}) self.assertEqual( http.client.OK, response.status_code, explain_unexpected_response(http.client.OK, response)) result = json.loads(response.content.decode(settings.DEFAULT_CHARSET)) expected_addresses = (network.last - network.first + 1) expected_first_address = inet_ntop(network.first + 1) if network.version == 6: # Don't count the IPv6 network address in num_addresses expected_addresses -= 1 expected_last_address = inet_ntop(network.last) else: # Don't count the IPv4 broadcast/network addresses in num_addresses expected_addresses -= 2 expected_last_address = inet_ntop(network.last - 1) self.assertThat(result, Equals([ { "start": expected_first_address, "end": expected_last_address, "num_addresses": expected_addresses, }]))
def test_GET_list_boot_images_denied_if_not_admin(self): rack = factory.make_RackController(owner=factory.make_User()) response = self.client.get(self.get_rack_uri(rack), {'op': 'list_boot_images'}) self.assertEqual( http.client.FORBIDDEN, response.status_code, explain_unexpected_response(http.client.FORBIDDEN, response))
def test_with_deprecated_node_summary_false(self): subnet = factory.make_Subnet() user = factory.make_User() node = factory.make_Node_with_Interface_on_Subnet( subnet=subnet, status=NODE_STATUS.READY) factory.make_StaticIPAddress(alloc_type=IPADDRESS_TYPE.USER_RESERVED, subnet=subnet, user=user) factory.make_StaticIPAddress( alloc_type=IPADDRESS_TYPE.STICKY, subnet=subnet, user=user, interface=node.get_boot_interface(), ) response = self.client.get( get_subnet_uri(subnet), { "op": "ip_addresses", "with_node_summary": "false" }, ) self.assertEqual( http.client.OK, response.status_code, explain_unexpected_response(http.client.OK, response), ) result = json.loads(response.content.decode(settings.DEFAULT_CHARSET)) expected_result = subnet.render_json_for_related_ips( with_username=True, with_summary=False) self.assertThat(result, Equals(expected_result))
def test_details_refuses_nonworker(self): log_in_as_normal_user(self.client) nodegroup = factory.make_node_group() response = self.make_details_request(self.client, nodegroup) self.assertEqual( httplib.FORBIDDEN, response.status_code, explain_unexpected_response(httplib.FORBIDDEN, response))
def test__unreserved_ip_ranges_fails_if_not_logged_in(self): subnet = factory.make_Subnet() response = self.client.get(get_subnet_uri(subnet), {'op': 'unreserved_ip_ranges'}) self.assertEqual( http.client.UNAUTHORIZED, response.status_code, explain_unexpected_response(http.client.UNAUTHORIZED, response))
def test__returns_empty_list_for_empty_ipv4_subnet(self): subnet = factory.make_Subnet(version=4, dns_servers=[], gateway_ip='') response = self.client.get(get_subnet_uri(subnet), {'op': 'reserved_ip_ranges'}) self.assertEqual(http.client.OK, response.status_code, explain_unexpected_response(http.client.OK, response)) result = json.loads(response.content.decode(settings.DEFAULT_CHARSET)) self.assertThat(result, Equals([]))
def test_import_boot_images_denied_if_not_admin(self): user = factory.make_user() client = OAuthAuthenticatedClient(user) response = client.post( reverse('nodegroups_handler'), {'op': 'import_boot_images'}) self.assertEqual( httplib.FORBIDDEN, response.status_code, explain_unexpected_response(httplib.FORBIDDEN, response))
def test_import_boot_images_denied_if_not_admin(self): user = factory.make_user() client = OAuthAuthenticatedClient(user) response = client.post(reverse('nodegroups_handler'), {'op': 'import_boot_images'}) self.assertEqual( httplib.FORBIDDEN, response.status_code, explain_unexpected_response(httplib.FORBIDDEN, response))
def test__accounts_for_reserved_ip_address(self): subnet = factory.make_ipv4_Subnet_with_IPRanges( with_dynamic_range=False, dns_servers=[], with_router=False ) network = subnet.get_ipnetwork() # Pick an address in the middle of the range. (that way we'll always # expect there to be two unreserved ranges, arranged around the # allocated IP address.) middle_ip = (network.first + network.last) // 2 ip = inet_ntop(middle_ip) factory.make_StaticIPAddress( ip=ip, alloc_type=IPADDRESS_TYPE.AUTO, subnet=subnet ) expected_addresses = network.last - network.first + 1 expected_first_address = inet_ntop(network.first + 1) first_range_end = inet_ntop(middle_ip - 1) first_range_size = middle_ip - network.first - 1 second_range_start = inet_ntop(middle_ip + 1) if network.version == 6: # Don't count the IPv6 network address in num_addresses expected_addresses -= 1 expected_last_address = inet_ntop(network.last) second_range_size = network.last - middle_ip else: # Don't count the IPv4 broadcast/network addresses in num_addresses expected_addresses -= 2 expected_last_address = inet_ntop(network.last - 1) second_range_size = network.last - middle_ip - 1 response = self.client.get( get_subnet_uri(subnet), {"op": "unreserved_ip_ranges"} ) self.assertEqual( http.client.OK, response.status_code, explain_unexpected_response(http.client.OK, response), ) result = json.loads(response.content.decode(settings.DEFAULT_CHARSET)) self.assertThat( result, Equals( [ { "start": expected_first_address, "end": first_range_end, "num_addresses": first_range_size, }, { "start": second_range_start, "end": expected_last_address, "num_addresses": second_range_size, }, ] ), "Reserved ranges: %s" % (subnet.get_ipranges_in_use()), )
def test_GET_describe_power_types(self): get_all_power_types_from_racks = self.patch( rackcontrollers, "get_all_power_types_from_racks") self.become_admin() response = self.client.get(self.get_rack_uri(), {'op': 'describe_power_types'}) self.assertEqual(http.client.OK, response.status_code, explain_unexpected_response(http.client.OK, response)) self.assertThat(get_all_power_types_from_racks, MockCalledOnce())
def test_GET_list_boot_images(self): rack = factory.make_RackController(owner=factory.make_User()) self.become_admin() response = self.client.get(self.get_rack_uri(rack), {'op': 'list_boot_images'}) self.assertEqual(http.client.OK, response.status_code, explain_unexpected_response(http.client.OK, response)) self.assertItemsEqual(['connected', 'images', 'status'], json_load_bytes(response.content).keys())
def test_update_leases_does_not_work_for_normal_user(self): nodegroup = factory.make_node_group() log_in_as_normal_user(self.client) response = self.client.post( reverse('nodegroup_handler', args=[nodegroup.uuid]), {'op': 'update_leases', 'leases': json.dumps({})}) self.assertEqual( httplib.FORBIDDEN, response.status_code, explain_unexpected_response(httplib.FORBIDDEN, response))
def test_GET_describe_power_types_denied_if_not_admin(self): get_all_power_types_from_racks = self.patch( rackcontrollers, "get_all_power_types_from_racks") response = self.client.get(self.get_rack_uri(), {'op': 'describe_power_types'}) self.assertEqual( http.client.FORBIDDEN, response.status_code, explain_unexpected_response(http.client.FORBIDDEN, response)) self.assertThat(get_all_power_types_from_racks, MockNotCalled())
def test_POST_import_boot_images_denied_if_not_admin(self): rack = factory.make_RackController(owner=factory.make_User()) response = self.client.post(self.get_rack_uri(rack), {"op": "import_boot_images"}) self.assertEqual( http.client.FORBIDDEN, response.status_code, explain_unexpected_response(http.client.FORBIDDEN, response), )
def test_update_leases_works_for_nodegroup_worker(self): nodegroup = factory.make_node_group() client = make_worker_client(nodegroup) response = client.post( reverse('nodegroup_handler', args=[nodegroup.uuid]), {'op': 'update_leases', 'leases': json.dumps({})}) self.assertEqual( httplib.OK, response.status_code, explain_unexpected_response(httplib.OK, response))
def test_update_leases_works_for_nodegroup_worker(self): nodegroup = factory.make_node_group() client = make_worker_client(nodegroup) response = client.post( reverse('nodegroup_handler', args=[nodegroup.uuid]), { 'op': 'update_leases', 'leases': json.dumps({}) }) self.assertEqual(httplib.OK, response.status_code, explain_unexpected_response(httplib.OK, response))
def test__returns_reserved_anycast_for_empty_ipv6_subnet(self): subnet = factory.make_Subnet(version=6, dns_servers=[], gateway_ip='') response = self.client.get(get_subnet_uri(subnet), {'op': 'reserved_ip_ranges'}) self.assertEqual(http.client.OK, response.status_code, explain_unexpected_response(http.client.OK, response)) result = json.loads(response.content.decode(settings.DEFAULT_CHARSET)) self.assertThat(result, HasLength(1)) self.assertThat(result[0]["num_addresses"], Equals(1)) self.assertThat(result[0]["purpose"], Contains("rfc-4291-2.6.1"))
def test_nodegroup_list_nodes_does_not_work_for_normal_user(self): nodegroup = factory.make_node_group() log_in_as_normal_user(self.client) response = self.client.get( reverse('nodegroup_handler', args=[nodegroup.uuid]), {'op': 'list_nodes'}) self.assertEqual( httplib.FORBIDDEN, response.status_code, explain_unexpected_response(httplib.FORBIDDEN, response))
def test_update_leases_does_not_work_for_normal_user(self): nodegroup = factory.make_node_group() log_in_as_normal_user(self.client) response = self.client.post( reverse('nodegroup_handler', args=[nodegroup.uuid]), { 'op': 'update_leases', 'leases': json.dumps({}) }) self.assertEqual( httplib.FORBIDDEN, response.status_code, explain_unexpected_response(httplib.FORBIDDEN, response))
def test_POST_import_boot_images_import_to_rack_controllers(self): from maasserver.clusterrpc import boot_images self.patch(boot_images, "RackControllersImporter") self.become_admin() rack = factory.make_RackController(owner=factory.make_User()) response = self.client.post(self.get_rack_uri(rack), {'op': 'import_boot_images'}) self.assertEqual(http.client.OK, response.status_code, explain_unexpected_response(http.client.OK, response)) self.assertThat(boot_images.RackControllersImporter.schedule, MockCalledOnceWith(rack.system_id))
def test_nodegroup_list_nodes_does_not_work_for_normal_user(self): nodegroup = factory.make_node_group() log_in_as_normal_user(self.client) response = self.client.get( reverse('nodegroup_handler', args=[nodegroup.uuid]), {'op': 'list_nodes'}) self.assertEqual( httplib.FORBIDDEN, response.status_code, explain_unexpected_response(httplib.FORBIDDEN, response))
def test_DELETE_cannot_delete_if_primary_rack(self): self.become_admin() vlan = factory.make_VLAN() rack = factory.make_RackController(vlan=vlan) vlan.dhcp_on = True vlan.primary_rack = rack vlan.save() response = self.client.delete(self.get_rack_uri(rack)) self.assertEqual( http.client.BAD_REQUEST, response.status_code, explain_unexpected_response(http.client.BAD_REQUEST, response))
def test_update_leases_does_not_let_worker_update_other_nodegroup(self): requesting_nodegroup = factory.make_node_group() about_nodegroup = factory.make_node_group() client = make_worker_client(requesting_nodegroup) response = client.post( reverse('nodegroup_handler', args=[about_nodegroup.uuid]), {'op': 'update_leases', 'leases': json.dumps({})}) self.assertEqual( httplib.FORBIDDEN, response.status_code, explain_unexpected_response(httplib.FORBIDDEN, response))
def _unreserved_ip_ranges_empty(self, subnet, first_address, last_address): """ Used by the succeeding three tests to prevent duplicating the boilerplate that creates the requested range, then makes sure the unreserved_ip_ranges API call successfully returns an empty list. """ factory.make_IPRange(subnet, first_address, last_address) response = self.client.get(get_subnet_uri(subnet), {'op': 'unreserved_ip_ranges'}) result = json.loads(response.content.decode(settings.DEFAULT_CHARSET)) self.assertEqual(http.client.OK, response.status_code, explain_unexpected_response(http.client.OK, response)) self.assertThat(result, Equals([]), str(subnet.get_ipranges_in_use()))
def test_POST_report_download_progress_does_not_work_for_normal_user(self): nodegroup = factory.make_node_group() log_in_as_normal_user(self.client) response = self.client.post( reverse('nodegroup_handler', args=[nodegroup.uuid]), { 'op': 'report_download_progress', 'filename': factory.getRandomString(), }) self.assertEqual( httplib.FORBIDDEN, response.status_code, explain_unexpected_response(httplib.FORBIDDEN, response))
def test_nodegroup_list_nodes_works_for_nodegroup_worker(self): nodegroup = factory.make_node_group() node = factory.make_node(nodegroup=nodegroup) client = make_worker_client(nodegroup) response = client.get( reverse('nodegroup_handler', args=[nodegroup.uuid]), {'op': 'list_nodes'}) self.assertEqual(httplib.OK, response.status_code, explain_unexpected_response(httplib.OK, response)) parsed_result = json.loads(response.content) self.assertItemsEqual([node.system_id], parsed_result)
def test_report_download_progress_rejects_invalid_data(self): progress = factory.make_download_progress_incomplete() client = make_worker_client(progress.nodegroup) response = client.post( reverse('nodegroup_handler', args=[progress.nodegroup.uuid]), { 'op': 'report_download_progress', 'filename': progress.filename, 'bytes_downloaded': -1, }) self.assertEqual( httplib.BAD_REQUEST, response.status_code, explain_unexpected_response(httplib.BAD_REQUEST, response))
def test_POST_report_download_progress_works_for_nodegroup_worker(self): nodegroup = factory.make_node_group() filename = factory.getRandomString() client = make_worker_client(nodegroup) response = client.post( reverse('nodegroup_handler', args=[nodegroup.uuid]), { 'op': 'report_download_progress', 'filename': filename, }) self.assertEqual(httplib.OK, response.status_code, explain_unexpected_response(httplib.OK, response))
def test__default_does_not_include_ranges(self): subnet = factory.make_Subnet() factory.make_StaticIPAddress(alloc_type=IPADDRESS_TYPE.USER_RESERVED, subnet=subnet) response = self.client.get(get_subnet_uri(subnet), { 'op': 'statistics', }) self.assertEqual(http.client.OK, response.status_code, explain_unexpected_response(http.client.OK, response)) result = json.loads(response.content.decode(settings.DEFAULT_CHARSET)) full_iprange = subnet.get_iprange_usage() statistics = IPRangeStatistics(full_iprange) expected_result = statistics.render_json(include_ranges=False) self.assertThat(result, Equals(expected_result))
def test_POST_report_download_progress_does_not_work_for_normal_user(self): nodegroup = factory.make_node_group() log_in_as_normal_user(self.client) response = self.client.post( reverse('nodegroup_handler', args=[nodegroup.uuid]), { 'op': 'report_download_progress', 'filename': factory.getRandomString(), }) self.assertEqual( httplib.FORBIDDEN, response.status_code, explain_unexpected_response(httplib.FORBIDDEN, response))
def test_update_leases_does_not_let_worker_update_other_nodegroup(self): requesting_nodegroup = factory.make_node_group() about_nodegroup = factory.make_node_group() client = make_worker_client(requesting_nodegroup) response = client.post( reverse('nodegroup_handler', args=[about_nodegroup.uuid]), { 'op': 'update_leases', 'leases': json.dumps({}) }) self.assertEqual( httplib.FORBIDDEN, response.status_code, explain_unexpected_response(httplib.FORBIDDEN, response))
def test_nodegroup_list_nodes_works_for_nodegroup_worker(self): nodegroup = factory.make_node_group() node = factory.make_node(nodegroup=nodegroup) client = make_worker_client(nodegroup) response = client.get( reverse('nodegroup_handler', args=[nodegroup.uuid]), {'op': 'list_nodes'}) self.assertEqual( httplib.OK, response.status_code, explain_unexpected_response(httplib.OK, response)) parsed_result = json.loads(response.content) self.assertItemsEqual([node.system_id], parsed_result)
def test_report_download_progress_rejects_invalid_data(self): progress = factory.make_download_progress_incomplete() client = make_worker_client(progress.nodegroup) response = client.post( reverse('nodegroup_handler', args=[progress.nodegroup.uuid]), { 'op': 'report_download_progress', 'filename': progress.filename, 'bytes_downloaded': -1, }) self.assertEqual( httplib.BAD_REQUEST, response.status_code, explain_unexpected_response(httplib.BAD_REQUEST, response))
def test_DELETE_force_not_required_for_pod_region_rack(self): self.become_admin() vlan = factory.make_VLAN() factory.make_Subnet(vlan=vlan) rack = factory.make_RegionRackController(vlan=vlan) ip = factory.make_StaticIPAddress(interface=rack.interface_set.first()) factory.make_Pod(ip_address=ip) mock_async_delete = self.patch(Pod, "async_delete") response = self.client.delete(self.get_region_uri(rack), QUERY_STRING=urlencode({'force': 'true'}, doseq=True)) self.assertEqual( http.client.NO_CONTENT, response.status_code, explain_unexpected_response(http.client.NO_CONTENT, response)) self.assertThat(mock_async_delete, MockNotCalled())
def test_pod_DELETE_delete_without_force(self): self.become_admin() vlan = factory.make_VLAN() subnet = factory.make_Subnet(vlan=vlan) region = factory.make_Node_with_Interface_on_Subnet( node_type=NODE_TYPE.REGION_CONTROLLER, subnet=subnet, vlan=vlan) ip = factory.make_StaticIPAddress( interface=region.interface_set.first()) factory.make_Pod(ip_address=ip) mock_async_delete = self.patch(Pod, "async_delete") response = self.client.delete(self.get_region_uri(region)) self.assertEqual( http.client.BAD_REQUEST, response.status_code, explain_unexpected_response(http.client.BAD_REQUEST, response)) self.assertThat(mock_async_delete, MockNotCalled())
def test_POST_report_download_progress_does_work_for_other_cluster(self): filename = factory.getRandomString() client = make_worker_client(factory.make_node_group()) response = client.post( reverse( 'nodegroup_handler', args=[factory.make_node_group().uuid]), { 'op': 'report_download_progress', 'filename': filename, }) self.assertEqual( httplib.FORBIDDEN, response.status_code, explain_unexpected_response(httplib.FORBIDDEN, response))
def test_nodegroup_import_boot_images_calls_script(self): recorder = self.patch(tasks, 'call_and_check') proxy = factory.getRandomString() Config.objects.set_config('http_proxy', proxy) nodegroup = factory.make_node_group() admin = factory.make_admin() client = OAuthAuthenticatedClient(admin) response = client.post( reverse('nodegroup_handler', args=[nodegroup.uuid]), {'op': 'import_boot_images'}) self.assertEqual(httplib.OK, response.status_code, explain_unexpected_response(httplib.OK, response)) recorder.assert_called_once_with( ['sudo', '-n', '-E', 'maas-import-pxe-files'], env=ANY)
def test_pod_DELETE_delete_without_force(self): self.become_admin() vlan = factory.make_VLAN() factory.make_Subnet(vlan=vlan) rack = factory.make_RackController(vlan=vlan) ip = factory.make_StaticIPAddress(interface=rack.interface_set.first()) factory.make_Pod(ip_address=ip) vlan.dhcp_on = True vlan.primary_rack = rack vlan.save() mock_async_delete = self.patch(Pod, "async_delete") response = self.client.delete(self.get_rack_uri(rack)) self.assertEqual( http.client.BAD_REQUEST, response.status_code, explain_unexpected_response(http.client.BAD_REQUEST, response)) self.assertThat(mock_async_delete, MockNotCalled())
def test_nodegroup_import_boot_images_calls_script(self): recorder = self.patch(tasks, 'call_and_check') proxy = factory.getRandomString() Config.objects.set_config('http_proxy', proxy) nodegroup = factory.make_node_group() admin = factory.make_admin() client = OAuthAuthenticatedClient(admin) response = client.post( reverse('nodegroup_handler', args=[nodegroup.uuid]), {'op': 'import_boot_images'}) self.assertEqual( httplib.OK, response.status_code, explain_unexpected_response(httplib.OK, response)) recorder.assert_called_once_with( ['sudo', '-n', '-E', 'maas-import-pxe-files'], env=ANY)
def test_report_download_progress_updates_ongoing_download(self): progress = factory.make_download_progress_incomplete() client = make_worker_client(progress.nodegroup) new_bytes_downloaded = progress.bytes_downloaded + 1 response = client.post( reverse('nodegroup_handler', args=[progress.nodegroup.uuid]), { 'op': 'report_download_progress', 'filename': progress.filename, 'bytes_downloaded': new_bytes_downloaded, }) self.assertEqual( httplib.OK, response.status_code, explain_unexpected_response(httplib.OK, response)) progress = reload_object(progress) self.assertEqual(new_bytes_downloaded, progress.bytes_downloaded)
def test_report_download_progress_accepts_new_download(self): nodegroup = factory.make_node_group() filename = factory.getRandomString() client = make_worker_client(nodegroup) response = client.post( reverse('nodegroup_handler', args=[nodegroup.uuid]), { 'op': 'report_download_progress', 'filename': filename, }) self.assertEqual( httplib.OK, response.status_code, explain_unexpected_response(httplib.OK, response)) progress = DownloadProgress.objects.get(nodegroup=nodegroup) self.assertEqual(nodegroup, progress.nodegroup) self.assertEqual(filename, progress.filename) self.assertIsNone(progress.size) self.assertIsNone(progress.bytes_downloaded) self.assertEqual('', progress.error)
def test_import_boot_images_calls_script_for_all_accepted_clusters(self): recorder = self.patch(nodegroup_module, 'import_boot_images') proxy = factory.make_name('proxy') Config.objects.set_config('http_proxy', proxy) accepted_nodegroups = [ factory.make_node_group(status=NODEGROUP_STATUS.ACCEPTED), factory.make_node_group(status=NODEGROUP_STATUS.ACCEPTED), ] factory.make_node_group(status=NODEGROUP_STATUS.REJECTED) factory.make_node_group(status=NODEGROUP_STATUS.PENDING) admin = factory.make_admin() client = OAuthAuthenticatedClient(admin) response = client.post( reverse('nodegroups_handler'), {'op': 'import_boot_images'}) self.assertEqual( httplib.OK, response.status_code, explain_unexpected_response(httplib.OK, response)) queues = [ kwargs['queue'] for args, kwargs in recorder.apply_async.call_args_list] self.assertItemsEqual( [nodegroup.work_queue for nodegroup in accepted_nodegroups], queues)