This file is indexed.

/usr/lib/python3/dist-packages/provisioningserver/rpc/boot_images.py is in python3-maas-provisioningserver 2.0.0~beta3+bzr4941-0ubuntu1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# Copyright 2014-2015 Canonical Ltd.  This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).

"""RPC relating to boot images."""

__all__ = [
    "import_boot_images",
    "list_boot_images",
    "is_import_boot_images_running",
    ]

from urllib.parse import urlparse

from provisioningserver import concurrency
from provisioningserver.auth import get_maas_user_gpghome
from provisioningserver.boot import tftppath
from provisioningserver.config import ClusterConfiguration
from provisioningserver.import_images import boot_resources
from provisioningserver.utils.env import environment_variables
from provisioningserver.utils.twisted import synchronous
from twisted.internet.threads import deferToThread


CACHED_BOOT_IMAGES = None


def list_boot_images():
    """List the boot images that exist on the cluster.

    This return value of this function is cached. This helps reduce the amount
    of IO, as this function is called often. To update the cache call
    `reload_boot_images`.
    """

    global CACHED_BOOT_IMAGES
    if CACHED_BOOT_IMAGES is None:
        with ClusterConfiguration.open() as config:
            tftp_root = config.tftp_root
        CACHED_BOOT_IMAGES = tftppath.list_boot_images(tftp_root)
    return CACHED_BOOT_IMAGES


def reload_boot_images():
    """Update the cached boot images so `list_boot_images` returns the
    most up-to-date boot images list."""
    global CACHED_BOOT_IMAGES
    with ClusterConfiguration.open() as config:
        tftp_root = config.tftp_root
    CACHED_BOOT_IMAGES = tftppath.list_boot_images(tftp_root)


def get_hosts_from_sources(sources):
    """Return set of hosts that are contained in the given sources."""
    hosts = set()
    for source in sources:
        url = urlparse(source['url'])
        if url.hostname is not None:
            hosts.add(url.hostname)
    return hosts


def fix_sources_for_cluster(sources):
    """Return modified sources that use the URL to the region defined in the
    cluster configuration instead of the one the region suggested."""
    sources = list(sources)
    with ClusterConfiguration.open() as config:
        maas_url = config.maas_url
    maas_url_parsed = urlparse(maas_url)
    maas_url_path = maas_url_parsed.path.lstrip('/').rstrip('/')
    for source in sources:
        url = urlparse(source['url'])
        source_path = url.path.lstrip('/')
        # Most likely they will both have 'MAAS/' at the start. We can't just
        # append because then the URL would be 'MAAS/MAAS/' which is incorrect.
        # If the initial part of the URL defined in the config matches the
        # beginning of what the region told the cluster to use then strip it
        # out and build the new URL.
        if source_path.startswith(maas_url_path):
            source_path = source_path[len(maas_url_path):]
        url = maas_url.rstrip('/') + '/' + source_path.lstrip('/')
        source['url'] = url
    return sources


@synchronous
def _run_import(sources, http_proxy=None, https_proxy=None):
    """Run the import.

    This is function is synchronous so it must be called with deferToThread.
    """
    # Fix the sources to download from the IP address defined in the cluster
    # configuration, instead of the URL that the region asked it to use.
    sources = fix_sources_for_cluster(sources)
    variables = {
        'GNUPGHOME': get_maas_user_gpghome(),
        }
    if http_proxy is not None:
        variables['http_proxy'] = http_proxy
    if https_proxy is not None:
        variables['https_proxy'] = https_proxy
    # Communication to the sources and loopback should not go through proxy.
    no_proxy_hosts = ["localhost", "127.0.0.1", "::1"]
    no_proxy_hosts += list(get_hosts_from_sources(sources))
    variables['no_proxy'] = ','.join(no_proxy_hosts)
    with environment_variables(variables):
        boot_resources.import_images(sources)

    # Update the boot images cache so `list_boot_images` returns the
    # correct information.
    reload_boot_images()


def import_boot_images(sources, http_proxy=None, https_proxy=None):
    """Imports the boot images from the given sources."""
    lock = concurrency.boot_images
    if not lock.locked:
        return lock.run(
            deferToThread, _run_import, sources,
            http_proxy=http_proxy, https_proxy=https_proxy)


def is_import_boot_images_running():
    """Return True if the import process is currently running."""
    return concurrency.boot_images.locked