def _start_workflow_stages(pb: ProcessingBlock, pb_id: str,
                           workflow_stage_dict: dict,
                           workflow_stage: WorkflowStage,
                           docker: DockerSwarmClient):
    """Start a workflow stage by starting a number of docker services.

    This function first assesses if the specified workflow stage can be
    started based on its dependencies. If this is found to be the case,
    the workflow stage is stared by first resolving and template arguments
    in the workflow stage configuration, and then using the Docker Swarm Client
    API to start workflow stage services. As part of this, the
    workflow_stage_dict data structure is updated accordingly.

    TODO(BMo) This function will need refactoring at some point as part
    of an update to the way workflow state metadata is stored in the
    configuration database. Currently the stage_data dictionary
    is a bit of a hack for a badly specified Configuration Database
    backed WorkflowStage object.

    This function is used by `execute_processing_block`.

    Args:
        pb (ProcessingBlock): Configuration database Processing Block data
            object
        pb_id (str): Processing Block identifier
        workflow_stage_dict (dict): Workflow stage metadata structure
        workflow_stage (WorkflowStage): Workflow state configuration database
            data object.
        docker (DockerClient): Docker Swarm Client object.

    """
    # FIXME(BMo) replace pb_id argument, get this from the pb instead!
    stage_data = workflow_stage_dict[workflow_stage.id]
    stage_data['start'] = False

    # Determine if the stage can be started.
    if stage_data['status'] == 'none':
        if not workflow_stage.dependencies:
            stage_data['start'] = True
        else:
            dependency_status = []
            for dependency in workflow_stage.dependencies:
                dependency_status.append(
                    workflow_stage_dict[dependency['value']][
                        'status'] == 'complete')
                # ii += 1
            stage_data['start'] = all(dependency_status)

    # Start the workflow stage.
    if stage_data['start']:
        # Configure EE (set up templates)
        LOG.info('-- Starting workflow stage: %s --', workflow_stage.id)
        LOG.info('Configuring EE templates.')
        args_template = jinja2.Template(workflow_stage.args_template)
        stage_params = pb.workflow_parameters[workflow_stage.id]
        template_params = {**workflow_stage.config, **stage_params}
        args = args_template.render(stage=template_params)
        LOG.info('Resolving workflow script arguments.')

        args = json.dumps(json.loads(args))
        compose_template = jinja2.Template(
            workflow_stage.compose_template)
        compose_str = compose_template.render(stage=dict(args=args))

        # Prefix service names with the PB id
        compose_dict = yaml.load(compose_str)
        service_names = compose_dict['services'].keys()
        new_service_names = [
            '{}_{}_{}'.format(pb_id, pb.workflow_id, name)
            for name in service_names]
        for new, old in zip(new_service_names, service_names):
            compose_dict['services'][new] = \
                compose_dict['services'].pop(old)
        compose_str = yaml.dump(compose_dict)

        # Run the compose file
        service_ids = docker.create_services(compose_str)
        LOG.info('Staring workflow containers:')
        for service_id in service_ids:
            service_name = docker.get_service_name(service_id)
            LOG.info("  %s, %s ", service_name, service_id)
            stage_data['services'][service_id] = {}
            LOG.info('Created Services: %s', service_ids)
            stage_data['services'][service_id] = dict(
                name=docker.get_service_name(service_id),
                status='running',
                complete=False
            )
        stage_data["status"] = 'running'
Start a workflow stage by starting a number of docker services.

    This function first assesses if the specified workflow stage can be
    started based on its dependencies. If this is found to be the case,
    the workflow stage is stared by first resolving and template arguments
    in the workflow stage configuration, and then using the Docker Swarm Client
    API to start workflow stage services. As part of this, the
    workflow_stage_dict data structure is updated accordingly.

    TODO(BMo) This function will need refactoring at some point as part
    of an update to the way workflow state metadata is stored in the
    configuration database. Currently the stage_data dictionary
    is a bit of a hack for a badly specified Configuration Database
    backed WorkflowStage object.

    This function is used by `execute_processing_block`.

    Args:
        pb (ProcessingBlock): Configuration database Processing Block data
            object
        pb_id (str): Processing Block identifier
        workflow_stage_dict (dict): Workflow stage metadata structure
        workflow_stage (WorkflowStage): Workflow state configuration database
            data object.
        docker (DockerClient): Docker Swarm Client object.