def get_provision_flow():
    """
    Provisioning flow consisting of three graph flows, each consisting of set of
    tasks that can execute in parallel.

    Returns tuple consisting of the whole flow and a dictionary including
    references to three graph flows for pre-execution customisations.
    """
    pre_flow = gf.Flow('PreBootInstance').add(
        AddUserPublicKey('add_user_public_key'),
        GetImage('get_image', provides='image'),
        GetFlavor('get_flavor', provides='flavor'),
        CreateRootVolume('create_root_volume', provides='root_volume_id')
    )
    main_flow = gf.Flow('BootInstance').add(
        CreateSecurityGroup('create_security_group', provides='security_group'),
        CreateDataVolume('create_data_volume', provides='data_volume_id'),
        ProvisionInstance('provision_instance', provides='server_id')
    )
    post_flow = gf.Flow('PostBootInstance').add(
        AllocateIPForInstance('allocate_ip_for_instance', provides='address_data'),
        AttachDataVolume('attach_data_volume'),
        RemoveUserPublicKey('remove_user_public_key')
    )
    return (lf.Flow('ProvisionInstance').add(pre_flow, main_flow, post_flow),
            {'pre': pre_flow, 'main': main_flow, 'post': post_flow})