1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import ConfigParser
21 import errno
22 import fcntl
23 import logging
24 import os.path
25 import select
26 import subprocess
27 import tempfile
28 from exception import VMBuilderException, VMBuilderUserError
29
32 self.file = fp
33 self.set_non_blocking()
34 self.buf = ''
35 self.logbuf = ''
36 self.logfunc = logfunc
37
39 flags = fcntl.fcntl(self.file, fcntl.F_GETFL)
40 flags = flags | os.O_NONBLOCK
41 fcntl.fcntl(self.file, fcntl.F_SETFL, flags)
42
44 if attr == 'closed':
45 return self.file.closed
46 else:
47 raise AttributeError()
48
61
63 """
64 Runs a command.
65
66 Locale is reset to C to make parsing error messages possible.
67
68 @type stdin: string
69 @param stdin: input to provide to the process on stdin. If None, process'
70 stdin will be attached to /dev/null
71 @type ignore_fail: boolean
72 @param ignore_fail: If True, a non-zero exit code from the command will not
73 cause an exception to be raised.
74 @type env: dict
75 @param env: Dictionary of extra environment variables to set in the new process
76
77 @rtype: string
78 @return: string containing the stdout of the process
79 """
80
81 env = kwargs.get('env', {})
82 stdin = kwargs.get('stdin', None)
83 ignore_fail = kwargs.get('ignore_fail', False)
84 args = [str(arg) for arg in argv]
85 logging.debug(args.__repr__())
86 if stdin:
87 logging.debug('stdin was set and it was a string: %s' % (stdin,))
88 stdin_arg = subprocess.PIPE
89 else:
90 stdin_arg = file('/dev/null', 'r')
91 proc_env = dict(os.environ)
92 proc_env['LANG'] = 'C'
93 proc_env['LC_ALL'] = 'C'
94 proc_env.update(env)
95
96 try:
97 proc = subprocess.Popen(args, stdin=stdin_arg, stderr=subprocess.PIPE, stdout=subprocess.PIPE, env=proc_env)
98 except OSError, error:
99 if error.errno == errno.ENOENT:
100 raise VMBuilderUserError, "Couldn't find the program '%s' on your system" % (argv[0])
101 else:
102 raise VMBuilderUserError, "Couldn't launch the program '%s': %s" % (argv[0], error)
103
104 if stdin:
105 proc.stdin.write(stdin)
106 proc.stdin.close()
107
108 mystdout = NonBlockingFile(proc.stdout, logfunc=logging.debug)
109 mystderr = NonBlockingFile(proc.stderr, logfunc=(ignore_fail and logging.debug or logging.info))
110
111 while not (mystdout.closed and mystderr.closed):
112
113 fds = select.select([x.file for x in [mystdout, mystderr] if not x.closed], [], [])[0]
114 for fp in [mystderr, mystdout]:
115 if fp.file in fds:
116 fp.process_input()
117
118 status = proc.wait()
119 if not ignore_fail and status != 0:
120 raise VMBuilderException, "Process (%s) returned %d. stdout: %s, stderr: %s" % (args.__repr__(), status, mystdout.buf, mystderr.buf)
121 return mystdout.buf
122
124 """
125 Check if we're running as root, and bail out if we're not.
126 """
127
128 if os.geteuid() != 0:
129 raise VMBuilderUserError("This script must be run as root (e.g. via sudo)")
130
132
133 from Cheetah.Template import Template
134 searchList = []
135 if context:
136 searchList.append(extra_context)
137 searchList.append(context)
138
139
140
141 tmpldirs = [dir % plugin for dir in context.template_dirs]
142
143 for dir in tmpldirs:
144 tmplfile = '%s/%s.tmpl' % (dir, tmplname)
145 if os.path.exists(tmplfile):
146 t = Template(file=tmplfile, searchList=searchList)
147 output = t.respond()
148 logging.debug('Output from template \'%s\': %s' % (tmplfile, output))
149 return output
150
151 raise VMBuilderException('Template %s.tmpl not found in any of %s' % (tmplname, ', '.join(tmpldirs)))
152
154 logging.info('Calling hook: %s' % func)
155 logging.debug('(args=%r, kwargs=%r)' % (args, kwargs))
156 for plugin in context.plugins:
157 logging.debug('Calling %s method in %s plugin.' % (func, plugin.__module__))
158 getattr(plugin, func, log_no_such_method)(*args, **kwargs)
159
160 for f in context.hooks.get(func, []):
161 logging.debug('Calling %r.' % (f,))
162 f(*args, **kwargs)
163
164 logging.debug('Calling %s method in context plugin %s.' % (func, context.__module__))
165 getattr(context, func, log_no_such_method)(*args, **kwargs)
166
168 logging.debug('No such method')
169 return
170
172 (fd, filename) = tempfile.mkstemp(suffix=suffix)
173 os.close(fd)
174 if not keep:
175 os.unlink(filename)
176 return filename
177
178 -def tmpdir(suffix='', keep=True):
179 dir = tempfile.mkdtemp(suffix=suffix)
180 if not keep:
181 os.rmdir(dir)
182 return dir
183
185 confvalue = None
186 try:
187 confvalue = confparser.get('DEFAULT', key)
188 except ConfigParser.NoSectionError:
189 pass
190 except ConfigParser.NoOptionError:
191 pass
192
193 if confparser.has_option(context.arg, key):
194 confvalue = confparser.get(context.arg, key)
195
196 logging.debug('Returning value %s for configuration key %s' % (repr(confvalue), key))
197 return confvalue
198
199 -def apply_config_files_to_context(config_files, context):
200 confparser = ConfigParser.SafeConfigParser()
201 confparser.read(config_files)
202
203 for (key, setting) in context._config.iteritems():
204 confvalue = get_conf_value(context, confparser, key)
205 if confvalue:
206 setting.set_value_fuzzy(confvalue)
207