Exemple #1
0
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'),
        }
Exemple #2
0
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)
Exemple #3
0
    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))
Exemple #4
0
 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)
Exemple #5
0
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)
Exemple #6
0
 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)
Exemple #7
0
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)
Exemple #8
0
 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)
Exemple #9
0
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
Exemple #10
0
 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)
Exemple #11
0
    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)
Exemple #12
0
 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'])
Exemple #13
0
 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)
Exemple #14
0
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,
                }
            }
        }
Exemple #15
0
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)
Exemple #16
0
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)
Exemple #17
0
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)
Exemple #18
0
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)
Exemple #19
0
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)
Exemple #20
0
 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)
Exemple #21
0
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)
Exemple #22
0
 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)
Exemple #23
0
    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)
Exemple #24
0
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))
Exemple #25
0
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()
Exemple #26
0
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)
Exemple #27
0
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)
Exemple #28
0
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)
Exemple #29
0
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,
    }
Exemple #30
0
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,
            }
        }
    })
Exemple #31
0
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),
    }
Exemple #32
0
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'])
Exemple #34
0
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)
Exemple #35
0
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}
Exemple #36
0
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(),
    }
Exemple #37
0
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))
Exemple #39
0
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)
Exemple #40
0
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)
Exemple #41
0
 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)
Exemple #42
0
 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)
Exemple #43
0
 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'])