def compose_preseed(preseed_type, node): """Put together preseed data for `node`. This produces preseed data for the node in different formats depending on the preseed_type. :param preseed_type: The type of preseed to compose. :type preseed_type: string :param node: The node to compose preseed data for. :type node: Node :return: Preseed data containing the information the node needs in order to access the metadata service: its URL and auth token. """ # Circular import. from metadataserver.models import NodeKey token = NodeKey.objects.get_token_for_node(node) rack_controller = node.get_boot_rack_controller() base_url = rack_controller.url if preseed_type == PRESEED_TYPE.COMMISSIONING: return compose_commissioning_preseed(node, token, base_url) else: metadata_url = _get_metadata_url(preseed_type, base_url) try: return get_preseed_data(preseed_type, node, token, metadata_url) except NotImplementedError: # This is fine; it indicates that the OS does not specify # any special preseed data for this type of preseed. pass except NoSuchOperatingSystem: # Let a caller handle this. If rendered for presentation in the # UI, an explanatory error message could be displayed. If rendered # via the API, in response to cloud-init for example, the prudent # course of action might be to turn the node's power off, mark it # as broken, and notify the user. raise except NoConnectionsAvailable: # This means that the region is not in contact with the node's # cluster controller. In the UI this could be shown as an error # message. This is, however, a show-stopping problem when booting # or installing a node. A caller cannot turn the node's power off # via the usual methods because they rely on a connection to the # cluster. This /could/ generate a preseed that aborts the boot or # installation. The caller /could/ mark the node as broken. For # now, let the caller make the decision, which might be to retry. raise # There is no OS-specific preseed data. if preseed_type == PRESEED_TYPE.CURTIN: return compose_curtin_preseed(node, token, base_url) else: return compose_cloud_init_preseed(node, token, base_url)
def test_returns_preseed_data(self): # The Windows driver is known to provide custom preseed data. rack = factory.make_RackController() node = factory.make_Node(interface=True, osystem="windows") boot_interface = node.get_boot_interface() boot_interface.vlan.dhcp_on = True boot_interface.vlan.primary_rack = rack boot_interface.vlan.save() self.useFixture(RunningClusterRPCFixture()) preseed_data = get_preseed_data( PRESEED_TYPE.COMMISSIONING, node, token=NodeKey.objects.get_token_for_node(node), metadata_url=factory.make_url()) self.assertThat(preseed_data, IsInstance(dict)) self.assertNotIn("data", preseed_data) self.assertThat(preseed_data, Not(HasLength(0)))