~avishai-ish-shalom/cloud-init/chef

« back to all changes in this revision

Viewing changes to cloudinit/UserDataHandler.py

  • Committer: Avishai Ish-Shalom
  • Date: 2011-09-08 22:39:28 UTC
  • mfrom: (390.1.52 chef.fixes)
  • Revision ID: avishai.ish-shalom@mail.huji.ac.il-20110908223928-74by62gszzin4lkk
Merged main branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
from email.mime.base import MIMEBase
23
23
from email import encoders
24
24
import yaml
 
25
import cloudinit
 
26
import cloudinit.util as util
 
27
import md5
25
28
 
26
29
starts_with_mappings={
27
30
    '#include' : 'text/x-include-url',
 
31
    '#include-once' : 'text/x-include-once-url',
28
32
    '#!' : 'text/x-shellscript',
29
33
    '#cloud-config' : 'text/cloud-config',
30
34
    '#upstart-job'  : 'text/upstart-job',
45
49
 
46
50
def do_include(str,parts):
47
51
    import urllib
 
52
    import os
48
53
    # is just a list of urls, one per line
49
54
    # also support '#include <url here>'
 
55
    includeonce = False
50
56
    for line in str.splitlines():
51
57
        if line == "#include": continue
52
 
        if line.startswith("#include"):
 
58
        if line == "#include-once":
 
59
            includeonce = True
 
60
            continue
 
61
        if line.startswith("#include-once"):
 
62
            line = line[len("#include-once"):].lstrip()
 
63
            includeonce = True
 
64
        elif line.startswith("#include"):
53
65
            line = line[len("#include"):].lstrip()
54
66
        if line.startswith("#"): continue
55
 
        content = urllib.urlopen(line).read()
 
67
 
 
68
        # urls cannot not have leading or trailing white space
 
69
        msum = md5.new()
 
70
        msum.update(line.strip())
 
71
        includeonce_filename = "%s/urlcache/%s" % (
 
72
            cloudinit.get_ipath_cur("data"), msum.hexdigest())
 
73
        try:
 
74
            if includeonce and os.path.isfile(includeonce_filename):
 
75
                with open(includeonce_filename, "r") as fp:
 
76
                    content = fp.read()
 
77
            else:
 
78
                content = urllib.urlopen(line).read()
 
79
                if includeonce:
 
80
                    util.write_file(includeonce_filename, content, mode=0600)
 
81
        except Exception as e:
 
82
            raise
 
83
 
56
84
        process_includes(email.message_from_string(decomp_str(content)),parts)
57
85
 
 
86
 
58
87
def explode_cc_archive(archive,parts):
59
88
    for ent in yaml.load(archive):
60
89
        # ent can be one of:
74
103
            if mtype == None:
75
104
                mtype = type_from_startswith(payload,def_type)
76
105
 
77
 
        print "adding %s,%s" % (filename, mtype)
78
106
        parts['content'].append(content)
79
107
        parts['names'].append(filename)
80
108
        parts['types'].append(mtype)
114
142
            do_include(payload,parts)
115
143
            continue
116
144
 
 
145
        if ctype == 'text/x-include-once-url':
 
146
            do_include(payload,parts)
 
147
            continue
 
148
 
117
149
        if ctype == "text/cloud-config-archive":
118
150
            explode_cc_archive(payload,parts)
119
151
            continue
158
190
    process_includes(email.message_from_string(decomp_str(data)),parts)
159
191
    return(parts2mime(parts))
160
192
 
161
 
# callbacks is a dictionary with:
162
 
#  { 'content-type': handler(data,content_type,filename,payload) }
163
 
def walk_userdata(str, callbacks, data = None):
 
193
# callback is a function that will be called with (data, content_type, filename, payload)
 
194
def walk_userdata(istr, callback, data = None):
164
195
    partnum = 0
165
 
    for part in email.message_from_string(str).walk():
 
196
    for part in email.message_from_string(istr).walk():
166
197
        # multipart/* are just containers
167
198
        if part.get_content_maintype() == 'multipart':
168
199
            continue
175
206
        if not filename:
176
207
            filename = 'part-%03d' % partnum
177
208
 
178
 
        if callbacks.has_key(ctype):
179
 
            callbacks[ctype](data,ctype,filename,part.get_payload())
 
209
        callback(data, ctype, filename, part.get_payload())
180
210
 
181
211
        partnum = partnum+1
182
212