~lutostag/ubuntu/trusty/maas/1.5.2+packagefix

« back to all changes in this revision

Viewing changes to scripts/maas-import-pxe-files

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez
  • Date: 2014-03-28 10:43:53 UTC
  • mto: This revision was merged to the branch mainline in revision 57.
  • Revision ID: package-import@ubuntu.com-20140328104353-ekpolg0pm5xnvq2s
Tags: upstream-1.5+bzr2204
ImportĀ upstreamĀ versionĀ 1.5+bzr2204

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env bash
2
 
# Copyright 2012, 2013 Canonical Ltd.  This software is licensed under the
 
1
#!/usr/bin/env python2.7
 
2
# -*- mode: python -*-
 
3
# Copyright 2014 Canonical Ltd.  This software is licensed under the
3
4
# GNU Affero General Public License version 3 (see the file LICENSE).
4
 
#
5
 
# Download static files needed for net-booting nodes through TFTP:
6
 
# pre-boot loader, kernels, and initrd images.
7
 
#
8
 
# This script downloads the required files into the TFTP home directory
9
 
# (by default, /var/lib/maas/tftp).  Run it with the necessarily privileges
10
 
# to write them there.
11
 
 
12
 
# Exit immediately if a command exits with a non-zero status.
13
 
set -o errexit
14
 
# Treat unset variables as an error when substituting.
15
 
set -o nounset
16
 
 
17
 
# Load settings if available.
18
 
settings="/etc/maas/import_pxe_files"
19
 
[ -r $settings ] && . $settings
20
 
 
21
 
# Location of the GPG keyring for the Ubuntu archive.
22
 
GPG_KEYRING="${GPG_KEYRING:-/usr/share/keyrings/ubuntu-archive-keyring.gpg}"
23
 
 
24
 
# Whether to skip checking GPG keys (necessary for testing of this script).
25
 
# Set this to a nonempty string to skip checking.  This is needed for test
26
 
# programs, because they can't possibly sign with the right key.
27
 
IGNORE_GPG="${IGNORE_GPG:-}"
28
 
 
29
 
# Download locations for Ubuntu releases.  When the cluster controller runs
30
 
# the import scripts, it provides settings from the server side.
31
 
MAIN_ARCHIVE=${MAIN_ARCHIVE:-http://archive.ubuntu.com/ubuntu/}
32
 
PORTS_ARCHIVE=${PORTS_ARCHIVE:-http://ports.ubuntu.com/ubuntu-ports/}
33
 
 
34
 
# Ubuntu releases that are to be downloaded.
35
 
SUPPORTED_RELEASES=$(distro-info --supported)
36
 
RELEASES=${RELEASES:-$SUPPORTED_RELEASES}
37
 
 
38
 
# The current Ubuntu release.
39
 
STABLE_RELEASE=$(distro-info --stable)
40
 
 
41
 
# Supported architectures.
42
 
ARCHES=${ARCHES:-amd64/generic i386/generic armhf/highbank armhf/generic}
43
 
 
44
 
# Command line to download a resource at a given URL into the current
45
 
# directory.  A wget command line will work here, but curl will do as well.
46
 
DOWNLOAD=${DOWNLOAD:-wget --no-verbose}
47
 
 
48
 
# Whether to download ephemeral images as well: "1" for yes, "0" for no.
49
 
# Default is yes.
50
 
IMPORT_EPHEMERALS=${IMPORT_EPHEMERALS:-1}
51
 
 
52
 
fail() {
53
 
    local msg=$1
54
 
 
55
 
    echo $msg >&2
56
 
    exit 1
57
 
}
58
 
 
59
 
# Show script usage/summary.
60
 
show_usage() {
61
 
    echo "Usage: ${0##*/}"
62
 
    echo
63
 
    echo "This helper script downloads the relevant boot images from an "
64
 
    echo "Ubuntu archive and uses 'maas' to provision them for PXE booting "
65
 
    echo "from TFTP."
66
 
    echo
67
 
    echo "This script takes no arguments, but you can adjust some parameters "
68
 
    echo -e "by editing the config file found at \033[1m$settings\033[0m."
69
 
    echo
70
 
    echo "MAAS homepage:<http://maas.ubuntu.com>"
71
 
    echo
72
 
}
73
 
 
74
 
# Return a URL that points to the images directory for the relevant
75
 
# release/arch.
76
 
compose_installer_base_url() {
77
 
    local arch=$1 release=$2
78
 
 
79
 
    case $arch in
80
 
        amd64/*|i386/*)
81
 
            local installer_url="$MAIN_ARCHIVE/dists/$release/main/installer-${arch%%/*}"
82
 
            echo "$installer_url/current/images/"
83
 
            ;;
84
 
        armhf/*)
85
 
            # No ARM server installers were available in precise, so always go for -updates for now
86
 
            # A better general fix is LP: #1052397
87
 
            if [ "$release" = "precise" ]; then
88
 
                updates=-updates
89
 
            else
90
 
                updates=
91
 
            fi
92
 
            local installer_url="$PORTS_ARCHIVE/dists/${release}${updates}/main/installer-${arch%%/*}"
93
 
            echo "$installer_url/current/images/"
94
 
            ;;
95
 
        *)
96
 
            echo "Unknown architecture: $arch" >&2
97
 
            exit 1
98
 
            ;;
99
 
    esac
100
 
}
101
 
 
102
 
# Return the URL part that is appended to the base url that gives the location
103
 
# of the images.
104
 
compose_installer_download_url_postfix() {
105
 
    local arch=$1
106
 
 
107
 
    case $arch in
108
 
        amd64/*|i386/*)
109
 
            echo "netboot/ubuntu-installer/${arch%%/*}/"
110
 
            ;;
111
 
        armhf/*)
112
 
            echo "${arch#*/}/netboot/"
113
 
            ;;
114
 
        *)
115
 
            echo "Unknown architecture: $arch" >&2
116
 
            exit 1
117
 
            ;;
118
 
    esac
119
 
}
120
 
 
121
 
# Put together a full URL for where the installer files for architecture $1
122
 
# and release $2 can be downloaded.
123
 
compose_installer_download_url() {
124
 
    local arch=$1 release=$2
125
 
 
126
 
    base_url=$(compose_installer_base_url $arch $release)
127
 
    postfix=$(compose_installer_download_url_postfix $arch)
128
 
 
129
 
    echo "$base_url/$postfix"
130
 
}
131
 
 
132
 
# Fetch MD5SUMS file.  This returns false (i.e. nonzero) in the case of
133
 
# survivable failure, so that the caller can skip this image and move on.
134
 
fetch_server_md5sums() {
135
 
    local base_url=$1
136
 
 
137
 
    if ! $DOWNLOAD "$base_url/MD5SUMS"
138
 
    then
139
 
        echo "Unable to download $base_url/MD5SUMS" >&2
140
 
        return 1
141
 
    fi
142
 
 
143
 
    if [ "x$IGNORE_GPG" == "x" ]
144
 
    then
145
 
        if ! $DOWNLOAD "$base_url/MD5SUMS.gpg"
146
 
        then
147
 
            echo "Unable to download $base_url/MD5SUMS.gpg" >&2
148
 
            return 1
149
 
        fi
150
 
 
151
 
        if ! gpg --keyring=$GPG_KEYRING --verify MD5SUMS.gpg MD5SUMS >/dev/null 2>/dev/null
152
 
        then
153
 
            echo "Failed to verify MD5SUMS via $GPG_KEYRING ($base_url/MD5SUMS)" >&2
154
 
            return 1
155
 
        fi
156
 
    fi
157
 
    return 0
158
 
}
159
 
 
160
 
get_md5sum_for_file() {
161
 
    local filename=$1
162
 
 
163
 
    # The filename supplied in $1 must be the full path as seen in the
164
 
    # MD5SUMS file.  The files are rooted from a single place so the grepped
165
 
    # string will only match once.
166
 
    server_md5sum=$(grep $filename MD5SUMS|awk '{print $1}') ||
167
 
        fail "failed to find checksum for $filename"
168
 
    echo $server_md5sum
169
 
}
170
 
 
171
 
check_checksum() {
172
 
    local server_md5sum=$1 file_on_disk=$2
173
 
    local md5sum
174
 
 
175
 
    md5sum=$(md5sum $file_on_disk|awk '{print $1}')
176
 
 
177
 
    if [ "$md5sum" != "$server_md5sum" ]; then
178
 
        fail "md5 checksum mismatch for $file_on_disk: expected $server_md5sum, got $md5sum"
179
 
    fi
180
 
}
181
 
 
182
 
# Return a list of files for architecture $1 and release $2 that need to be
183
 
# downloaded
184
 
compose_installer_download_files() {
185
 
    local arch=$1 release=$2
186
 
 
187
 
    case $arch in
188
 
        amd64/*|i386/*)
189
 
            echo "linux initrd.gz"
190
 
            ;;
191
 
        armhf/*)
192
 
            echo "vmlinuz initrd.gz"
193
 
            ;;
194
 
        *)
195
 
            echo "Unknown architecture: $arch" >&2
196
 
            exit 1
197
 
            ;;
198
 
    esac
199
 
}
200
 
 
201
 
 
202
 
# Rename downloaded files for architecture $1 and release $2 into the form that
203
 
# MAAS expects them
204
 
rename_installer_download_files() {
205
 
    local arch=$1 release=$2
206
 
 
207
 
    case $arch in
208
 
        amd64/*|i386/*)
209
 
            # do nothing
210
 
            ;;
211
 
        armhf/*)
212
 
            mv vmlinuz linux
213
 
            ;;
214
 
        *)
215
 
            echo "Unknown architecture: $arch" >&2
216
 
            exit 1
217
 
            ;;
218
 
    esac
219
 
}
220
 
 
221
 
 
222
 
# Copy the pre-boot loader pxelinux.0, and modules we need, from the
223
 
# installed syslinux version.  Install it into the TFTP tree for
224
 
# netbooting.
225
 
update_pre_boot_loader() {
226
 
    for loader_file in pxelinux.0 chain.c32 ifcpu64.c32
227
 
    do
228
 
        maas-provision install-pxe-bootloader \
229
 
            --loader="/usr/lib/syslinux/$loader_file"
230
 
    done
231
 
}
232
 
 
233
 
 
234
 
# Download kernel/initrd for installing Ubuntu release $2 for
235
 
# architecture $1.
236
 
download_install_files() {
237
 
    local arch=$1 release=$2
238
 
    local files file url file_prefix filename_in_md5sums_file md5sum
239
 
 
240
 
    files=$(compose_installer_download_files $arch $release)
241
 
    url=$(compose_installer_download_url $arch $release)
242
 
 
243
 
    mkdir "install"
244
 
    pushd "install" >/dev/null
245
 
    if ! fetch_server_md5sums $(compose_installer_base_url $arch $release)
246
 
    then
247
 
        echo "Failed to download MD5 sums for $arch $release." >&2
248
 
        popd >/dev/null
249
 
        rm -rf "install"
250
 
        return 1
251
 
    fi
252
 
    echo "MD5SUMS GPG signature OK for $arch $release"
253
 
    for file in $files
254
 
    do
255
 
        if ! $DOWNLOAD $url/$file
256
 
        then
257
 
            # Download failed.  Log error, and skip this image.
258
 
            echo "Failed to download $url/$file" >&2
259
 
            popd >/dev/null
260
 
            rm -rf "install"
261
 
            return 1
262
 
        fi
263
 
        file_prefix=$(compose_installer_download_url_postfix $arch)
264
 
        filename_in_md5sums_file=./$file_prefix$file
265
 
        md5sum=$(get_md5sum_for_file $filename_in_md5sums_file)
266
 
        check_checksum $md5sum $file
267
 
        echo "'$file' md5sum OK"
268
 
    done
269
 
    rename_installer_download_files $arch $release
270
 
    popd >/dev/null
271
 
    return 0
272
 
}
273
 
 
274
 
# Download kernel/initrd for installing Ubuntu release $2 for
275
 
# architecture $1, and install them into the TFTP directory hierarchy.
276
 
update_install_files() {
277
 
    local arch=$1 release=$2
278
 
 
279
 
    # Try the -updates pocket first, and fall back to release if it failed.
280
 
    if ! download_install_files $arch ${release}-updates
281
 
    then
282
 
        echo "$release-updates not available, falling back to release"
283
 
        if ! download_install_files $arch $release
284
 
        then
285
 
            return
286
 
        fi
287
 
    fi
288
 
 
289
 
    maas-provision install-pxe-image \
290
 
        --arch="${arch%%/*}" --subarch="${arch#*/}" \
291
 
        --release=$release --purpose="install" \
292
 
        --image="install"
293
 
}
294
 
 
295
 
 
296
 
# Download and install the "install" images.
297
 
import_install_images() {
298
 
    local arch release DOWNLOAD_DIR
299
 
 
300
 
    DOWNLOAD_DIR=$(mktemp -d)
301
 
    echo "Downloading to temporary location $DOWNLOAD_DIR."
302
 
    pushd -- $DOWNLOAD_DIR
303
 
 
304
 
    for arch in $ARCHES
305
 
    do
306
 
        for release in $RELEASES
307
 
        do
308
 
            update_install_files $arch $release
309
 
        done
310
 
    done
311
 
 
312
 
    popd
313
 
    rm -rf -- $DOWNLOAD_DIR
314
 
}
315
 
 
316
 
 
317
 
# Download and install the ephemeral images.
318
 
import_ephemeral_images() {
319
 
    if test "$IMPORT_EPHEMERALS" != "0"
320
 
    then
321
 
        maas-import-ephemerals
322
 
    fi
323
 
}
324
 
 
325
 
 
326
 
main() {
327
 
    # All files we create here are public.  The TFTP user will need to be
328
 
    # able to read them.
329
 
    umask a+r
330
 
 
331
 
    update_pre_boot_loader
332
 
    import_install_images
333
 
    import_ephemeral_images
334
 
}
335
 
 
336
 
# check for commandline arguments
337
 
if [ $# -gt 0 ]
338
 
  then
339
 
   case $1 in
340
 
    "-h"|"--help") show_usage ; exit ;;
341
 
    esac
342
 
fi
343
 
 
344
 
if [ ! -f "$GPG_KEYRING" ]; then
345
 
    fail "gpg keyring $GPG_KEYRING is not a file"
346
 
fi
347
 
 
348
 
main
 
5
 
 
6
"""Import boot resources into MAAS cluster controller."""
 
7
 
 
8
from __future__ import (
 
9
    absolute_import,
 
10
    print_function,
 
11
    unicode_literals,
 
12
    )
 
13
 
 
14
str = None
 
15
 
 
16
__metaclass__ = type
 
17
 
 
18
from provisioningserver.import_images.boot_resources import (
 
19
    logger,
 
20
    main,
 
21
    make_arg_parser,
 
22
    NoConfigFile,
 
23
    )
 
24
 
 
25
 
 
26
if __name__ == "__main__":
 
27
    parser = make_arg_parser(__doc__)
 
28
    args = parser.parse_args()
 
29
    try:
 
30
        main(args)
 
31
    except NoConfigFile:
 
32
        logger.error("Config file %s not found." % args.config_file)
 
33
        raise SystemExit(1)
 
34
    except Exception:
 
35
        # logger.exception() will log the error message, followed by the
 
36
        # exception's stack trace. Using it here rather than allowing
 
37
        # the exception to kill the process unhandled means we can be
 
38
        # sure about where the exception ends up, rather than it
 
39
        # potentially vanishing.
 
40
        logger.exception("Unhandled exception; unable to continue.")
 
41
        raise SystemExit(2)