~maas-committers/maas/trunk

« back to all changes in this revision

Viewing changes to src/metadataserver/commissioning/user_data.py

[r=allenap][bug=][author=jtv] Make commissioning nodes download their commissioning scripts (such as lshw) from the metadata service.  And componentize the big commissioning script.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright 2012 Canonical Ltd.  This software is licensed under the
 
2
# GNU Affero General Public License version 3 (see the file LICENSE).
 
3
 
 
4
"""Generate commissioning user-data from template and code snippets.
 
5
 
 
6
This combines the `user_data.template` and the snippets of code in the
 
7
`snippets` directory into the main commissioning script.
 
8
 
 
9
Its contents are not customizable.  To inject custom code, use the
 
10
:class:`CommissioningScript` model.
 
11
"""
 
12
 
 
13
from __future__ import (
 
14
    absolute_import,
 
15
    print_function,
 
16
    unicode_literals,
 
17
    )
 
18
 
 
19
__metaclass__ = type
 
20
__all__ = [
 
21
    'generate_user_data',
 
22
    ]
 
23
 
 
24
from os import listdir
 
25
import os.path
 
26
 
 
27
import tempita
 
28
 
 
29
 
 
30
def read_snippet(snippets_dir, name, encoding='utf-8'):
 
31
    """Read a snippet file.
 
32
 
 
33
    :rtype: `unicode`
 
34
    """
 
35
    path = os.path.join(snippets_dir, name)
 
36
    with open(path, 'rb') as snippet_file:
 
37
        return snippet_file.read().decode(encoding)
 
38
 
 
39
 
 
40
def is_snippet(filename):
 
41
    """Does `filename` represent a valid snippet name?"""
 
42
    return all([
 
43
        not filename.startswith('.'),
 
44
        filename != '__init__.py',
 
45
        not filename.endswith('.pyc'),
 
46
        not filename.endswith('~'),
 
47
        ])
 
48
 
 
49
 
 
50
def list_snippets(snippets_dir):
 
51
    """List names of available snippets."""
 
52
    return filter(is_snippet, listdir(snippets_dir))
 
53
 
 
54
 
 
55
def strip_name(snippet_name):
 
56
    """Canonicalize a snippet name."""
 
57
    # Dot suffixes do not work well in tempita variable names.
 
58
    return snippet_name.replace('.', '_')
 
59
 
 
60
 
 
61
def generate_user_data():
 
62
    """Produce the main commissioning script.
 
63
 
 
64
    The script was templated so that code snippets become easier to
 
65
    maintain, check for lint, and ideally, unit-test.  However its
 
66
    contents are static: there are no variables.  It's perfectly
 
67
    cacheable.
 
68
 
 
69
    :rtype: `bytes`
 
70
    """
 
71
    encoding = 'utf-8'
 
72
    commissioning_dir = os.path.dirname(__file__)
 
73
    template_file = os.path.join(commissioning_dir, 'user_data.template')
 
74
    snippets_dir = os.path.join(commissioning_dir, 'snippets')
 
75
    template = tempita.Template.from_filename(template_file, encoding=encoding)
 
76
 
 
77
    snippets = {
 
78
        strip_name(name): read_snippet(snippets_dir, name, encoding=encoding)
 
79
        for name in list_snippets(snippets_dir)
 
80
    }
 
81
    return template.substitute(snippets).encode('utf-8')