aboutsummaryrefslogtreecommitdiffstats
path: root/docs/source/devel/storage.rst
blob: ce89db09f01bcf916e7c4ec7fc1618670e189a94 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
=========
 Storage
=========

The storage systems attached to your app
----------------------------------------

Dynamic content: queue_store and public_store
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Two instances of the StorageInterface come attached to your app. These 
are: 

+ **queue_store:** When a user submits a fresh piece of media for their gallery, before the Processing stage, that piece of media sits here in the queue_store. (It's possible that we'll rename this to "private_store" and start storing more non-publicly-stored stuff in the future...). This is a StorageInterface implementation instance. Visitors to your site probably cannot see it... it isn't designed to be seen, anyway. 

+ **public_store:** After your media goes through processing it gets moved to the public store. This is also a StorageInterface implelementation, and is for stuff that's intended to be seen by site visitors. 

The workbench
~~~~~~~~~~~~~

In addition, there's a "workbench" used during
processing...  it's just for temporary files during
processing, and also for making local copies of stuff that
might be on remote storage interfaces while transitionally
moving/converting from the queue_store to the public store. 
See the workbench module documentation for more.

.. automodule:: mediagoblin.tools.workbench
   :members:
   :show-inheritance:


Static assets / staticdirect
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

On top of all that, there is some static media that comes bundled with your
application. This stuff is kept in: 

   mediagoblin/static/

These files are for mediagoblin base assets. Things like the CSS files, 
logos, etc. You can mount these at whatever location is appropriate to you
(see the direct_remote_path option in the config file) so if your users 
are keeping their static assets at http://static.mgoblin.example.org/ but 
their actual site is at http://mgoblin.example.org/, you need to be able 
to get your static files in a where-it's-mounted agnostic way. There's a 
"staticdirector" attached to the request object. It's pretty easy to use;
just look at this bit taken from the 
mediagoblin/templates/mediagoblin/base.html main template:

    <link rel="stylesheet" type="text/css" 
        href="Template:Request.staticdirect('/css/extlib/text.css')"/>

see? Not too hard. As expected, if you configured direct_remote_path to be 
http://static.mgoblin.example.org/ you'll get back 
http://static.mgoblin.example.org/css/extlib/text.css just as you'd 
probably expect. 

StorageInterface and implementations
------------------------------------

The guts of StorageInterface and friends 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

So, the StorageInterface!

So, the public and queue stores both use StorageInterface implementations
... but what does that mean? It's not too hard.

Open up: 

    mediagoblin/storage.py

In here you'll see a couple of things. First of all, there's the 
StorageInterface class. What you'll see is that this is just a very simple
python class. A few of the methods actually implement things, but for the
most part, they don't. What really matters about this class is the 
docstrings. Each expected method is documented as to how it should be 
constructed. Want to make a new StorageInterface? Simply subclass it. Want 
to know how to use the methods of your storage system? Read these docs, 
they span all implementations.

There are a couple of implementations of these classes bundled in 
storage.py as well. The most simple of these is BasicFileStorage, which is 
also the default storage system used. As expected, this stores files 
locally on your machine.

There's also a CloudFileStorage system. This provides a mapping to 
[OpenStack's swift http://swift.openstack.org/] storage system (used by 
RackSpace Cloud files and etc).

Between these two examples you should be able to get a pretty good idea of
how to write your own storage systems, for storing data across your 
beowulf cluster of radioactive monkey brains, whatever. 

Writing code to store stuff
~~~~~~~~~~~~~~~~~~~~~~~~~~~

So what does coding for StorageInterface implementations actually look 
like? It's pretty simple, really. For one thing, the design is fairly 
inspired by [Django's file storage API 
https://docs.djangoproject.com/en/dev/ref/files/storage/]... with some 
differences.

Basically, you access files on "file paths", which aren't exactly like 
unix file paths, but are close. If you wanted to store a file on a path 
like dir1/dir2/filename.jpg you'd actually write that file path like:

['dir1', 'dir2', 'filename.jpg']

This way we can be *sure* that each component is actually a component of
the path that's expected... we do some filename cleaning on each component.

Your StorageInterface should pass in and out "file like objects". In other 
words, they should provide .read() and .write() at minimum, and probably 
also .seek() and .close().