Advanced
=====================================
**Design**
This reference implementation is based on the `VOSpace 2.1 specification. `_
The design separates the metadata and data services into into 2 main HTTP(S) based processes:
* The VOSpace metadata service; and
* The VOSpace storage service.
The reference implementation provides a posix based VOSpace storage service out-of-the-box.
The design allows for custom VOSpace storage services to be implemented by extending a basic set of interfaces.
Please refer to the advanced section for details.
**VOSpace Services**
The VOSpace metadata service is designed to allow it to be a standalone process that implements
the core metadata features of the VOSpace specification. These include the following web operations:
* Service Metadata (Section 6.1)
* Creating and manipulating data nodes (Section 6.2)
* Accessing metadata (Section 6.3)
The transfer of data (Section 6.4) to and from a VOSpace node is the responsibility of the
VOSpace storage process(es). The following transfer actions are supported:
* pushToVoSpace; and
* pullFromVoSpace.
**Custom VOService**
The base package implements a basic posix backend. If the developer wished to implement a custom storage backend follow the recipe below.
Note: that the storage classes in this packages only supports the HTTP and HTTP(S) protocols.
Other protocols can be implemented by following the recipe found in :py:class:`pyvospace.server.storage.HTTPSpaceStorageServer`
1. Implement interface :py:class:`pyvospace.server.space.AbstractSpace`
* This implementation must be passed to :py:func:`pyvospace.server.space.SpaceServer.setup` for the VOSpace metadata service.
2. To control permissions on the space extend :py:class:`pyvospace.server.space.SpaceServer` and override :py:class:`pyvospace.server.space.SpacePermission.permits`.
Note: The authentication and authorisation mechanisms are outside the scope of the implementation but it does implement
the hooks to the `aiohttp_security `_ library which is can be leveraged.
Refer to posix example for more details.
3. Implement the storage interface :py:class:`pyvospace.server.storage.HTTPSpaceStorageServer`
Note that when implementing the upload funtionality it's important to first upload the data to a staging area
then copy or move data to its final location in a single transaction. In this way the system can ensure consistency in a concurrent environment::
async def upload(self, job: StorageUWSJob, request: aiohttp.web.Request):
# upload data to staging area first
...
# copy data to final location and update node details in db in single transaction.
# good practise to asyncio.shield save() and move() to ensure they are not aborted.
async with job.transaction() as tr:
node = tr.target # get the target node that is associated with the data
node.size = size # set the size
node.storage = self.storage # set the storage back end so it can be found
await asyncio.shield(node.save()) # save details to db
await asyncio.shield(move(stage_file_name, real_file_name)) # move file from staging to final location in the space in single transaction
4. Create configuration file for the Space.
**[Space]**
Ref by :py:class:`pyvospace.server.space.SpaceServer`
* host: host of space metadata service.
* port: port of space metadata service.
* name: name of the space (unique).
* uri: uri base for the space.
* dsn: connection string to the database.
* parameters: any customs parameters defined by the implementor of the space (json string)
* use_ssl: use https (1: yes, 0: no)
* cert_file: SSL certificate file.
* key_file = SSL key file.
**[Storage]**
Ref by :py:class:`pyvospace.server.storage.HTTPSpaceStorageServer`
* host: host of space storage.
* port: port of space storage.
* name: name of the space (unique).
* parameters: any customs parameters defined by the implementor of the space (json string)
* use_ssl: use https (1: yes, 0: no)
* cert_file: SSL certificate file.
* key_file = SSL key file.
Configuration Example::
[Space]
host = localhost
port = 8080
name = posix
uri = icrar.org
dsn = postgres://vos_user:vos_user@localhost:5435/vospace
parameters = {}
use_ssl = 0
[Storage]
name = posix
host = localhost
port = 8081
parameters = {"root_dir": "/tmp/posix/storage/", "staging_dir": "/tmp/posix/staging/"}
use_ssl = 0
5. Start each service.
VOSpace metadata service::
abstract_space = MySpecificImpl()
app = SpaceServer()
await app.setup(abstract_space)
VOSpace storage service::
app = MyHTTPSpaceStorageServer()
await app.setup()