Esempio n. 1
0
 def test_preseed_context_cluster_host(self):
     # The cluster_host context variable is derived from the nodegroup.
     release = factory.getRandomString()
     nodegroup = factory.make_node_group(maas_url=factory.getRandomString())
     context = get_preseed_context(release, nodegroup)
     self.assertIsNotNone(context["cluster_host"])
     self.assertEqual(nodegroup.get_managed_interface().ip,
                      context["cluster_host"])
Esempio n. 2
0
 def test_get_preseed_context_contains_keys(self):
     release = factory.getRandomString()
     nodegroup = factory.make_node_group(maas_url=factory.getRandomString())
     context = get_preseed_context(release, nodegroup)
     self.assertItemsEqual([
         'release', 'metadata_enlist_url', 'server_host', 'server_url',
         'cluster_host', 'main_archive_hostname', 'main_archive_directory',
         'ports_archive_hostname', 'ports_archive_directory', 'http_proxy'
     ], context)
Esempio n. 3
0
 def test_get_preseed_context_contains_keys(self):
     release = factory.getRandomString()
     nodegroup = factory.make_node_group(maas_url=factory.getRandomString())
     context = get_preseed_context(release, nodegroup)
     self.assertItemsEqual(
         ['release', 'metadata_enlist_url', 'server_host', 'server_url',
         'main_archive_hostname', 'main_archive_directory',
         'ports_archive_hostname', 'ports_archive_directory',
         'http_proxy',
         ],
         context)
Esempio n. 4
0
 def test_preseed_context_cluster_host_if_unmanaged(self):
     # If the nodegroup has no managed interface recorded, the cluster_host
     # context variable is still present and derived from the nodegroup.
     release = factory.getRandomString()
     nodegroup = factory.make_node_group(maas_url=factory.getRandomString())
     for interface in nodegroup.nodegroupinterface_set.all():
         interface.management = NODEGROUPINTERFACE_MANAGEMENT.UNMANAGED
         interface.save()
     context = get_preseed_context(release, nodegroup)
     self.assertIsNotNone(context["cluster_host"])
     self.assertEqual(nodegroup.get_any_interface().ip,
                      context["cluster_host"])
Esempio n. 5
0
def generate_user_data(nodegroup=None):
    """Produce the main commissioning script.

    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`
    """
    commissioning_dir = get_userdata_template_dir()
    userdata_template_file = os.path.join(commissioning_dir,
                                          'user_data.template')
    config_template_file = os.path.join(commissioning_dir,
                                        'user_data_config.template')
    userdata_template = tempita.Template.from_filename(userdata_template_file,
                                                       encoding=ENCODING)
    config_template = tempita.Template.from_filename(config_template_file,
                                                     encoding=ENCODING)
    # The preseed context is a dict containing various configs that the
    # templates can use.
    preseed_context = get_preseed_context(nodegroup=nodegroup)

    # Render the snippets in the main template.
    snippets = get_snippet_context(encoding=ENCODING)
    snippets.update(preseed_context)
    userdata = userdata_template.substitute(snippets).encode(ENCODING)

    # Render the config.
    config = config_template.substitute(preseed_context)

    # Create a MIME multipart message from the config and the userdata.
    config_part = MIMEText(config, 'cloud-config', ENCODING)
    config_part.add_header('Content-Disposition',
                           'attachment; filename="config"')
    data_part = MIMEText(userdata, 'x-shellscript', ENCODING)
    data_part.add_header('Content-Disposition',
                         'attachment; filename="user_data.sh"')
    combined = MIMEMultipart()
    combined.attach(config_part)
    combined.attach(data_part)
    return combined.as_string()
Esempio n. 6
0
def generate_user_data(node, userdata_template_file, extra_context=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`
    """
    # Avoid circular dependencies.
    from maasserver.preseed import get_preseed_context

    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.
    preseed_context = get_preseed_context(
        rack_controller=node.get_boot_rack_controller())
    preseed_context['node'] = node

    # 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()
Esempio n. 7
0
 def test_get_preseed_context_archive_refs(self):
     # urlparse lowercases the hostnames. That should not have any
     # impact but for testing, create lower-case hostnames.
     main_archive = make_url('main_archive')
     ports_archive = make_url('ports_archive')
     Config.objects.set_config('main_archive', main_archive)
     Config.objects.set_config('ports_archive', ports_archive)
     nodegroup = factory.make_node_group(maas_url=factory.getRandomString())
     context = get_preseed_context(factory.make_node(), nodegroup)
     parsed_main_archive = urlparse(main_archive)
     parsed_ports_archive = urlparse(ports_archive)
     self.assertEqual((
         parsed_main_archive.hostname,
         parsed_main_archive.path,
         parsed_ports_archive.hostname,
         parsed_ports_archive.path,
     ), (
         context['main_archive_hostname'],
         context['main_archive_directory'],
         context['ports_archive_hostname'],
         context['ports_archive_directory'],
     ))
Esempio n. 8
0
 def test_get_preseed_context_archive_refs(self):
     # urlparse lowercases the hostnames. That should not have any
     # impact but for testing, create lower-case hostnames.
     main_archive = make_url('main_archive')
     ports_archive = make_url('ports_archive')
     Config.objects.set_config('main_archive', main_archive)
     Config.objects.set_config('ports_archive', ports_archive)
     nodegroup = factory.make_node_group(maas_url=factory.getRandomString())
     context = get_preseed_context(factory.make_node(), nodegroup)
     parsed_main_archive = urlparse(main_archive)
     parsed_ports_archive = urlparse(ports_archive)
     self.assertEqual(
         (
             parsed_main_archive.hostname,
             parsed_main_archive.path,
             parsed_ports_archive.hostname,
             parsed_ports_archive.path,
         ),
         (
             context['main_archive_hostname'],
             context['main_archive_directory'],
             context['ports_archive_hostname'],
             context['ports_archive_directory'],
         ))
Esempio n. 9
0
 def test_preseed_context_null_cluster_host_if_does_not_exist(self):
     # If there's no nodegroup, the cluster_host context variable is
     # present, but None.
     release = factory.getRandomString()
     context = get_preseed_context(release)
     self.assertIsNone(context["cluster_host"])