def test_get_hostname_ip_mapping_picks_mac_with_lease(self): node = factory.make_node(hostname=factory.make_name('host')) factory.make_mac_address(node=node) second_mac = factory.make_mac_address(node=node) # Create a lease for the second MAC Address. lease = factory.make_dhcp_lease( nodegroup=node.nodegroup, mac=second_mac.mac_address) mapping = DHCPLease.objects.get_hostname_ip_mapping(node.nodegroup) self.assertEqual({node.hostname: lease.ip}, mapping)
def test_is_registered_returns_True_if_node_registered(self): mac_address = factory.getRandomMACAddress() factory.make_mac_address(mac_address) response = self.client.get( reverse('nodes_handler'), {'op': 'is_registered', 'mac_address': mac_address}) self.assertEqual( (httplib.OK, "true"), (response.status_code, response.content))
def test_start_commisssioning_doesnt_start_nodes_for_non_admin_users(self): node = factory.make_node( status=NODE_STATUS.DECLARED, power_type=POWER_TYPE.WAKE_ON_LAN) factory.make_mac_address(node=node) node.start_commissioning(factory.make_user()) expected_attrs = { 'status': NODE_STATUS.COMMISSIONING, } self.assertAttributes(node, expected_attrs) self.assertEqual([], self.celery.tasks)
def test_get_hostname_ip_mapping_considers_only_first_mac(self): nodegroup = factory.make_node_group() node = factory.make_node( nodegroup=nodegroup) factory.make_mac_address(node=node) second_mac = factory.make_mac_address(node=node) # Create a lease for the second MAC Address. factory.make_dhcp_lease( nodegroup=nodegroup, mac=second_mac.mac_address) mapping = DHCPLease.objects.get_hostname_ip_mapping(nodegroup) self.assertEqual({}, mapping)
def test_get_hostname_ip_mapping_picks_oldest_mac_with_lease(self): node = factory.make_node(hostname=factory.make_name('host')) older_mac = factory.make_mac_address(node=node) newer_mac = factory.make_mac_address(node=node) factory.make_dhcp_lease( nodegroup=node.nodegroup, mac=newer_mac.mac_address) lease_for_older_mac = factory.make_dhcp_lease( nodegroup=node.nodegroup, mac=older_mac.mac_address) mapping = DHCPLease.objects.get_hostname_ip_mapping(node.nodegroup) self.assertEqual({node.hostname: lease_for_older_mac.ip}, mapping)
def test_start_commissioning_changes_status_and_starts_node(self): node = factory.make_node( status=NODE_STATUS.DECLARED, power_type=POWER_TYPE.WAKE_ON_LAN) factory.make_mac_address(node=node) node.start_commissioning(factory.make_admin()) expected_attrs = { 'status': NODE_STATUS.COMMISSIONING, } self.assertAttributes(node, expected_attrs) self.assertEqual( ['provisioningserver.tasks.power_on'], [task['task'].name for task in self.celery.tasks])
def test_get_hostname_ip_mapping_returns_mapping(self): nodegroup = factory.make_node_group() expected_mapping = {} for i in range(3): node = factory.make_node( nodegroup=nodegroup) mac = factory.make_mac_address(node=node) factory.make_mac_address(node=node) lease = factory.make_dhcp_lease( nodegroup=nodegroup, mac=mac.mac_address) expected_mapping[node.hostname] = lease.ip mapping = DHCPLease.objects.get_hostname_ip_mapping(nodegroup) self.assertEqual(expected_mapping, mapping)
def test_is_registered_normalizes_mac_address(self): # These two non-normalized MAC addresses are the same. non_normalized_mac_address = 'AA-bb-cc-dd-ee-ff' non_normalized_mac_address2 = 'aabbccddeeff' factory.make_mac_address(non_normalized_mac_address) response = self.client.get( reverse('nodes_handler'), { 'op': 'is_registered', 'mac_address': non_normalized_mac_address2 }) self.assertEqual( (httplib.OK, "true"), (response.status_code, response.content))
def test_start_commissioning_changes_status_and_starts_node(self): user = factory.make_user() node = factory.make_node( status=NODE_STATUS.DECLARED, power_type=POWER_TYPE.WAKE_ON_LAN) factory.make_mac_address(node=node) node.start_commissioning(user) expected_attrs = { 'status': NODE_STATUS.COMMISSIONING, 'owner': user, } self.assertAttributes(node, expected_attrs) self.assertEqual( (1, 'provisioningserver.tasks.power_on'), (len(self.celery.tasks), self.celery.tasks[0]['task'].name))
def test_generate_certs_for_lxd_power_type(self): hostname = factory.make_string() form = AdminMachineWithMACAddressesForm( data={ "architecture": make_usable_architecture(self), "hostname": hostname, "mac_addresses": [factory.make_mac_address()], "power_type": "lxd", "power_parameters": { "power_address": "1.2.3.4", "instance_name": hostname, }, }, ) self.assertTrue(form.is_valid()) machine = form.save() power_params = machine.bmc.power_parameters self.assertIn("certificate", power_params) self.assertIn("key", power_params) cert = Certificate.from_pem( power_params["certificate"] + power_params["key"] ) self.assertEqual(cert.cn(), Config.objects.get_config("maas_name")) # cert/key are not per-instance parameters self.assertNotIn("certificate", machine.instance_power_parameters) self.assertNotIn("key", machine.instance_power_parameters)
def test_creates_device_with_macs(self): hostname = factory.make_name("device") mac1 = factory.make_mac_address() mac2 = factory.make_mac_address() form = DeviceWithMACsForm(data=get_QueryDict({ "hostname": hostname, "mac_addresses": [mac1, mac2] }), request=self.make_request()) self.assertTrue(form.is_valid(), dict(form.errors)) form.save() device = get_one(Device.objects.filter(hostname=hostname)) self.assertThat(device.hostname, Equals(hostname)) iface = get_one(Interface.objects.filter(mac_address=mac1)) self.assertThat(iface.node, Equals(device)) iface = get_one(Interface.objects.filter(mac_address=mac2)) self.assertThat(iface.node, Equals(device))
def test_POST_create_validates_architecture(self): hostname = factory.make_name("hostname") power_type = 'ipmi' power_parameters = { "power_address": factory.make_ip_address(), "power_user": factory.make_name("power-user"), "power_pass": factory.make_name("power-pass"), "power_driver": 'LAN_2_0', "mac_address": '', "power_boot_type": 'auto', } factory.make_Machine(hostname=hostname, status=NODE_STATUS.NEW, architecture='', power_type=power_type, power_parameters=power_parameters) response = self.client.post( reverse('machines_handler'), { 'hostname': 'maas-enlistment', 'architecture': factory.make_name('arch'), 'power_type': power_type, 'mac_addresses': factory.make_mac_address(), 'power_parameters': json.dumps(power_parameters), }) self.assertEqual(http.client.BAD_REQUEST, response.status_code)
def test__creates_node(self): self.prepare_rack_rpc() mac_addresses = [ factory.make_mac_address() for _ in range(3)] architecture = make_usable_architecture(self) node = create_node(architecture, 'manual', {}, mac_addresses) self.assertEqual( ( architecture, 'manual', {}, ), ( node.architecture, node.power_type, node.power_parameters )) # Node will not have an auto-generated name because migrations are # not ran in the testing environment. # self.expectThat(node.hostname, Contains("-")) self.expectThat(node.id, Not(Is(None))) self.assertItemsEqual( mac_addresses, [nic.mac_address for nic in node.interface_set.all()])
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_ip_addresses_uses_result_cache(self): # ip_addresses has a specialized code path for the case where the # node group's set of DHCP leases is already cached in Django's ORM. # This test exercises that code path. node = factory.make_node() macs = [factory.make_mac_address(node=node) for i in range(2)] leases = [ factory.make_dhcp_lease( nodegroup=node.nodegroup, mac=mac.mac_address) for mac in macs] # Other nodes in the nodegroup have leases, but those are not # relevant here. factory.make_dhcp_lease(nodegroup=node.nodegroup) # Don't address the node directly; address it through a query with # prefetched DHCP leases, to ensure that the query cache for those # leases on the nodegroup will be populated. query = Node.objects.filter(id=node.id) query = query.prefetch_related('nodegroup__dhcplease_set') # The cache is populated. This is the condition that triggers the # separate code path in Node.ip_addresses(). self.assertIsNotNone( query[0].nodegroup.dhcplease_set.all()._result_cache) # ip_addresses() still returns the node's leased addresses. num_queries, addresses = self.getNumQueries(query[0].ip_addresses) # It only takes one query: to get the node's MAC addresses. self.assertEqual(1, num_queries) # The result is not a query set, so this isn't hiding a further query. no_queries, _ = self.getNumQueries(list, addresses) self.assertEqual(0, no_queries) # We still get exactly the right IP addresses. self.assertItemsEqual([lease.ip for lease in leases], addresses)
def test_POST_create_creates_machine_with_power_parameters(self): # We're setting power parameters so we disable start_commissioning to # prevent anything from attempting to issue power instructions. self.patch(Node, "start_commissioning") hostname = factory.make_name("hostname") architecture = make_usable_architecture(self) power_type = "ipmi" power_parameters = { "power_address": factory.make_ip_address(), "power_user": factory.make_name("power-user"), "power_pass": factory.make_name("power-pass"), } response = self.client.post( reverse("machines_handler"), { "hostname": hostname, "architecture": architecture, "power_type": power_type, "mac_addresses": factory.make_mac_address(), "power_parameters": json.dumps(power_parameters), }, ) # Add the default values. power_parameters["power_driver"] = "LAN_2_0" power_parameters["mac_address"] = "" power_parameters["power_boot_type"] = "auto" self.assertEqual(http.client.OK, response.status_code) [machine] = Machine.objects.filter(hostname=hostname) self.assertEqual(power_parameters, machine.power_parameters) self.assertEqual(power_type, machine.power_type)
def test_api_retrieves_node_metadata_by_mac(self): mac = factory.make_mac_address() url = reverse('metadata-meta-data-by-mac', args=['latest', mac.mac_address, 'instance-id']) response = self.client.get(url) self.assertEqual((httplib.OK, mac.node.system_id), (response.status_code, response.content))
def test_create_creates_device_with_dynamic_ip_assignment(self): user = factory.make_User() request = HttpRequest() request.user = user handler = DeviceHandler(user, {}, request) mac = factory.make_mac_address() hostname = factory.make_name("hostname") description = factory.make_name("description") created_device = handler.create({ "hostname": hostname, "description": description, "primary_mac": mac, "interfaces": [{ "mac": mac, "ip_assignment": DEVICE_IP_ASSIGNMENT_TYPE.DYNAMIC, }], }) self.expectThat(created_device["hostname"], Equals(hostname)) self.expectThat(created_device["description"], Equals(description)) self.expectThat(created_device["primary_mac"], Equals(mac)) self.expectThat(created_device["extra_macs"], Equals([])) self.expectThat(created_device["ip_assignment"], Equals(DEVICE_IP_ASSIGNMENT_TYPE.DYNAMIC)) self.expectThat(created_device["ip_address"], Is(None)) self.expectThat(created_device["owner"], Equals(user.username))
def test_create_interface_creates_with_static_ip_assignment_implicit(self): user = factory.make_User() handler = DeviceHandler(user, {}, None) device = factory.make_Device(owner=user) mac = factory.make_mac_address() subnet = factory.make_Subnet() updated_device = handler.create_interface({ "system_id": device.system_id, "mac_address": mac, "ip_assignment": DEVICE_IP_ASSIGNMENT_TYPE.STATIC, "subnet": subnet.id, }) self.expectThat(updated_device["primary_mac"], Equals(mac)) self.expectThat( updated_device["ip_assignment"], Equals(DEVICE_IP_ASSIGNMENT_TYPE.STATIC), ) static_interface = Interface.objects.get(mac_address=MAC(mac)) observed_subnet = static_interface.ip_addresses.first().subnet self.expectThat( observed_subnet, Equals(subnet), "Static assignment to the subnet was not created.", )
def test_pxeconfig_uses_nodegroup_domain_for_node(self): mac = factory.make_mac_address() params = self.get_default_params() params['mac'] = mac self.assertEqual( mac.node.nodegroup.name, self.get_pxeconfig(params).get('domain'))
def test_POST_create_validates_architecture(self): hostname = factory.make_name("hostname") power_type = "ipmi" power_parameters = { "power_address": factory.make_ip_address(), "power_user": factory.make_name("power-user"), "power_pass": factory.make_name("power-pass"), "power_driver": "LAN_2_0", "mac_address": "", "power_boot_type": "auto", } factory.make_Machine( hostname=hostname, status=NODE_STATUS.NEW, architecture="", power_type=power_type, power_parameters=power_parameters, ) response = self.client.post( reverse("machines_handler"), { "hostname": "maas-enlistment", "architecture": factory.make_name("arch"), "power_type": power_type, "mac_addresses": factory.make_mac_address(), "power_parameters": json.dumps(power_parameters), }, ) self.assertEqual(http.client.BAD_REQUEST, response.status_code)
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_create_creates_device_with_static_ip_assignment_implicit(self): user = factory.make_User() request = HttpRequest() request.user = user handler = DeviceHandler(user, {}, request) mac = factory.make_mac_address() hostname = factory.make_name("hostname") subnet = factory.make_Subnet() created_device = handler.create({ "hostname": hostname, "primary_mac": mac, "interfaces": [{ "mac": mac, "ip_assignment": DEVICE_IP_ASSIGNMENT_TYPE.STATIC, "subnet": subnet.id, }], }) self.expectThat(created_device["ip_assignment"], Equals(DEVICE_IP_ASSIGNMENT_TYPE.STATIC)) static_interface = Interface.objects.get(mac_address=MAC(mac)) observed_subnet = static_interface.ip_addresses.first().subnet self.expectThat(observed_subnet, Equals(subnet), "Static assignment to the subnet was not created.") ip_address = created_device["ip_address"] self.expectThat( StaticIPAddress.objects.filter(ip=ip_address).count(), Equals(1), "StaticIPAddress was not created.")
def test_logs_migration(self): logger = self.useFixture(FakeLogger("maas")) rack = factory.make_RackController() vlan = factory.make_VLAN() subnet = factory.make_Subnet(vlan=vlan) ip = factory.pick_ip_in_Subnet(subnet) interfaces = { factory.make_name("eth0"): { "type": "physical", "mac_address": factory.make_mac_address(), "parents": [], "links": [{ "mode": "static", "address": "%s/%d" % (str(ip), subnet.get_ipnetwork().prefixlen), }], "enabled": True, } } rack.update_interfaces(interfaces) ng_uuid = factory.make_UUID() NodeGroupToRackController.objects.create(uuid=ng_uuid, subnet=subnet) handle_upgrade(rack, ng_uuid) vlan = reload_object(vlan) self.assertEqual( "DHCP setting from NodeGroup(%s) have been migrated to %s." % (ng_uuid, vlan), logger.output.strip())
def test_is_registered_returns_False_if_node_new_commis_retired(self): if self.user.is_anonymous: status = random.choice( [ NODE_STATUS.NEW, NODE_STATUS.COMMISSIONING, NODE_STATUS.RETIRED, ] ) else: status = NODE_STATUS.RETIRED node = factory.make_Node(status=status) mac_address = factory.make_mac_address() factory.make_Interface( INTERFACE_TYPE.PHYSICAL, mac_address=mac_address, node=node ) response = self.client.get( reverse("nodes_handler"), {"op": "is_registered", "mac_address": mac_address}, ) self.assertEqual( (http.client.OK.value, "false"), ( response.status_code, response.content.decode(settings.DEFAULT_CHARSET), ), )
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_sets_url(self): load_builtin_scripts() rack_controller = factory.make_RackController() interfaces = { factory.make_name("eth0"): { "type": "physical", "mac_address": factory.make_mac_address(), "parents": [], "links": [], "enabled": True, } } url = "http://%s/MAAS" % factory.make_name("host") rack_registered = register( rack_controller.system_id, interfaces=interfaces, url=urlparse(url), is_loopback=False, ) self.assertEqual(url, rack_registered.url) rack_registered = register( rack_controller.system_id, interfaces=interfaces, url=urlparse("http://localhost/MAAS/"), is_loopback=True, ) self.assertEqual("", rack_registered.url)
def test__silent_when_no_node(self): event_type = factory.make_EventType() description = factory.make_name('description') # Exception should not be raised. events.send_event_mac_address(factory.make_mac_address(), event_type.name, description, datetime.datetime.utcnow())
def test_updates_interfaces(self): # Interfaces are set on existing rack controllers. rack_controller = factory.make_RackController() interfaces = { factory.make_name("eth0"): { "type": "physical", "mac_address": factory.make_mac_address(), "parents": [], "links": [], "enabled": True, } } rack_registered = register(rack_controller.system_id, interfaces=interfaces) self.assertThat( rack_registered.interface_set.all(), MatchesSetwise(*(MatchesAll( IsInstance(PhysicalInterface), MatchesStructure.byEquality( name=name, mac_address=interface["mac_address"], enabled=interface["enabled"], ), first_only=True, ) for name, interface in interfaces.items())))
def test_create_interface_creates_with_external_ip_assignment(self): user = factory.make_User() request = HttpRequest() request.user = user handler = DeviceHandler(user, {}, request) device = factory.make_Device(owner=user) mac = factory.make_mac_address() ip_address = factory.make_ipv4_address() updated_device = handler.create_interface({ "system_id": device.system_id, "mac_address": mac, "ip_assignment": DEVICE_IP_ASSIGNMENT_TYPE.EXTERNAL, "ip_address": ip_address, }) self.expectThat(updated_device["primary_mac"], Equals(mac)) self.expectThat( updated_device["ip_assignment"], Equals(DEVICE_IP_ASSIGNMENT_TYPE.EXTERNAL), ) self.expectThat( StaticIPAddress.objects.filter(ip=ip_address).count(), Equals(1), "StaticIPAddress was not created.", )
def test__creates_node_with_explicit_domain(self): self.prepare_rack_rpc() mac_addresses = [factory.make_mac_address() for _ in range(3)] architecture = make_usable_architecture(self) hostname = factory.make_hostname() domain = factory.make_Domain() node = create_node(architecture, 'manual', {}, mac_addresses, domain=domain.name, hostname=hostname) self.assertEqual(( architecture, 'manual', {}, domain.id, hostname, ), ( node.architecture, node.power_type, node.power_parameters, node.domain.id, node.hostname, )) self.expectThat(node.id, Not(Is(None))) self.assertItemsEqual( mac_addresses, [nic.mac_address for nic in node.interface_set.all()])
def test_migrates_nodegroup_subnet(self): rack = factory.make_RackController() vlan = factory.make_VLAN() subnet = factory.make_Subnet(vlan=vlan) ip = factory.pick_ip_in_Subnet(subnet) interfaces = { factory.make_name("eth0"): { "type": "physical", "mac_address": factory.make_mac_address(), "parents": [], "links": [{ "mode": "static", "address": "%s/%d" % (str(ip), subnet.get_ipnetwork().prefixlen), }], "enabled": True, } } rack.update_interfaces(interfaces) ng_uuid = factory.make_UUID() NodeGroupToRackController.objects.create(uuid=ng_uuid, subnet=subnet) handle_upgrade(rack, ng_uuid) vlan = reload_object(vlan) self.assertEqual(rack.system_id, vlan.primary_rack.system_id) self.assertTrue(vlan.dhcp_on) self.assertItemsEqual([], NodeGroupToRackController.objects.all())
def test_reuses_rackcontroller_domain(self): # If a domain name already exists for a FQDN hostname, it is # not modified. factory.make_Domain("example.com", authoritative=True) hostname = "newcontroller.example.com" interfaces = { factory.make_name("eth0"): { "type": "physical", "mac_address": factory.make_mac_address(), "parents": [], "links": [], "enabled": True, } } url = "http://%s/MAAS" % factory.make_name("host") rack_registered = register( "rack-id-foo", interfaces=interfaces, url=urlparse(url), is_loopback=False, hostname=hostname, ) self.assertEqual("newcontroller", rack_registered.hostname) self.assertEqual("example.com", rack_registered.domain.name) self.assertTrue(rack_registered.domain.authoritative)
def test_create_creates_device_with_external_ip_assignment(self): user = factory.make_User() request = HttpRequest() request.user = user handler = DeviceHandler(user, {}, request) mac = factory.make_mac_address() hostname = factory.make_name("hostname") ip_address = factory.make_ipv4_address() created_device = handler.create({ "hostname": hostname, "primary_mac": mac, "interfaces": [{ "mac": mac, "ip_assignment": DEVICE_IP_ASSIGNMENT_TYPE.EXTERNAL, "ip_address": ip_address, }], }) self.expectThat(created_device["ip_assignment"], Equals(DEVICE_IP_ASSIGNMENT_TYPE.EXTERNAL)) self.expectThat(created_device["ip_address"], Equals(ip_address)) self.expectThat( StaticIPAddress.objects.filter(ip=ip_address).count(), Equals(1), "StaticIPAddress was not created.")
def test_create_interface_creates_static_ip_assignment_explicit(self): user = factory.make_User() request = HttpRequest() request.user = user handler = DeviceHandler(user, {}, request) device = factory.make_Device(owner=user) mac = factory.make_mac_address() subnet = factory.make_Subnet() ip_address = factory.pick_ip_in_Subnet(subnet) updated_device = handler.create_interface({ "system_id": device.system_id, "mac_address": mac, "ip_assignment": DEVICE_IP_ASSIGNMENT_TYPE.STATIC, "subnet": subnet.id, "ip_address": ip_address, }) self.expectThat(updated_device["primary_mac"], Equals(mac)) self.expectThat(updated_device["ip_assignment"], Equals(DEVICE_IP_ASSIGNMENT_TYPE.STATIC)) self.expectThat(updated_device["ip_address"], Equals(ip_address)) static_interface = Interface.objects.get(mac_address=MAC(mac)) observed_subnet = static_interface.ip_addresses.first().subnet self.expectThat(observed_subnet, Equals(subnet), "Static assignment to the subnet was not created.") self.expectThat( StaticIPAddress.objects.filter(ip=ip_address).count(), Equals(1), "StaticIPAddress was not created.")
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_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_create_creates_device_with_static_and_external_ip(self): user = factory.make_User() request = HttpRequest() request.user = user handler = DeviceHandler(user, {}, request) hostname = factory.make_name("hostname") subnet = factory.make_Subnet() mac_static = factory.make_mac_address() static_ip_address = factory.pick_ip_in_Subnet(subnet) mac_external = factory.make_mac_address() external_ip_address = factory.make_ipv4_address() created_device = handler.create({ "hostname": hostname, "primary_mac": mac_static, "extra_macs": [mac_external], "interfaces": [ { "mac": mac_static, "ip_assignment": DEVICE_IP_ASSIGNMENT_TYPE.STATIC, "subnet": subnet.id, "ip_address": static_ip_address, }, { "mac": mac_external, "ip_assignment": DEVICE_IP_ASSIGNMENT_TYPE.EXTERNAL, "ip_address": external_ip_address, }, ], }) self.expectThat(created_device["primary_mac"], Equals(mac_static)) self.expectThat(created_device["extra_macs"], Equals([mac_external])) self.expectThat(created_device["ip_assignment"], Equals(DEVICE_IP_ASSIGNMENT_TYPE.STATIC)) self.expectThat(created_device["ip_address"], Equals(static_ip_address)) static_interface = Interface.objects.get(mac_address=MAC(mac_static)) observed_subnet = static_interface.ip_addresses.first().subnet self.expectThat(observed_subnet, Equals(subnet), "Static assignment to the subnet was not created.") self.expectThat( StaticIPAddress.objects.filter(ip=static_ip_address).count(), Equals(1), "Static StaticIPAddress was not created.") self.expectThat( StaticIPAddress.objects.filter(ip=external_ip_address).count(), Equals(1), "External StaticIPAddress was not created.")
def test_api_normally_disallows_anonymous_node_metadata_access(self): self.patch(settings, 'ALLOW_UNSAFE_METADATA_ACCESS', False) mac = factory.make_mac_address() url = reverse( 'metadata-meta-data-by-mac', args=['latest', mac.mac_address, 'instance-id']) response = self.client.get(url) self.assertEqual(httplib.FORBIDDEN, response.status_code)
def test__raises_validation_errors_for_invalid_data(self): self.prepare_rack_rpc() self.assertRaises( ValidationError, create_node, architecture="spam/eggs", power_type="scrambled", power_parameters={}, mac_addresses=[factory.make_mac_address()])
def test__raises_BootConfigNoResponse_for_unknown_node(self): rack_controller = factory.make_RackController() local_ip = factory.make_ip_address() remote_ip = factory.make_ip_address() mac = factory.make_mac_address(delimiter='-') self.assertRaises( BootConfigNoResponse, get_config, rack_controller.system_id, local_ip, remote_ip, mac=mac)
def test_node_delete_mac_contains_mac(self): node = factory.make_node(owner=self.logged_in_user) mac = factory.make_mac_address(node=node) mac_delete_link = reverse('mac-delete', args=[node.system_id, mac]) response = self.client.get(mac_delete_link) self.assertIn( 'Are you sure you want to delete the MAC address "%s"' % mac.mac_address, response.content)
def test_ip_addresses_queries_leases(self): node = factory.make_node() macs = [factory.make_mac_address(node=node) for i in range(2)] leases = [ factory.make_dhcp_lease( nodegroup=node.nodegroup, mac=mac.mac_address) for mac in macs] self.assertItemsEqual( [lease.ip for lease in leases], node.ip_addresses())
def test_api_retrieves_node_metadata_by_mac(self): mac = factory.make_mac_address() url = reverse( 'metadata-meta-data-by-mac', args=['latest', mac.mac_address, 'instance-id']) response = self.client.get(url) self.assertEqual( (httplib.OK, mac.node.system_id), (response.status_code, response.content))
def test_pxeconfig_returns_extra_kernel_options(self): node = factory.make_node() extra_kernel_opts = factory.getRandomString() Config.objects.set_config('kernel_opts', extra_kernel_opts) mac = factory.make_mac_address(node=node) params = self.get_default_params() params['mac'] = mac.mac_address pxe_config = self.get_pxeconfig(params) self.assertEqual(extra_kernel_opts, pxe_config['extra_opts'])
def test_edit_nodes_contains_list_of_macaddresses(self): node = factory.make_node(owner=self.logged_in_user) macs = [ factory.make_mac_address(node=node).mac_address for i in range(3) ] node_edit_link = reverse('node-edit', args=[node.system_id]) response = self.client.get(node_edit_link) self.assertThat(response.content, ContainsAll(macs))
def test_node_delete_mac_POST_deletes_mac(self): node = factory.make_node(owner=self.logged_in_user) mac = factory.make_mac_address(node=node) mac_delete_link = reverse('mac-delete', args=[node.system_id, mac]) response = self.client.post(mac_delete_link, {'post': 'yes'}) self.assertEqual( reverse('node-edit', args=[node.system_id]), extract_redirect(response)) self.assertFalse(MACAddress.objects.filter(id=mac.id).exists())
def test_node_delete_mac_POST_displays_message(self): node = factory.make_node(owner=self.logged_in_user) mac = factory.make_mac_address(node=node) mac_delete_link = reverse('mac-delete', args=[node.system_id, mac]) response = self.client.post(mac_delete_link, {'post': 'yes'}) redirect = extract_redirect(response) response = self.client.get(redirect) self.assertEqual( ["Mac address %s deleted." % mac.mac_address], [message.message for message in response.context['messages']])
def test_api_retrieves_node_userdata_by_mac(self): mac = factory.make_mac_address() user_data = factory.getRandomString().encode('ascii') NodeUserData.objects.set_user_data(mac.node, user_data) url = reverse( 'metadata-user-data-by-mac', args=['latest', mac.mac_address]) response = self.client.get(url) self.assertEqual( (httplib.OK, user_data), (response.status_code, response.content))
def test_is_registered_returns_False_if_mac_registered_node_retired(self): mac_address = factory.getRandomMACAddress() mac = factory.make_mac_address(mac_address) mac.node.status = NODE_STATUS.RETIRED mac.node.save() response = self.client.get( reverse('nodes_handler'), {'op': 'is_registered', 'mac_address': mac_address}) self.assertEqual( (httplib.OK, "false"), (response.status_code, response.content))
def test_POST_fails_if_mac_duplicated(self): # Mac Addresses should be unique. mac = 'aa:bb:cc:dd:ee:ff' factory.make_mac_address(mac) architecture = factory.getRandomChoice(ARCHITECTURE_CHOICES) response = self.client.post( reverse('nodes_handler'), { 'op': 'new', 'architecture': architecture, 'hostname': factory.getRandomString(), 'mac_addresses': [mac], }) parsed_result = json.loads(response.content) self.assertEqual(httplib.BAD_REQUEST, response.status_code) self.assertIn('application/json', response['Content-Type']) self.assertEqual( ["Mac address %s already in use." % mac], parsed_result['mac_addresses'])
def test_MACAddressForm_displays_error_message_if_mac_already_used(self): mac = factory.getRandomMACAddress() node = factory.make_mac_address(address=mac) node = factory.make_node() form = MACAddressForm(node=node, data={'mac_address': mac}) self.assertFalse(form.is_valid()) self.assertEquals( {'mac_address': ['This MAC address is already registered.']}, form._errors) self.assertFalse( MACAddress.objects.filter(node=node, mac_address=mac).exists())
def test_pxeconfig_splits_domain_from_node_hostname(self): host = factory.make_name('host') domain = factory.make_name('domain') full_hostname = '.'.join([host, domain]) node = factory.make_node(hostname=full_hostname) mac = factory.make_mac_address(node=node) params = self.get_default_params() params['mac'] = mac.mac_address pxe_config = self.get_pxeconfig(params) self.assertEqual(host, pxe_config.get('hostname')) self.assertNotIn(domain, pxe_config.values())
def test_get_hostname_ip_mapping_considers_given_nodegroup(self): nodegroup = factory.make_node_group() node = factory.make_node( nodegroup=nodegroup) mac = factory.make_mac_address(node=node) factory.make_dhcp_lease( nodegroup=nodegroup, mac=mac.mac_address) another_nodegroup = factory.make_node_group() mapping = DHCPLease.objects.get_hostname_ip_mapping( another_nodegroup) self.assertEqual({}, mapping)
def test_GET_returns_associated_ip_addresses(self): node = factory.make_node() mac = factory.make_mac_address(node=node) lease = factory.make_dhcp_lease( nodegroup=node.nodegroup, mac=mac.mac_address) response = self.client.get(self.get_node_uri(node)) self.assertEqual( httplib.OK, response.status_code, response.content) parsed_result = json.loads(response.content) self.assertEqual([lease.ip], parsed_result['ip_addresses'])
def test_get_hostname_ip_mapping_strips_out_domain(self): nodegroup = factory.make_node_group() hostname = factory.make_name('hostname') domain = factory.make_name('domain') node = factory.make_node( nodegroup=nodegroup, hostname='%s.%s' % (hostname, domain)) mac = factory.make_mac_address(node=node) lease = factory.make_dhcp_lease( nodegroup=nodegroup, mac=mac.mac_address) mapping = DHCPLease.objects.get_hostname_ip_mapping(nodegroup) self.assertEqual({hostname: lease.ip}, mapping)
def test_ip_addresses_filters_by_mac_addresses(self): node = factory.make_node() # Another node in the same nodegroup has some IP leases. The one thing # that tells ip_addresses what nodes these leases belong to are their # MAC addresses. other_node = factory.make_node(nodegroup=node.nodegroup) macs = [factory.make_mac_address(node=node) for i in range(2)] for mac in macs: factory.make_dhcp_lease( nodegroup=node.nodegroup, mac=mac.mac_address) # The other node's leases do not get mistaken for ones that belong to # our original node. self.assertItemsEqual([], other_node.ip_addresses())
def test_GET_list_with_macs_returns_matching_nodes(self): # The "list" operation takes optional "mac_address" parameters. Only # nodes with matching MAC addresses will be returned. macs = [factory.make_mac_address() for counter in range(3)] matching_mac = macs[0].mac_address matching_system_id = macs[0].node.system_id response = self.client.get(reverse('nodes_handler'), { 'op': 'list', 'mac_address': [matching_mac], }) parsed_result = json.loads(response.content) self.assertItemsEqual( [matching_system_id], extract_system_ids(parsed_result))
def test_view_tag_includes_node_links(self): tag = factory.make_tag() node = factory.make_node() node.tags.add(tag) mac = factory.make_mac_address(node=node).mac_address tag_link = reverse('tag-view', args=[tag.name]) node_link = reverse('node-view', args=[node.system_id]) response = self.client.get(tag_link) doc = fromstring(response.content) content_text = doc.cssselect('#content')[0].text_content() self.assertThat( content_text, ContainsAll([mac, '%s' % node.hostname])) self.assertNotIn(node.system_id, content_text) self.assertIn(node_link, get_content_links(response))