def get_preseed_context(release='', nodegroup=None): """Return the node-independent context dictionary to be used to render preseed templates. :param release: See `get_preseed_filenames`. :param nodegroup: The nodegroup used to generate the preseed. :return: The context dictionary. :rtype: dict. """ server_host = get_maas_facing_server_host(nodegroup=nodegroup) main_archive_hostname, main_archive_directory = get_hostname_and_path( Config.objects.get_config('main_archive')) ports_archive_hostname, ports_archive_directory = get_hostname_and_path( Config.objects.get_config('ports_archive')) base_url = nodegroup.maas_url if nodegroup is not None else None return { 'main_archive_hostname': main_archive_hostname, 'main_archive_directory': main_archive_directory, 'ports_archive_hostname': ports_archive_hostname, 'ports_archive_directory': ports_archive_directory, 'release': release, 'server_host': server_host, 'server_url': absolute_reverse('nodes_handler', base_url=base_url), 'metadata_enlist_url': absolute_reverse('enlist', base_url=base_url), 'http_proxy': Config.objects.get_config('http_proxy'), }
def _get_metadata_url(preseed_type, base_url, default_region_ip=None): if preseed_type == PRESEED_TYPE.CURTIN: return absolute_reverse('curtin-metadata', default_region_ip=default_region_ip, base_url=base_url) else: return absolute_reverse('metadata', default_region_ip=default_region_ip, base_url=base_url)
def test_compose_preseed_with_osystem_compose_preseed(self): os_name = factory.make_name('os') osystem = make_osystem(self, os_name, [BOOT_IMAGE_PURPOSE.XINSTALL]) make_usable_osystem(self, os_name) compose_preseed_orig = osystem.compose_preseed compose_preseed_mock = self.patch(osystem, 'compose_preseed') compose_preseed_mock.side_effect = compose_preseed_orig rack_controller = factory.make_RackController(url='') node = factory.make_Node(interface=True, osystem=os_name, status=NODE_STATUS.READY) nic = node.get_boot_interface() nic.vlan.dhcp_on = True nic.vlan.primary_rack = rack_controller nic.vlan.save() self.useFixture(RunningClusterRPCFixture()) token = NodeKey.objects.get_token_for_node(node) region_ip = factory.make_ip_address() expected_url = absolute_reverse('curtin-metadata', default_region_ip=region_ip) compose_preseed(PRESEED_TYPE.CURTIN, node, default_region_ip=region_ip) self.assertThat( compose_preseed_mock, MockCalledOnceWith(PRESEED_TYPE.CURTIN, (node.system_id, node.hostname), (token.consumer.key, token.key, token.secret), expected_url))
def test_absolute_reverse_uses_given_base_url(self): maas_url = factory.make_simple_http_url() absolute_url = absolute_reverse("login", base_url=maas_url) expected_url = self.expected_from_maas_url_and_reverse( maas_url, reverse("login") ) self.assertEqual(expected_url, absolute_url)
def compose_cloud_init_preseed(token, base_url=''): """Compose the preseed value for a node in any state but Commissioning.""" credentials = urlencode({ 'oauth_consumer_key': token.consumer.key, 'oauth_token_key': token.key, 'oauth_token_secret': token.secret, }) local_config_yaml = yaml.safe_dump({ "manage_etc_hosts": "localhost", "apt_preserve_sources_list": True, }) # this is debconf escaping local_config = local_config_yaml.replace("\\", "\\\\").replace("\n", "\\n") # Preseed data to send to cloud-init. We set this as MAAS_PRESEED in # ks_meta, and it gets fed straight into debconf. preseed_items = [('datasources', 'multiselect', 'MAAS'), ('maas-metadata-url', 'string', absolute_reverse('metadata', base_url=base_url)), ('maas-metadata-credentials', 'string', credentials), ('local-cloud-config', 'string', local_config)] return '\n'.join("cloud-init cloud-init/%s %s %s" % ( item_name, item_type, item_value, ) for item_name, item_type, item_value in preseed_items)
def test_absolute_reverse_uses_kwargs(self): node = factory.make_node() self.patch(settings, 'DEFAULT_MAAS_URL', '') absolute_url = absolute_reverse('node-view', kwargs={'system_id': node.system_id}) expected_url = reverse('node-view', args=[node.system_id]) self.assertEqual(expected_url, absolute_url)
def compose_cloud_init_preseed(token, base_url=''): """Compose the preseed value for a node in any state but Commissioning.""" credentials = urlencode({ 'oauth_consumer_key': token.consumer.key, 'oauth_token_key': token.key, 'oauth_token_secret': token.secret, }) local_config_yaml = yaml.safe_dump({ "manage_etc_hosts": "localhost", "apt_preserve_sources_list": True, }) # this is debconf escaping local_config = local_config_yaml.replace("\\", "\\\\").replace("\n", "\\n") # Preseed data to send to cloud-init. We set this as MAAS_PRESEED in # ks_meta, and it gets fed straight into debconf. preseed_items = [ ('datasources', 'multiselect', 'MAAS'), ('maas-metadata-url', 'string', absolute_reverse( 'metadata', base_url=base_url)), ('maas-metadata-credentials', 'string', credentials), ('local-cloud-config', 'string', local_config) ] return '\n'.join( "cloud-init cloud-init/%s %s %s" % ( item_name, item_type, item_value, ) for item_name, item_type, item_value in preseed_items)
def test_absolute_reverse_handles_base_url_without_ending_slash(self): maas_url = factory.make_simple_http_url() maas_url = maas_url.rstrip("/") absolute_url = absolute_reverse("login", base_url=maas_url) expected_url = self.expected_from_maas_url_and_reverse( maas_url, reverse("login")) self.assertEqual(expected_url, absolute_url)
def request_commissioning_results(pod): """Request commissioning results from machines associated with the Pod.""" nodes = yield deferToDatabase(lambda: list(pod.hints.nodes.all())) # Intel RSD and libvirt Pods don't create machines for the host. if not nodes: return pod client_identifiers = yield deferToDatabase(pod.get_client_identifiers) client = yield getClientFromIdentifiers(client_identifiers) for node in nodes: token = yield deferToDatabase(NodeKey.objects.get_token_for_node, node) try: yield send_pod_commissioning_results( client, pod.id, pod.name, pod.power_type, node.system_id, pod.power_parameters, token.consumer.key, token.key, token.secret, urlparse(absolute_reverse("metadata-version", args=["latest"])), ) except PodProblem as e: yield deferToDatabase( Event.objects.create_node_event, node, EVENT_TYPES.NODE_COMMISSIONING_EVENT_FAILED, event_description=str(e), ) return pod
def test_absolute_reverse_uses_maas_url_by_default(self): maas_url = factory.make_simple_http_url(path="") self.useFixture(RegionConfigurationFixture(maas_url=maas_url)) absolute_url = absolute_reverse("login") expected_url = self.expected_from_maas_url_and_reverse( maas_url, reverse("login")) self.assertEqual(expected_url, absolute_url)
def test_compose_preseed_with_curtin_installer(self): rack_controller = factory.make_RackController(url='') node = factory.make_Node(interface=True, status=NODE_STATUS.DEPLOYING) nic = node.get_boot_interface() nic.vlan.dhcp_on = True nic.vlan.primary_rack = rack_controller nic.vlan.save() self.useFixture(RunningClusterRPCFixture()) region_ip = factory.make_ip_address() expected_apt_proxy = get_apt_proxy(node.get_boot_rack_controller(), default_region_ip=region_ip) preseed = yaml.safe_load( compose_preseed(PRESEED_TYPE.CURTIN, node, default_region_ip=region_ip)) self.assertIn('datasource', preseed) self.assertIn('MAAS', preseed['datasource']) self.assertThat( preseed['datasource']['MAAS'], KeysEqual('metadata_url', 'consumer_key', 'token_key', 'token_secret')) self.assertDictEqual( { 'delay': 'now', 'mode': 'reboot', 'timeout': 1800, 'condition': 'test ! -e /tmp/block-reboot', }, preseed['power_state']) self.assertEqual( absolute_reverse('curtin-metadata', default_region_ip=region_ip), preseed['datasource']['MAAS']['metadata_url']) self.assertEqual(expected_apt_proxy, preseed['apt_proxy']) self.assertSystemInfo(preseed) self.assertAptConfig(preseed, expected_apt_proxy)
def test_compose_preseed_for_commissioning_includes_metadata_status_url( self): rack_controller = factory.make_RackController() node = factory.make_Node(interface=True, status=NODE_STATUS.COMMISSIONING) nic = node.get_boot_interface() nic.vlan.dhcp_on = True nic.vlan.primary_rack = rack_controller nic.vlan.save() preseed = yaml.safe_load( compose_preseed(PRESEED_TYPE.COMMISSIONING, node)) self.assertEqual(absolute_reverse('metadata'), preseed['datasource']['MAAS']['metadata_url']) self.assertEqual( absolute_reverse('metadata-status', args=[node.system_id]), preseed['reporting']['maas']['endpoint'])
def test_absolute_reverse_uses_kwargs(self): node = factory.make_node() self.patch(settings, 'DEFAULT_MAAS_URL', '') absolute_url = absolute_reverse( 'node-view', kwargs={'system_id': node.system_id}) expected_url = reverse('node-view', args=[node.system_id]) self.assertEqual(expected_url, absolute_url)
def curtin_maas_reporter(node, events_support=True): token = NodeKey.objects.get_token_for_node(node) rack_controller = node.get_boot_rack_controller() base_url = rack_controller.url if events_support: return { 'reporting': { 'maas': { 'type': 'webhook', 'endpoint': absolute_reverse('metadata-status', args=[node.system_id], base_url=base_url), 'consumer_key': token.consumer.key, 'token_key': token.key, 'token_secret': token.secret, }, }, 'install': { 'log_file': CURTIN_INSTALL_LOG, 'error_tarfile': CURTIN_ERROR_TARFILE, 'post_files': [CURTIN_INSTALL_LOG, CURTIN_ERROR_TARFILE], } } else: version = 'latest' return { 'reporter': { 'maas': { 'url': absolute_reverse('curtin-metadata-version', args=[version], query={'op': 'signal'}, base_url=base_url), 'consumer_key': token.consumer.key, 'token_key': token.key, 'token_secret': token.secret, } } }
def compose_cloud_init_preseed(node, token, base_url=''): """Compose the preseed value for a node in any state but Commissioning. Returns cloud-config that's preseeded to cloud-init via debconf (It only configures cloud-init in Ubuntu Classic systems. Ubuntu Core does not have debconf as it is not Debian based. """ credentials = urlencode({ 'oauth_consumer_key': token.consumer.key, 'oauth_token_key': token.key, 'oauth_token_secret': token.secret, }) config = { # Do not let cloud-init override /etc/hosts/: use the default # behavior which means running `dns_resolve(hostname)` on a node # will query the DNS server (and not return 127.0.0.1). # See bug 1087183 for details. "manage_etc_hosts": False, "apt_preserve_sources_list": True, # Prevent the node from requesting cloud-init data on every reboot. # This is done so a machine does not need to contact MAAS every time # it reboots. "manual_cache_clean": True, } # This is used as preseed for a node that's been installed. # This will allow cloud-init to be configured with reporting for # a node that has already been installed. config.update( get_cloud_init_reporting(node=node, token=token, base_url=base_url)) # Add the system configuration information. config.update(get_system_info()) apt_proxy = get_apt_proxy(node.get_boot_rack_controller()) if apt_proxy: config['apt_proxy'] = apt_proxy # Add APT configuration for new cloud-init (>= 0.7.7-17) config.update(get_archive_config(node=node, preserve_sources=False)) local_config_yaml = yaml.safe_dump(config) # this is debconf escaping local_config = local_config_yaml.replace("\\", "\\\\").replace("\n", "\\n") # Preseed data to send to cloud-init. We set this as MAAS_PRESEED in # ks_meta, and it gets fed straight into debconf. preseed_items = [ ('datasources', 'multiselect', 'MAAS'), ('maas-metadata-url', 'string', absolute_reverse( 'metadata', base_url=base_url)), ('maas-metadata-credentials', 'string', credentials), ('local-cloud-config', 'string', local_config) ] return '\n'.join( "cloud-init cloud-init/%s %s %s" % ( item_name, item_type, item_value, ) for item_name, item_type, item_value in preseed_items)
def compose_preseed_url(node, *, base_url=None, default_region_ip=None): """Compose a metadata URL for `node`'s preseed data.""" # Always uses the latest version of the metadata API. version = 'latest' return absolute_reverse( 'metadata-node-by-id', default_region_ip=default_region_ip, args=[version, node.system_id], query={'op': 'get_preseed'}, base_url=base_url)
def compose_preseed_url(node, rack_controller): """Compose a metadata URL for `node`'s preseed data.""" # Always uses the latest version of the metadata API. version = 'latest' return absolute_reverse('metadata-node-by-id', args=[version, node.system_id], query={'op': 'get_preseed'}, base_url=rack_controller.url)
def compose_preseed_url(node): """Compose a metadata URL for `node`'s preseed data.""" # Always uses the latest version of the metadata API. version = 'latest' base_url = node.nodegroup.maas_url return absolute_reverse( 'metadata-node-by-id', args=[version, node.system_id], query={'op': 'get_preseed'}, base_url=base_url)
def compose_preseed_url(node): """Compose a metadata URL for `node`'s preseed data.""" # Always uses the latest version of the metadata API. version = 'latest' base_url = node.nodegroup.maas_url return absolute_reverse('metadata-node-by-id', args=[version, node.system_id], query={'op': 'get_preseed'}, base_url=base_url)
def test_absolute_reverse_uses_kwargs(self): maas_url = factory.make_simple_http_url() user = factory.make_User() self.useFixture(RegionConfigurationFixture(maas_url=maas_url)) absolute_url = absolute_reverse('accounts-edit', kwargs={'username': user.username}) reversed_url = reverse('accounts-edit', args=[user.username]) expected_url = self.expected_from_maas_url_and_reverse( maas_url, reversed_url) self.assertEqual(expected_url, absolute_url)
def compose_curtin_preseed(node, token, base_url='', default_region_ip=None): """Compose the preseed value for a node being installed with curtin.""" metadata_url = absolute_reverse('curtin-metadata', default_region_ip=default_region_ip, base_url=base_url) return _compose_cloud_init_preseed(node, token, metadata_url, base_url=base_url, default_region_ip=default_region_ip)
def test_absolute_reverse_uses_kwargs(self): maas_url = factory.make_simple_http_url() filename = factory.make_name("file") self.useFixture(RegionConfigurationFixture(maas_url=maas_url)) absolute_url = absolute_reverse("simplestreams_stream_handler", kwargs={"filename": filename}) reversed_url = reverse("simplestreams_stream_handler", args=[filename]) expected_url = self.expected_from_maas_url_and_reverse( maas_url, reversed_url) self.assertEqual(expected_url, absolute_url)
def test_absolute_reverse_uses_query_string(self): maas_url = factory.make_simple_http_url() self.useFixture(RegionConfigurationFixture(maas_url=maas_url)) parameters = {factory.make_string(): factory.make_string()} absolute_url = absolute_reverse("login", query=parameters) reversed_url = "%s?%s" % (reverse("login"), urlencode(parameters)) expected_url = self.expected_from_maas_url_and_reverse( maas_url, reversed_url) self.assertEqual(expected_url, absolute_url)
def compose_commissioning_preseed(node, token, base_url=''): """Compose the preseed value for a Commissioning node.""" metadata_url = absolute_reverse('metadata', base_url=base_url) if node.status == NODE_STATUS.DISK_ERASING: poweroff_timeout = timedelta(days=7).total_seconds() # 1 week else: poweroff_timeout = timedelta(hours=1).total_seconds() # 1 hour return _compose_cloud_init_preseed( node, token, metadata_url, base_url=base_url, poweroff_timeout=int(poweroff_timeout))
def generate_user_data( node, userdata_template_file, extra_context=None, rack_controller=None, request=None, ): """Produce a user_data script for use by an ephemeral environment. The main template file contains references to so-called ``snippets'' which are read in here, and substituted. In addition, the regular preseed context variables are available (such as 'http_proxy'). The final result is a MIME multipart message that consists of a 'cloud-config' part and an 'x-shellscript' part. This allows maximum flexibility with cloud-init as we read in a template 'user_data_config.template' to set cloud-init configs before the script is run. :rtype: `bytes` """ # Enlisting machines will not have a node object or an assoicated # rack controller if the subnet is unknown to MAAS or MAAS does not # control DHCP on the VLAN(see find_rack_controller in maasserver.utils) if rack_controller is None and node is not None: rack_controller = node.get_boot_rack_controller() userdata_template = tempita.Template.from_filename(userdata_template_file, encoding=ENCODING) # The preseed context is a dict containing various configs that the # templates can use. if request is None: server_url = absolute_reverse("machines_handler") else: server_url = request.build_absolute_uri(reverse("machines_handler")) configs = Config.objects.get_configs(["maas_auto_ipmi_user"]) preseed_context = { "node": node, "server_url": server_url, "maas_ipmi_user": configs["maas_auto_ipmi_user"], } # Render the snippets in the main template. snippets = get_snippet_context(encoding=ENCODING) snippets.update(preseed_context) if extra_context is not None: snippets.update(extra_context) userdata = userdata_template.substitute(snippets).encode(ENCODING) data_part = MIMEText(userdata, "x-shellscript", ENCODING) data_part.add_header("Content-Disposition", 'attachment; filename="user_data.sh"') combined = MIMEMultipart() combined.attach(data_part) return combined.as_bytes()
def compose_enlistment_preseed_url(nodegroup=None): """Compose enlistment preseed URL. :param nodegroup: The nodegroup used to generate the preseed. """ # Always uses the latest version of the metadata API. base_url = nodegroup.maas_url if nodegroup is not None else None version = 'latest' return absolute_reverse( 'metadata-enlist-preseed', args=[version], query={'op': 'get_enlist_preseed'}, base_url=base_url)
def compose_enlistment_preseed_url(rack_controller=None): """Compose enlistment preseed URL. :param rack_controller: The rack controller used to generate the preseed. """ # Always uses the latest version of the metadata API. base_url = (rack_controller.url if rack_controller is not None else None) version = 'latest' return absolute_reverse('metadata-enlist-preseed', args=[version], query={'op': 'get_enlist_preseed'}, base_url=base_url)
def compose_enlistment_preseed_url(nodegroup=None): """Compose enlistment preseed URL. :param nodegroup: The nodegroup used to generate the preseed. """ # Always uses the latest version of the metadata API. base_url = nodegroup.maas_url if nodegroup is not None else None version = 'latest' return absolute_reverse('metadata-enlist-preseed', args=[version], query={'op': 'get_enlist_preseed'}, base_url=base_url)
def get_preseed_context(release='', nodegroup=None): """Return the node-independent context dictionary to be used to render preseed templates. :param release: See `get_preseed_filenames`. :param nodegroup: The nodegroup used to generate the preseed. :return: The context dictionary. :rtype: dict. """ server_host = get_maas_facing_server_host(nodegroup=nodegroup) main_archive_hostname, main_archive_directory = get_hostname_and_path( Config.objects.get_config('main_archive')) ports_archive_hostname, ports_archive_directory = get_hostname_and_path( Config.objects.get_config('ports_archive')) if nodegroup is None: base_url = None cluster_host = None else: base_url = nodegroup.maas_url cluster_if = nodegroup.get_managed_interface() any_cluster_if = nodegroup.get_any_interface() cluster_host = None if cluster_if is None: if any_cluster_if is not None: cluster_host = any_cluster_if.ip else: cluster_host = cluster_if.ip return { 'main_archive_hostname': main_archive_hostname, 'main_archive_directory': main_archive_directory, 'ports_archive_hostname': ports_archive_hostname, 'ports_archive_directory': ports_archive_directory, 'release': release, 'server_host': server_host, 'server_url': absolute_reverse('nodes_handler', base_url=base_url), 'metadata_enlist_url': absolute_reverse('enlist', base_url=base_url), 'http_proxy': Config.objects.get_config('http_proxy'), 'cluster_host': cluster_host, }
def compose_commissioning_preseed(token, base_url=''): """Compose the preseed value for a Commissioning node.""" return "#cloud-config\n%s" % yaml.safe_dump({ 'datasource': { 'MAAS': { 'metadata_url': absolute_reverse( 'metadata', base_url=base_url), 'consumer_key': token.consumer.key, 'token_key': token.key, 'token_secret': token.secret, } } })
def get_preseed_context(osystem='', release='', rack_controller=None, default_region_ip=None): """Return the node-independent context dictionary to be used to render preseed templates. :param osystem: See `get_preseed_filenames`. :param release: See `get_preseed_filenames`. :param rack_controller: The rack controller used to generate the preseed. :return: The context dictionary. :rtype: dict. """ server_host = get_maas_facing_server_host( rack_controller=rack_controller, default_region_ip=default_region_ip) if rack_controller is None: base_url = None else: base_url = rack_controller.url return { 'osystem': osystem, 'release': release, 'server_host': server_host, 'server_url': absolute_reverse('machines_handler', default_region_ip=default_region_ip, base_url=base_url), 'syslog_host_port': '%s:%d' % (server_host, RSYSLOG_PORT), 'metadata_enlist_url': absolute_reverse('enlist', default_region_ip=default_region_ip, base_url=base_url), }
def get_cloud_init_reporting(node, token, base_url): """Return the cloud-init metadata to enable reporting""" return { 'reporting': { 'maas': { 'type': 'webhook', 'endpoint': absolute_reverse( 'metadata-status', args=[node.system_id], base_url=base_url), 'consumer_key': token.consumer.key, 'token_key': token.key, 'token_secret': token.secret, } } }
def test_compose_preseed_with_curtin_installer(self): node = factory.make_node(status=NODE_STATUS.READY) node.use_fastpath_installer() preseed = compose_preseed(node) preseed = yaml.safe_load(compose_preseed(node)) self.assertIn('datasource', preseed) self.assertIn('MAAS', preseed['datasource']) self.assertThat( preseed['datasource']['MAAS'], KeysEqual( 'metadata_url', 'consumer_key', 'token_key', 'token_secret')) self.assertEqual( absolute_reverse('curtin-metadata'), preseed['datasource']['MAAS']['metadata_url'])
def compose_enlistment_preseed_url(rack_controller=None, default_region_ip=None): """Compose enlistment preseed URL. :param rack_controller: The rack controller used to generate the preseed. :param default_region_ip: The preferred IP address this region should communicate on. """ # Always uses the latest version of the metadata API. base_url = (rack_controller.url if rack_controller is not None else None) version = 'latest' return absolute_reverse('metadata-enlist-preseed', default_region_ip=default_region_ip, args=[version], query={'op': 'get_enlist_preseed'}, base_url=base_url)
def get_curtin_cloud_config(node): """Compose the curtin cloud-config, which is only applied to Ubuntu core (by curtin).""" token = NodeKey.objects.get_token_for_node(node) rack_controller = node.get_boot_rack_controller() base_url = rack_controller.url datasource = { 'datasource': { 'MAAS': { 'consumer_key': token.consumer.key, 'token_key': token.key, 'token_secret': token.secret, 'metadata_url': absolute_reverse('metadata', base_url=base_url), } } } config = { 'maas-datasource': { 'path': '/etc/cloud/cloud.cfg.d/90_maas_datasource.cfg', 'content': 'datasource_list: [ MAAS ]', }, 'maas-cloud-config': { 'path': '/etc/cloud/cloud.cfg.d/90_maas_cloud_config.cfg', 'content': "#cloud-config\n%s" % yaml.safe_dump(datasource) }, } # Add the Ubuntu SSO email if its set on the user. if node.owner is not None and node.owner.email: config['maas-ubuntu-sso'] = { 'path': '/etc/cloud/cloud.cfg.d/90_maas_ubuntu_sso.cfg', 'content': "#cloud-config\n%s" % yaml.safe_dump({'snappy': { 'email': node.owner.email }}) } config['maas-reporting'] = { 'path': '/etc/cloud/cloud.cfg.d/90_maas_cloud_init_reporting.cfg', 'content': '#cloud-config\n%s' % yaml.safe_dump( get_cloud_init_reporting(node=node, token=token, base_url=base_url)) } return {'cloudconfig': config}
def get_node_preseed_context(node, osystem='', release='', rack_controller=None, default_region_ip=None): """Return the node-dependent context dictionary to be used to render preseed templates. :param node: See `get_preseed_filenames`. :param osystem: See `get_preseed_filenames`. :param release: See `get_preseed_filenames`. :return: The context dictionary. :rtype: dict. """ if rack_controller is None: rack_controller = node.get_boot_rack_controller() # Create the url and the url-data (POST parameters) used to turn off # PXE booting once the install of the node is finished. node_disable_pxe_url = absolute_reverse( 'metadata-node-by-id', default_region_ip=default_region_ip, args=['latest', node.system_id], base_url=rack_controller.url) node_disable_pxe_data = urlencode({'op': 'netboot_off'}) driver = get_third_party_driver(node) return { 'third_party_drivers': (Config.objects.get_config('enable_third_party_drivers')), 'driver': driver, 'driver_package': driver.get('package', ''), 'node': node, 'preseed_data': compose_preseed(get_preseed_type_for(node), node, default_region_ip=default_region_ip), 'node_disable_pxe_url': node_disable_pxe_url, 'node_disable_pxe_data': node_disable_pxe_data, 'license_key': node.get_effective_license_key(), }
def get_node_preseed_context(node, release=''): """Return the node-dependent context dictionary to be used to render preseed templates. :param node: See `get_preseed_filenames`. :param release: See `get_preseed_filenames`. :return: The context dictionary. :rtype: dict. """ # Create the url and the url-data (POST parameters) used to turn off # PXE booting once the install of the node is finished. node_disable_pxe_url = absolute_reverse( 'metadata-node-by-id', args=['latest', node.system_id], base_url=node.nodegroup.maas_url) node_disable_pxe_data = urlencode({'op': 'netboot_off'}) return { 'node': node, 'preseed_data': compose_preseed(node), 'node_disable_pxe_url': node_disable_pxe_url, 'node_disable_pxe_data': node_disable_pxe_data, }
def test_compose_preseed_includes_metadata_url(self): node = factory.make_node(status=NODE_STATUS.READY) self.assertIn(absolute_reverse('metadata'), compose_preseed(node))
def compose_commissioning_preseed(token, base_url=''): """Compose the preseed value for a Commissioning node.""" metadata_url = absolute_reverse('metadata', base_url=base_url) return _compose_cloud_init_preseed(token, metadata_url)
def compose_curtin_preseed(token, base_url=''): """Compose the preseed value for a node being installed with curtin.""" metadata_url = absolute_reverse('curtin-metadata', base_url=base_url) return _compose_cloud_init_preseed(token, metadata_url)
def test_absolute_reverse_uses_DEFAULT_MAAS_URL_by_default(self): maas_url = 'http://%s' % factory.getRandomString() self.patch(settings, 'DEFAULT_MAAS_URL', maas_url) absolute_url = absolute_reverse('settings') expected_url = settings.DEFAULT_MAAS_URL + reverse('settings') self.assertEqual(expected_url, absolute_url)
def test_absolute_reverse_uses_given_base_url(self): maas_url = 'http://%s' % factory.getRandomString() absolute_url = absolute_reverse('settings', base_url=maas_url) expected_url = maas_url + reverse('settings') self.assertEqual(expected_url, absolute_url)
def test_absolute_reverse_uses_query_string(self): self.patch(settings, 'DEFAULT_MAAS_URL', '') parameters = {factory.getRandomString(): factory.getRandomString()} absolute_url = absolute_reverse('settings', query=parameters) expected_url = '%s?%s' % (reverse('settings'), urlencode(parameters)) self.assertEqual(expected_url, absolute_url)
def test_compose_preseed_for_commissioning_includes_metadata_url(self): node = factory.make_node(status=NODE_STATUS.COMMISSIONING) preseed = yaml.safe_load(compose_preseed(node)) self.assertEqual( absolute_reverse('metadata'), preseed['datasource']['MAAS']['metadata_url'])