def test_returns_null_details_when_there_are_none(self): nodes = [factory.make_node(), factory.make_node()] expected = { node.system_id: {"lshw": None, "lldp": None} for node in nodes } self.assertDictEqual(expected, self.get_details(nodes))
def test_signaling_commissioning_result_does_not_affect_other_node(self): node = factory.make_node(status=NODE_STATUS.COMMISSIONING) client = make_node_client(node=factory.make_node( status=NODE_STATUS.COMMISSIONING)) response = call_signal(client, status='OK') self.assertEqual(httplib.OK, response.status_code) self.assertEqual(NODE_STATUS.COMMISSIONING, reload_object(node).status)
def test_GET_list_allocated_returns_only_allocated_with_user_token(self): # If the user's allocated nodes have different session tokens, # list_allocated should only return the nodes that have the # current request's token on them. node_1 = factory.make_node( status=NODE_STATUS.ALLOCATED, owner=self.logged_in_user, token=get_auth_tokens(self.logged_in_user)[0]) second_token = create_auth_token(self.logged_in_user) factory.make_node( owner=self.logged_in_user, status=NODE_STATUS.ALLOCATED, token=second_token) user_2 = factory.make_user() create_auth_token(user_2) factory.make_node( owner=self.logged_in_user, status=NODE_STATUS.ALLOCATED, token=second_token) # At this point we have two nodes owned by the same user but # allocated with different tokens, and a third node allocated to # someone else entirely. We expect list_allocated to # return the node with the same token as the one used in # self.client, which is the one we set on node_1 above. response = self.client.get(reverse('nodes_handler'), { 'op': 'list_allocated'}) self.assertEqual(httplib.OK, response.status_code) parsed_result = json.loads(response.content) self.assertItemsEqual( [node_1.system_id], extract_system_ids(parsed_result))
def test_GET_list_allocated_returns_only_allocated_with_user_token(self): # If the user's allocated nodes have different session tokens, # list_allocated should only return the nodes that have the # current request's token on them. node_1 = factory.make_node(status=NODE_STATUS.ALLOCATED, owner=self.logged_in_user, token=get_auth_tokens( self.logged_in_user)[0]) second_token = create_auth_token(self.logged_in_user) factory.make_node(owner=self.logged_in_user, status=NODE_STATUS.ALLOCATED, token=second_token) user_2 = factory.make_user() create_auth_token(user_2) factory.make_node(owner=self.logged_in_user, status=NODE_STATUS.ALLOCATED, token=second_token) # At this point we have two nodes owned by the same user but # allocated with different tokens, and a third node allocated to # someone else entirely. We expect list_allocated to # return the node with the same token as the one used in # self.client, which is the one we set on node_1 above. response = self.client.get(reverse('nodes_handler'), {'op': 'list_allocated'}) self.assertEqual(httplib.OK, response.status_code) parsed_result = json.loads(response.content) self.assertItemsEqual([node_1.system_id], extract_system_ids(parsed_result))
def test_POST_acquire_fails_with_invalid_mem(self): # Asking for an invalid amount of memory returns a bad request. factory.make_node(status=NODE_STATUS.READY) response = self.client.post(reverse('nodes_handler'), { 'op': 'acquire', 'mem': 'bags', }) self.assertResponseCode(httplib.BAD_REQUEST, response)
def test_POST_acquire_allocates_node_by_zone_fails_if_no_node(self): factory.make_node(status=NODE_STATUS.READY) zone = factory.make_zone() response = self.client.post(reverse('nodes_handler'), { 'op': 'acquire', 'zone': zone.name, }) self.assertResponseCode(httplib.CONFLICT, response)
def test_POST_acquire_treats_unknown_arch_as_bad_request(self): # Asking for an unknown arch returns an HTTP "400 Bad Request" factory.make_node(status=NODE_STATUS.READY) response = self.client.post(reverse('nodes_handler'), { 'op': 'acquire', 'arch': 'sparc', }) self.assertEqual(httplib.BAD_REQUEST, response.status_code)
def test_signaling_commissioning_result_does_not_affect_other_node(self): node = factory.make_node(status=NODE_STATUS.COMMISSIONING) client = self.make_node_client( node=factory.make_node(status=NODE_STATUS.COMMISSIONING)) response = self.call_signal(client, status='OK') self.assertEqual(httplib.OK, response.status_code) self.assertEqual( NODE_STATUS.COMMISSIONING, reload_object(node).status)
def test_applies_tags_to_nodes(self): node1 = factory.make_node() node1.set_hardware_details('<node><child /></node>') node2 = factory.make_node() node2.set_hardware_details('<node />') tag = factory.make_tag(definition='/node/child') self.assertItemsEqual([tag.name], node1.tag_names()) self.assertItemsEqual([], node2.tag_names())
def test_cpu_count(self): node1 = factory.make_node(cpu_count=1) node2 = factory.make_node(cpu_count=2) nodes = [node1, node2] self.assertConstrainedNodes(nodes, {'cpu_count': '0'}) self.assertConstrainedNodes(nodes, {'cpu_count': '1.0'}) self.assertConstrainedNodes([node2], {'cpu_count': '2'}) self.assertConstrainedNodes([], {'cpu_count': '4'})
def test_node_list_contains_column_sort_links(self): # Just create a node to have something in the list factory.make_node() response = self.client.get(reverse('node-list')) sort_hostname = '?sort=hostname&dir=asc' sort_status = '?sort=status&dir=asc' self.assertIn(sort_hostname, get_content_links(response)) self.assertIn(sort_status, get_content_links(response))
def test_applies_tags_to_nodes(self): node1 = factory.make_node() inject_lshw_result(node1, b'<node><child /></node>') node2 = factory.make_node() inject_lshw_result(node2, b'<node />') tag = factory.make_tag(definition='//node/child') self.assertItemsEqual([tag.name], node1.tag_names()) self.assertItemsEqual([], node2.tag_names())
def test_get_preseed_type_for(self): normal = factory.make_node() normal.use_traditional_installer() fpi = factory.make_node() fpi.use_fastpath_installer() self.assertEqual(PRESEED_TYPE.DEFAULT, get_preseed_type_for(normal)) self.assertEqual(PRESEED_TYPE.CURTIN, get_preseed_type_for(fpi))
def test_memory(self): node1 = factory.make_node(memory=1024) node2 = factory.make_node(memory=4096) self.assertConstrainedNodes([node1, node2], {'mem': '512'}) self.assertConstrainedNodes([node1, node2], {'mem': '1024'}) self.assertConstrainedNodes([node2], {'mem': '2048'}) self.assertConstrainedNodes([node2], {'mem': '4096'}) self.assertConstrainedNodes([], {'mem': '8192'}) self.assertConstrainedNodes([node2], {'mem': '4096.0'})
def test_get_available_node_for_acquisition_ignores_taken_nodes(self): user = factory.make_user() available_status = NODE_STATUS.READY unavailable_statuses = ( set(NODE_STATUS_CHOICES_DICT) - set([available_status])) for status in unavailable_statuses: factory.make_node(status=status) self.assertEqual( None, Node.objects.get_available_node_for_acquisition(user))
def test_get_available_nodes_ignores_taken_nodes(self): user = factory.make_user() available_status = NODE_STATUS.READY unavailable_statuses = ( set(NODE_STATUS_CHOICES_DICT) - set([available_status])) for status in unavailable_statuses: factory.make_node(status=status) self.assertEqual( [], list(Node.objects.get_available_nodes_for_acquisition(user)))
def test_migrate_all_nodes_to_new_legacy_user_when_multiple_users(self): factory.make_file_storage(owner=None) user1 = factory.make_user() node1 = factory.make_node(owner=user1) user2 = factory.make_user() node2 = factory.make_node(owner=user2) migrate() self.assertNotIn(reload_object(node1).owner, {user1, user2, None}) self.assertNotIn(reload_object(node2).owner, {user1, user2, None})
def test_returns_null_details_when_there_are_none(self): nodes = [factory.make_node(), factory.make_node()] expected = { node.system_id: { "lshw": None, "lldp": None } for node in nodes } self.assertDictEqual(expected, self.get_details(nodes))
def test_returns_only_those_details_that_exist(self): nodes = [factory.make_node(), factory.make_node()] expected = { node.system_id: { "lshw": make_lshw_result(node, b"<node%d/>" % index).data, "lldp": None, } for index, node in enumerate(nodes) } self.assertDictEqual(expected, self.get_details(nodes))
def test_POST_accept_fails_if_node_does_not_exist(self): self.become_admin() # Make sure there is a node, it just isn't the one being accepted factory.make_node() node_id = factory.getRandomString() response = self.client.post( reverse('nodes_handler'), {'op': 'accept', 'nodes': [node_id]}) self.assertEqual( (httplib.BAD_REQUEST, "Unknown node(s): %s." % node_id), (response.status_code, response.content))
def test_GET_list_with_agent_name_filters_with_empty_string(self): factory.make_node(agent_name=factory.make_name('agent-name')) node = factory.make_node(agent_name='') response = self.client.get(reverse('nodes_handler'), { 'op': 'list', 'agent_name': '', }) self.assertEqual(httplib.OK, response.status_code) parsed_result = json.loads(response.content) self.assertSequenceEqual([node.system_id], extract_system_ids(parsed_result))
def test_GET_list_lists_nodes(self): # The api allows for fetching the list of Nodes. node1 = factory.make_node() node2 = factory.make_node(status=NODE_STATUS.ALLOCATED, owner=self.logged_in_user) response = self.client.get(reverse('nodes_handler'), {'op': 'list'}) parsed_result = json.loads(response.content) self.assertEqual(httplib.OK, response.status_code) self.assertItemsEqual([node1.system_id, node2.system_id], extract_system_ids(parsed_result))
def test_start_commissioning_ignores_other_commissioning_results(self): node = factory.make_node() filename = factory.getRandomString() data = factory.getRandomBytes() script_result = random.randint(0, 10) NodeCommissionResult.objects.store_data( node, filename, script_result, Bin(data)) other_node = factory.make_node(status=NODE_STATUS.DECLARED) other_node.start_commissioning(factory.make_admin()) self.assertEqual( data, NodeCommissionResult.objects.get_data(node, filename))
def test_returns_only_details_from_okay_commissioning_results(self): nodes = [factory.make_node(), factory.make_node()] expected = {} for index, node in enumerate(nodes): make_lshw_result(node, b"<node%d/>" % index) make_lldp_result(node, b"<node%d/>" % index, script_result=1) expected[node.system_id] = { "lshw": b"<node%d/>" % index, "lldp": None, } self.assertDictEqual(expected, self.get_details(nodes))
def test_connected_to(self): mac1 = MAC('aa:bb:cc:dd:ee:ff') mac2 = MAC('00:11:22:33:44:55') node1 = factory.make_node(routers=[mac1, mac2]) node2 = factory.make_node(routers=[mac1]) factory.make_node() self.assertConstrainedNodes( [node1], {'connected_to': [ mac1.get_raw(), mac2.get_raw()]}) self.assertConstrainedNodes( [node1, node2], {'connected_to': [mac1.get_raw()]})
def test_doesnt_touch_other_tags(self): node1 = factory.make_node() inject_lshw_result(node1, b'<node><foo /></node>') node2 = factory.make_node() inject_lshw_result(node2, b'<node><bar /></node>') tag1 = factory.make_tag(definition='//node/foo') self.assertItemsEqual([tag1.name], node1.tag_names()) self.assertItemsEqual([], node2.tag_names()) tag2 = factory.make_tag(definition='//node/bar') self.assertItemsEqual([tag1.name], node1.tag_names()) self.assertItemsEqual([tag2.name], node2.tag_names())
def test_memory(self): node1 = factory.make_node(memory=1024) node2 = factory.make_node(memory=4096) self.assertConstrainedNodes([node1, node2], {'memory': '512'}) self.assertConstrainedNodes([node1, node2], {'memory': '1024'}) self.assertConstrainedNodes([node2], {'memory': '2048'}) self.assertConstrainedNodes([node2], {'memory': '4096'}) self.assertConstrainedNodes([], {'memory': '8192'}) self.assertConstrainedNodes([node2], {'memory': '4096.0'}) self.assertRaises(InvalidConstraint, self.assertConstrainedNodes, [], {'memory': 'notint'})
def test_cpu_count(self): node1 = factory.make_node(cpu_count=1) node2 = factory.make_node(cpu_count=2) self.assertConstrainedNodes([node1, node2], {'cpu_count': '0'}) self.assertConstrainedNodes([node1, node2], {'cpu_count': '1'}) self.assertConstrainedNodes([node2], {'cpu_count': '2'}) self.assertConstrainedNodes([], {'cpu_count': '4'}) self.assertConstrainedNodes([node2], {'cpu_count': '2.0'}) self.assertConstrainedNodes([node2], {'cpu_count': '1.2'}) self.assertRaises(InvalidConstraint, self.assertConstrainedNodes, [], {'cpu_count': 'notint'})
def test_POST_acquire_allocates_node_by_zone(self): factory.make_node(status=NODE_STATUS.READY) zone = factory.make_zone() node = factory.make_node(status=NODE_STATUS.READY, zone=zone) response = self.client.post(reverse('nodes_handler'), { 'op': 'acquire', 'zone': zone.name, }) self.assertResponseCode(httplib.OK, response) response_json = json.loads(response.content) self.assertEqual(node.system_id, response_json['system_id'])
def test_POST_acquire_fails_without_all_tags(self): # Asking for particular tags does not acquire if no node has all tags. node1 = factory.make_node(status=NODE_STATUS.READY) node1.tags = [factory.make_tag(t) for t in ("fast", "stable", "cute")] node2 = factory.make_node(status=NODE_STATUS.READY) node2.tags = [factory.make_tag("cheap")] response = self.client.post(reverse('nodes_handler'), { 'op': 'acquire', 'tags': 'fast, cheap', }) self.assertResponseCode(httplib.CONFLICT, response)
def test_macs_DELETE_mac_forbidden(self): # When deleting a MAC address, the api returns a 'Forbidden' (403) # error if the node is not visible to the logged-in user. node, mac1, _ = self.createNodeWithMacs() factory.make_node(status=NODE_STATUS.ALLOCATED, owner=factory.make_user()) response = self.client.delete( reverse('node_mac_handler', args=[node.system_id, mac1.mac_address])) self.assertEqual(httplib.FORBIDDEN, response.status_code)
def test_migrate_all_nodes_to_bootstrap_owner_when_multiple_users(self): user1 = factory.make_user() node1 = factory.make_node(owner=user1) user2 = factory.make_user() node2 = factory.make_node(owner=user2) make_provider_state_file(node1) migrate() self.assertEqual( (user1, user1), (reload_object(node1).owner, reload_object(node2).owner))
def test_doesnt_touch_other_tags(self): node1 = factory.make_node() node1.set_hardware_details('<node><foo /></node>') node2 = factory.make_node() node2.set_hardware_details('<node><bar /></node>') tag1 = factory.make_tag(definition='/node/foo') self.assertItemsEqual([tag1.name], node1.tag_names()) self.assertItemsEqual([], node2.tag_names()) tag2 = factory.make_tag(definition='/node/bar') self.assertItemsEqual([tag1.name], node1.tag_names()) self.assertItemsEqual([tag2.name], node2.tag_names())
def test_connected_to(self): mac1 = MAC('aa:bb:cc:dd:ee:ff') mac2 = MAC('00:11:22:33:44:55') node1 = factory.make_node(routers=[mac1, mac2]) node2 = factory.make_node(routers=[mac1]) factory.make_node() self.assertConstrainedNodes( [node1], {'connected_to': [mac1.get_raw(), mac2.get_raw()]}) self.assertConstrainedNodes([node1, node2], {'connected_to': [mac1.get_raw()]})
def test_get_nodes_returns_everything_for_superuser(self): user1 = factory.make_user() user2 = factory.make_user() user2.is_superuser = True node1 = factory.make_node(owner=user1) node2 = factory.make_node() tag = factory.make_tag() node1.tags.add(tag) node2.tags.add(tag) self.assertItemsEqual([node1, node2], Tag.objects.get_nodes(tag.name, user2))
def test_zone(self): node1 = factory.make_node() node2 = factory.make_node() node3 = factory.make_node() zone1 = factory.make_zone(nodes=[node1, node2]) zone2 = factory.make_zone() self.assertConstrainedNodes([node1, node2], {'zone': zone1.name}) self.assertConstrainedNodes([node1, node2, node3], {'zone': ''}) self.assertConstrainedNodes([node1, node2, node3], {}) self.assertConstrainedNodes([], {'zone': zone2.name})
def test_start_commissioning_ignores_other_commissioning_results(self): node = factory.make_node() filename = factory.getRandomString() text = factory.getRandomString() script_result = random.randint(0, 10) NodeCommissionResult.objects.store_data( node, filename, script_result, text) other_node = factory.make_node(status=NODE_STATUS.DECLARED) other_node.start_commissioning(factory.make_admin()) self.assertEqual( text, NodeCommissionResult.objects.get_data(node, filename))
def test_clear_results_ignores_other_nodes(self): # clear_results should only remove results for the supplied # node. node1 = factory.make_node() factory.make_node_commission_result(node=node1) node2 = factory.make_node() factory.make_node_commission_result(node=node2) NodeCommissionResult.objects.clear_results(node1) self.assertTrue( NodeCommissionResult.objects.filter(node=node2).exists())
def test_GET_list_with_agent_name_filters_with_empty_string(self): factory.make_node(agent_name=factory.make_name('agent-name')) node = factory.make_node(agent_name='') response = self.client.get(reverse('nodes_handler'), { 'op': 'list', 'agent_name': '', }) self.assertEqual(httplib.OK, response.status_code) parsed_result = json.loads(response.content) self.assertSequenceEqual( [node.system_id], extract_system_ids(parsed_result))
def test_macs_DELETE_mac_forbidden(self): # When deleting a MAC address, the api returns a 'Forbidden' (403) # error if the node is not visible to the logged-in user. node, mac1, _ = self.createNodeWithMacs() factory.make_node( status=NODE_STATUS.ALLOCATED, owner=factory.make_user()) response = self.client.delete( reverse( 'node_mac_handler', args=[node.system_id, mac1.mac_address])) self.assertEqual(httplib.FORBIDDEN, response.status_code)
def test_POST_accept_all_does_not_accept_anything(self): # It is not an error for a non-admin user to attempt to accept all # anonymously enlisted nodes, but only those for which he/she has # admin privs will be accepted, which currently equates to none of # them. factory.make_node(status=NODE_STATUS.DECLARED), factory.make_node(status=NODE_STATUS.DECLARED), response = self.client.post( reverse('nodes_handler'), {'op': 'accept_all'}) self.assertEqual(httplib.OK, response.status_code) nodes_returned = json.loads(response.content) self.assertEqual([], nodes_returned)
def test_POST_accept_fails_if_node_does_not_exist(self): self.become_admin() # Make sure there is a node, it just isn't the one being accepted factory.make_node() node_id = factory.getRandomString() response = self.client.post(reverse('nodes_handler'), { 'op': 'accept', 'nodes': [node_id] }) self.assertEqual( (httplib.BAD_REQUEST, "Unknown node(s): %s." % node_id), (response.status_code, response.content))
def test_view_tag_hides_private_nodes(self): tag = factory.make_tag() node = factory.make_node() node2 = factory.make_node(owner=factory.make_user()) node.tags.add(tag) node2.tags.add(tag) tag_link = reverse('tag-view', args=[tag.name]) response = self.client.get(tag_link) doc = fromstring(response.content) content_text = doc.cssselect('#content')[0].text_content() self.assertIn(node.hostname, content_text) self.assertNotIn(node2.hostname, content_text)
def test_POST_acquire_would_rather_fail_than_disobey_constraint(self): # If "acquire" is passed a constraint, it won't return a node # that does not meet that constraint. Even if it means that it # can't meet the request. factory.make_node(status=NODE_STATUS.READY, owner=None) desired_node = factory.make_node(status=NODE_STATUS.ALLOCATED, owner=factory.make_user()) response = self.client.post(reverse('nodes_handler'), { 'op': 'acquire', 'name': desired_node.system_id, }) self.assertEqual(httplib.CONFLICT, response.status_code)
def test_set_random_hostname_checks_hostname_existence(self): Config.objects.set_config("enlistment_domain", '') existing_node = factory.make_node(hostname='hostname') hostnames = [existing_node.hostname, "new_hostname"] self.patch( node_module, "generate_hostname", lambda size: hostnames.pop(0)) node = factory.make_node() node.set_random_hostname() self.assertEqual('new_hostname', node.hostname)
def test_GET_nodes_returns_nodes(self): tag = factory.make_tag() node1 = factory.make_node() # Create a second node that isn't tagged. factory.make_node() node1.tags.add(tag) response = self.client.get(self.get_tag_uri(tag), {'op': 'nodes'}) self.assertEqual(httplib.OK, response.status_code) parsed_result = json.loads(response.content) self.assertEqual([node1.system_id], [r['system_id'] for r in parsed_result])
def test_POST_acquire_treats_unknown_name_as_resource_conflict(self): # A name constraint naming an unknown node produces a resource # conflict: most likely the node existed but has changed or # disappeared. # Certainly it's not a 404, since the resource named in the URL # is "nodes/," which does exist. factory.make_node(status=NODE_STATUS.READY, owner=None) response = self.client.post(reverse('nodes_handler'), { 'op': 'acquire', 'name': factory.getRandomString(), }) self.assertEqual(httplib.CONFLICT, response.status_code)