diff options
Diffstat (limited to 'morphlib/buildworker.py')
-rw-r--r-- | morphlib/buildworker.py | 277 |
1 files changed, 0 insertions, 277 deletions
diff --git a/morphlib/buildworker.py b/morphlib/buildworker.py deleted file mode 100644 index d839b09a..00000000 --- a/morphlib/buildworker.py +++ /dev/null @@ -1,277 +0,0 @@ -# Copyright (C) 2012 Codethink Limited -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - -import datetime -from multiprocessing import Manager, Process - -import morphlib - - -class BuildWorker(object): - - def __init__(self, name, ident, app): - self.name = name - self.ident = ident - self.settings = app.settings - self.real_msg = app.msg - self.indent = 2 - self.idle_since = datetime.datetime.now() - self.manager = Manager() - self.reset() - - def indent_more(self): # pragma: no cover - self.indent += 1 - - def indent_less(self): # pragma: no cover - self.indent -= 1 - - def msg(self, text): # pragma: no cover - spaces = ' ' * self.indent - self.real_msg('%s%s' % (spaces, text)) - - def reset(self): - self.process = None - self.blob = None - self._output = self.manager.list() - self._error = self.manager.dict() - - def build(self, blob): - raise NotImplementedError - - def check_complete(self, timeout): # pragma: no cover - if self.process: - self.process.join(timeout) - if self.process.is_alive(): - return False - else: - self.idle_since = datetime.datetime.now() - return True - else: - return True - - @property - def output(self): - try: - return self._output[0] - except IndexError: - return None - - @property - def error(self): - return self._error - - def options(self): # pragma: no cover - '''Returns an array of command line options for the settings. - - NOTE: This is just a hack that uses internals of the cliapp.Settings - class. We need to merge this kind of functionality into cliapp and - remove this hack! - - ''' - - # use the canonical names of the settings to generate cmdline options - names = list(self.settings._canonical_names) - - # internal function to combine an option name and a value into string - def combine(name, value): - if name.startswith('--'): - if isinstance(value, bool): - if value: - return '%s' % name - else: - return '%s=%s' % (name, value) - else: - if isinstance(value, bool): - if value: - return '%s' % name - else: - return '%s %s' % (name, value) - - # generate a list of (setting name, option name) pairs - options_list = [] - options = self.settings._option_names(names) - name_pairs = [(names[i], options[i]) for i in xrange(0, len(names))] - - # convert all settings into command line arguments; drop absent - # settings and make sure to convert all values correctly - for name, option in name_pairs: - value = self.settings[name] - if not value: - continue - if isinstance(value, list): - for listval in value: - if isinstance(listval, str): - if len(listval) > 0: - string = combine(option, listval) - if string: - options_list.append(string) - else: - string = combine(option, listval) - if string: - options_list.append(string) - else: - if isinstance(value, str): - if len(value) > 0: - string = combine(option, value) - if string: - options_list.append(string) - else: - string = combine(option, value) - if string: - options_list.append(string) - return options_list - - def __str__(self): - return self.name - - -class LocalBuildWorker(BuildWorker): - - def __init__(self, name, ident, app): - BuildWorker.__init__(self, name, ident, app) - - def run(self, first_tuple, second_tuple, sudo, output, - error): # pragma: no cover - ex = morphlib.execute.Execute('.', self.msg) - - # generate command line options - args = self.options() - cmdline = [] - if sudo: - cmdline.extend(['sudo']) - cmdline.extend(['morph', 'build-single']) - cmdline.extend([first_tuple['repo'], - first_tuple['ref'], - first_tuple['filename']]) - if second_tuple: - cmdline.extend([second_tuple['repo'], - second_tuple['ref'], - second_tuple['filename']]) - cmdline.extend(args) - - # run morph locally in a child process - try: - stdout = ex.runv(cmdline) - output.append(stdout) - except OSError, e: - error['error'] = str(e) - error['command'] = ' '.join(cmdline) - except morphlib.execute.CommandFailure, e: - error['error'] = str(e) - error['command'] = ' '.join(cmdline) - - def build(self, blob): # pragma: no cover - self.reset() - self.blob = blob - - first_tuple = None - if len(blob.parents) > 0: - first_tuple = { - 'repo': blob.parents[0].morph.treeish.original_repo, - 'ref': blob.parents[0].morph.treeish.ref, - 'filename': blob.parents[0].morph.filename, - } - - blob_tuple = { - 'repo': blob.morph.treeish.original_repo, - 'ref': blob.morph.treeish.ref, - 'filename': blob.morph.filename, - } - - args = (first_tuple if first_tuple else blob_tuple, - blob_tuple if first_tuple else None, - blob.morph.kind == 'system', - self._output, - self._error) - self.process = Process(group=None, target=self.run, args=args) - self.process.start() - - -class RemoteBuildWorker(BuildWorker): - - def __init__(self, name, ident, app): - BuildWorker.__init__(self, name, ident, app) - self.hostname = ident - - def run(self, first_tuple, second_tuple, sudo, output, - error): # pragma: no cover - ex = morphlib.execute.Execute('.', self.msg) - - # generate command line options - args = self.options() - cmdline = ['ssh', '-q', self.hostname] - if sudo: - cmdline.extend(['-t', '-t', '-t', 'sudo', '-S', - 'bash', '--login', '-c']) - cmdline.extend(['"']) - cmdline.extend(['morph', 'build-single', repo, ref, filename]) - cmdline.extend([first_tuple['repo'], - first_tuple['ref'], - first_tuple['filename']]) - if second_tuple: - cmdline.extend([second_tuple['repo'], - second_tuple['ref'], - second_tuple['filename']]) - cmdline.extend(args) - cmdline.extend(['"']) - else: - cmdline.extend(['fakeroot']) - cmdline.extend(['morph', 'build-single', repo, ref, filename]) - cmdline.extend([first_tuple['repo'], - first_tuple['ref'], - first_tuple['filename']]) - if second_tuple: - cmdline.extend([second_tuple['repo'], - second_tuple['ref'], - second_tuple['filename']]) - cmdline.extend(args) - - # run morph on the other machine - try: - stdout = ex.runv(cmdline) - output.append(stdout) - except OSError, e: - error['error'] = str(e) - error['command'] = ' '.join(cmdline) - except morphlib.execute.CommandFailure, e: - error['error'] = str(e) - error['command'] = ' '.join(cmdline) - - def build(self, blob): # pragma: no cover - self.reset() - self.blob = blob - - first_tuple = None - if len(blob.parents) > 0: - first_tuple = { - 'repo': blob.parents[0].morph.treeish.original_repo, - 'ref': blob.parents[0].morph.treeish.ref, - 'filename': blob.parents[0].morph.filename, - } - - blob_tuple = { - 'repo': blob.morph.treeish.original_repo, - 'ref': blob.morph.treeish.ref, - 'filename': blob.morph.filename, - } - - args = (first_tuple if first_tuple else blob_tuple, - blob_tuple if first_tuple else None, - blob.morph.kind == 'system', - self._output, - self._error) - self.process = Process(group=None, target=self.run, args=args) - self.process.start() |