## Why are these changes needed?
Prior to this PR, we have:
```cpp
class XxxAccessor {}
class ServiceBasedXxxAccessor : public XxxAccessor{}
class GcsClient {}
class ServiceBasedGcsClient : public GcsClient{}
```
However, XxxAccessor has only one implementation: ServiceBasedXxxAccessor. And GcsClient has only one implementation: ServiceBasedGcsClient.
I think this abstraction is not necessary and will make development hard(I have to modify two files every time).
This PR removes all ServiceBasedXxx and moves its implementations to the base class.
Now we only have:
```cpp
class XxxAccessor {}
class GcsClient {}
```
* wip.
* Test: Make a change in tune to trigger tune tests, which are not run otherwise, but seem to fail nevertheless with this PR's changes.
* remove bare_metal_policy_with_custom_view_reqs from tests
## Why are these changes needed?
Add the functionality to retrieve metadata for a workflow or workflow step.
Design:
- Similar to `get_output`, this will either return the metadata for workflow (`workflow.get_metadata(workflow_id)`) or the metadata for a specific step (`workflow.get_metadata(workflow_id, step_id)`)
- Exceptions will only be raised if workflow id or step id not exist. Canceled job, running job, etc. will return proper metadata by retrieving information from checkpoint. See [here](8c8ca609d7/python/ray/workflow/tests/test_metadata_get.py (L67)) for more details.
- Returned metadata is an aggregated result from multiple checkpoint files based on previous [discussion](https://github.com/ray-project/ray/issues/17090#issuecomment-920481789). The aggregation logic is [here for step metadata](8c8ca609d7/python/ray/workflow/workflow_storage.py (L451)) and [here for workflow metadata](8c8ca609d7/python/ray/workflow/workflow_storage.py (L484)) which can be tuned with further discussion.
Example:
```python
>>> user_step_metadata = {"k1": "v1"}
>>> user_run_metadata = {"k2": "v2"}
>>> step_name = "simple_step"
>>> workflow_id = "simple"
>>> @workflow.step
>>> def simple():
>>> return 0
>>> simple.options(name=step_name, metadata=user_step_metadata).step().run(workflow_id, metadata=user_run_metadata)
# get workflow-level metadata
>>> workflow.get_metadata("simple")
{'status': 'SUCCESSFUL',
'user_metadata': {'k2': 'v2'},
'stats': {'start_time': 1634173413.116535, 'end_time': 1634173413.149051}}
# get step-level metadata
>>> workflow.get_metadata("simple", "simple_step")
{'name': '__main__.simple',
'step_type': 'FUNCTION',
'workflows': [],
'max_retries': 3,
'workflow_refs': [],
'catch_exceptions': False,
'ray_options': {},
'user_metadata': {'k1': 'v1'},
'stats': {'start_time': 1634173413.131262, 'end_time': 1634173413.1347651}}
```
## Related issue number
https://github.com/ray-project/ray/issues/17090