Пример #1
0
    def _copy_asset(self, asset):
        """
        Copy app assets.

        Args:
            self: class instance
            asset: what to copy

        Returns:
            On success: True.
            On failure: False.

        """
        if not self._copy_prefix:
            Log.a().warning(
                'copy prefix must be specified when copying app assets'
            )
            return False

        if not asset.get('dst'):
            Log.a().warning('asset dst required for app %s', self._app['name'])
            return False

        if not asset.get('src'):
            Log.a().warning('asset src required for app %s', self._app['name'])
            return False

        # create asset destination
        asset_path = Path(self._path / asset['dst'])
        asset_path.mkdir(exist_ok=True)

        if 'zip' in asset:
            # create a tar.gz of src
            cmd = 'tar -czf "{}" --directory="{}" .'.format(
                str(Path(asset_path / '{}.tar.gz'.format(asset['zip']))),
                str(Path(self._copy_prefix) / asset['src'])
            )
            Log.some().info('zipping: %s', cmd)
            cmd_result = ShellWrapper.invoke(cmd)
            if cmd_result is False:
                Log.a().warning('cannot zip asset src: %s', cmd)
                return False

            Log.some().info('tar stdout: %s', cmd_result)

        else:
            # move without creating tar.gz
            cmd = 'cp -R "{}" "{}"'.format(
                str(Path(self._copy_prefix) / asset['src']),
                str(asset_path)
            )
            Log.some().info('copying: %s', cmd)
            cmd_result = ShellWrapper.invoke(cmd)
            if cmd_result is False:
                Log.a().warning('cannot copy asset src: %s', cmd)
                return False

            Log.some().info('copy stdout: %s', cmd_result)

        return True
Пример #2
0
    def check_running_jobs(self):
        """
        Check the status/progress of all map-reduce items and update _map status.

        Args:
            self: class instance.

        Returns:
            True.

        """
        # check if procs are running, finished, or failed
        for map_item in self._map:
            try:
                if ShellWrapper.is_running(
                        map_item['run'][map_item['attempt']]['proc']
                ):
                    map_item['status'] = 'RUNNING'
                else:
                    if map_item['run'][map_item['attempt']]['proc'].returncode:
                        map_item['status'] = 'FAILED'
                    else:
                        map_item['status'] = 'FINISHED'
                map_item['run'][map_item['attempt']]['status']\
                    = map_item['status']
            except (OSError, AttributeError) as err:
                Log.a().warning(
                    'process polling failed for map item "%s" [%s]',
                    map_item['filename'], str(err)
                )
                map_item['status'] = 'FAILED'

        self._update_status_db(self._status, '')

        return True
Пример #3
0
    def check_running_jobs(self):
        """
        Check the status/progress of all map-reduce items and update _map status.

        Args:
            self: class instance.

        Returns:
            True.

        """
        # check if procs are running, finished, or failed
        for map_item in self._map:
            if map_item['status'] in ['RUNNING', 'UNKNOWN']:
                try:
                    if not ShellWrapper.is_running(
                            map_item['run'][map_item['attempt']]['proc']):
                        returncode = map_item['run'][
                            map_item['attempt']]['proc'].returncode
                        if returncode:
                            map_item['status'] = 'FAILED'
                        else:
                            map_item['status'] = 'FINISHED'

                        Log.a().debug('[step.%s]: exit status: %s -> %s',
                                      self._step['name'],
                                      map_item['template']['output'],
                                      returncode)

                        # decrease num running procs
                        if self._num_running > 0:
                            self._num_running -= 1

                except (OSError, AttributeError) as err:
                    Log.a().warning(
                        'process polling failed for map item "%s" [%s]',
                        map_item['filename'], str(err))
                    map_item['status'] = 'UNKNOWN'

                map_item['run'][map_item['attempt']]['status']\
                    = map_item['status']

        self._update_status_db(self._status, '')

        return True
Пример #4
0
def step_impl(context, shell):

    context.shell[shell] = {}
    context.shell[shell]['shell'] = ShellWrapper()
Пример #5
0
    def _run_map(self, map_item):
        """
        Run a job for each map item and store the proc and PID.

        Args:
            self: class instance.
            map_item: map item object (item of self._map).

        Returns:
            On success: True.
            On failure: False.

        """
        # load default app inputs, overwrite with template inputs
        inputs = {}
        for input_key in self._app['inputs']:
            if input_key in map_item['template']:
                inputs[input_key] = map_item['template'][input_key]
            else:
                if self._app['inputs'][input_key]['default']:
                    inputs[input_key] = self._app['inputs'][input_key]['default']

        # load default app parameters, overwrite with template parameters
        parameters = {}
        for param_key in self._app['parameters']:
            if param_key in map_item['template']:
                parameters[param_key] = map_item['template'][param_key]
            else:
                if self._app['parameters'][param_key]['default'] not in [None, '']:
                    parameters[param_key] \
                        = self._app['parameters'][param_key]['default']

        # construct shell command
        cmd = self._app['implementation']['local']['script']
        for input_key in inputs:
            if inputs[input_key]:
                cmd += ' --{}="{}"'.format(
                    input_key,
                    URIParser.parse(inputs[input_key])['chopped_path']
                )
        for param_key in parameters:
            if param_key == 'output':
                cmd += ' --output="{}/{}"'.format(
                    self._parsed_data_uris[self._source_context]\
                        ['chopped_path'],
                    parameters['output']
                )

            else:
                cmd += ' --{}="{}"'.format(
                    param_key, parameters[param_key]
                )

        # add exeuction method
        cmd += ' --exec_method="{}"'.format(self._step['execution']['method'])

        # specify execution init commands if 'init' param given
        if 'init' in self._step['execution']['parameters']:
            cmd += ' --exec_init="{}"'.format(self._step['execution']['parameters']['init'])

        # add stdout and stderr
        log_path = '{}/_log/gf-{}-{}-{}'.format(
            self._parsed_data_uris[self._source_context]['chopped_path'],
            map_item['attempt'],
            slugify(self._step['name'], regex_pattern=r'[^-a-z0-9_]+'),
            slugify(map_item['template']['output'], regex_pattern=r'[^-a-z0-9_]+')
        )
        cmd += ' > "{}.out" 2> "{}.err"'.format(log_path, log_path)

        Log.a().debug('command: %s', cmd)

        # launch process
        proc = ShellWrapper.spawn(cmd)
        if proc is False:
            msg = 'shell process error: {}'.format(cmd)
            Log.an().error(msg)
            return self._fatal(msg)

        # record job info
        map_item['run'][map_item['attempt']]['proc'] = proc
        map_item['run'][map_item['attempt']]['pid'] = proc.pid

        # set status of process
        map_item['status'] = 'RUNNING'
        map_item['run'][map_item['attempt']]['status'] = 'RUNNING'

        return True
Пример #6
0
    def _build_asset(self, asset):
        """
        Build app assets.

        Args:
            self: class instance
            asset: what to build

        Returns:
            On success: True.
            On failure: False.

        """
        # make sure the build path exists
        build_path = self._path / 'build'
        build_path.mkdir(exist_ok=True)

        build_repo_path = None
        if not asset.get('folder'):
            Log.a().warning(
                'repo folder must be set when specifying a build asset'
            )
            return False

        # clone build repo
        build_repo_path = build_path / asset['folder']

        if asset.get('repo'):
            # if repo is set, clone and build it
            try:
                if asset.get('tag'):
                    Repo.clone_from(
                        asset['repo'], str(build_repo_path),
                        branch=asset['tag'], config='http.sslVerify=false'
                    )
                else:
                    Repo.clone_from(
                        asset['repo'], str(build_repo_path),
                        config='http.sslVerify=false'
                    )
            except GitError as err:
                Log.an().error(
                    'cannot clone git repo for build: %s [%s]',
                    asset['repo'], str(err)
                )
                return False

        # if repo is not set, packaged build scripts are included with the
        # workflow in the build_repo_path

        # build
        cmd = 'make -C "{}"'.format(str(build_repo_path))
        Log.some().info('build command: %s', cmd)
        cmd_result = ShellWrapper.invoke(cmd)
        if cmd_result is False:
            Log.a().warning('cannot build app: %s', cmd)
            return False

        Log.some().info('make stdout: %s', cmd_result)

        # move built assets
        # make sure asset folder exists
        if not asset.get('dst'):
            Log.a().warning('asset dst required for app %s', self._app['name'])
            return False

        if not asset.get('src'):
            Log.a().warning('asset src required for app %s', self._app['name'])
            return False

        # create asset destination
        asset_path = self._path / asset['dst']
        asset_path.mkdir(exist_ok=True)

        # set src path
        src_path = self._path / asset['src']

        if 'zip' in asset:
            # create a tar.gz of src
            cmd = 'tar -czf "{}" --directory="{}" .'.format(
                str(asset_path / '{}.tar.gz'.format(asset['zip'])),
                str(src_path)
            )
            Log.some().info('zipping: %s', cmd)
            cmd_result = ShellWrapper.invoke(cmd)
            if cmd_result is False:
                Log.a().warning('cannot zip asset src: %s', cmd)
                return False

            Log.some().info('tar stdout: %s', cmd_result)

        else:
            # move without creating tar.gz
            cmd = 'mv "{}" "{}"'.format(str(src_path), str(asset_path))
            Log.some().info('moving: %s', cmd)
            cmd_result = ShellWrapper.invoke(cmd)
            if cmd_result is False:
                Log.a().warning('cannot move asset src: %s', cmd)
                return False

            Log.some().info('mv stdout: %s', cmd_result)

        return True