Revision 5e7485da
b/docs/source/backends.rst | ||
---|---|---|
33 | 33 |
:members: |
34 | 34 |
:undoc-members: |
35 | 35 |
|
36 |
Policy |
|
37 |
~~~~~~ |
|
38 |
|
|
39 |
.. automodule:: pithos.backends.lib.sqlite.policy |
|
40 |
:show-inheritance: |
|
41 |
:members: |
|
42 |
:undoc-members: |
|
43 |
|
|
44 | 36 |
Permissions |
45 | 37 |
~~~~~~~~~~~ |
46 | 38 |
|
b/pithos/backends/lib/sqlalchemy/__init__.py | ||
---|---|---|
1 |
# Copyright 2011 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or |
|
4 |
# without modification, are permitted provided that the following |
|
5 |
# conditions are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above |
|
8 |
# copyright notice, this list of conditions and the following |
|
9 |
# disclaimer. |
|
10 |
# |
|
11 |
# 2. Redistributions in binary form must reproduce the above |
|
12 |
# copyright notice, this list of conditions and the following |
|
13 |
# disclaimer in the documentation and/or other materials |
|
14 |
# provided with the distribution. |
|
15 |
# |
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 |
# POSSIBILITY OF SUCH DAMAGE. |
|
28 |
# |
|
29 |
# The views and conclusions contained in the software and |
|
30 |
# documentation are those of the authors and should not be |
|
31 |
# interpreted as representing official policies, either expressed |
|
32 |
# or implied, of GRNET S.A. |
|
33 |
|
|
1 | 34 |
from dbwrapper import DBWrapper |
2 | 35 |
from node import Node |
3 | 36 |
from permissions import Permissions |
4 |
from policy import Policy |
|
5 | 37 |
|
6 |
__all__ = ["DBWrapper", "Node", "Permissions", "Policy"]
|
|
38 |
__all__ = ["DBWrapper", "Node", "Permissions"] |
|
7 | 39 |
|
b/pithos/backends/lib/sqlalchemy/node.py | ||
---|---|---|
119 | 119 |
# place an index on path |
120 | 120 |
Index('idx_nodes_path', self.nodes.c.path) |
121 | 121 |
|
122 |
#create policy table |
|
123 |
columns=[] |
|
124 |
columns.append(Column('node', Integer, |
|
125 |
ForeignKey('nodes.node', |
|
126 |
ondelete='CASCADE', |
|
127 |
onupdate='CASCADE'), |
|
128 |
primary_key=True)) |
|
129 |
columns.append(Column('key', String(255), primary_key=True)) |
|
130 |
columns.append(Column('value', String(255))) |
|
131 |
self.policies = Table('policy', metadata, *columns, mysql_engine='InnoDB') |
|
132 |
|
|
122 | 133 |
#create statistics table |
123 | 134 |
columns=[] |
124 | 135 |
columns.append(Column('node', Integer, |
... | ... | |
366 | 377 |
self.conn.execute(s).close() |
367 | 378 |
return True |
368 | 379 |
|
380 |
def policy_get(self, node): |
|
381 |
s = select([self.policies.c.key, self.policies.c.value], |
|
382 |
self.policies.c.node==node) |
|
383 |
r = self.conn.execute(s) |
|
384 |
d = dict(r.fetchall()) |
|
385 |
r.close() |
|
386 |
return d |
|
387 |
|
|
388 |
def policy_set(self, node, policy): |
|
389 |
#insert or replace |
|
390 |
for k, v in policy.iteritems(): |
|
391 |
s = self.policies.update().where(and_(self.policies.c.node == node, |
|
392 |
self.policies.c.key == k)) |
|
393 |
s = s.values(value = v) |
|
394 |
rp = self.conn.execute(s) |
|
395 |
rp.close() |
|
396 |
if rp.rowcount == 0: |
|
397 |
s = self.policies.insert() |
|
398 |
values = {'node':node, 'key':k, 'value':v} |
|
399 |
r = self.conn.execute(s, values) |
|
400 |
r.close() |
|
401 |
|
|
369 | 402 |
def statistics_get(self, node, cluster=0): |
370 | 403 |
"""Return population, total size and last mtime |
371 | 404 |
for all versions under node that belong to the cluster. |
/dev/null | ||
---|---|---|
1 |
# Copyright 2011 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or |
|
4 |
# without modification, are permitted provided that the following |
|
5 |
# conditions are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above |
|
8 |
# copyright notice, this list of conditions and the following |
|
9 |
# disclaimer. |
|
10 |
# |
|
11 |
# 2. Redistributions in binary form must reproduce the above |
|
12 |
# copyright notice, this list of conditions and the following |
|
13 |
# disclaimer in the documentation and/or other materials |
|
14 |
# provided with the distribution. |
|
15 |
# |
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 |
# POSSIBILITY OF SUCH DAMAGE. |
|
28 |
# |
|
29 |
# The views and conclusions contained in the software and |
|
30 |
# documentation are those of the authors and should not be |
|
31 |
# interpreted as representing official policies, either expressed |
|
32 |
# or implied, of GRNET S.A. |
|
33 |
|
|
34 |
from sqlalchemy import Table, Column, String, MetaData |
|
35 |
from sqlalchemy.sql import select |
|
36 |
from sqlalchemy.sql import and_ |
|
37 |
from dbworker import DBWorker |
|
38 |
|
|
39 |
|
|
40 |
class Policy(DBWorker): |
|
41 |
"""Paths can be assigned key, value pairs, representing policy.""" |
|
42 |
|
|
43 |
def __init__(self, **params): |
|
44 |
DBWorker.__init__(self, **params) |
|
45 |
metadata = MetaData() |
|
46 |
columns=[] |
|
47 |
columns.append(Column('path', String(2048), index=True)) |
|
48 |
columns.append(Column('key', String(255))) |
|
49 |
columns.append(Column('value', String(255))) |
|
50 |
self.policies = Table('policy', metadata, *columns, mysql_engine='InnoDB') |
|
51 |
metadata.create_all(self.engine) |
|
52 |
|
|
53 |
def policy_set(self, path, policy): |
|
54 |
#insert or replace |
|
55 |
for k, v in policy.iteritems(): |
|
56 |
s = self.policies.update().where(and_(self.policies.c.path == path, |
|
57 |
self.policies.c.key == k)) |
|
58 |
s = s.values(value = v) |
|
59 |
rp = self.conn.execute(s) |
|
60 |
rp.close() |
|
61 |
if rp.rowcount == 0: |
|
62 |
s = self.policies.insert() |
|
63 |
values = {'path':path, 'key':k, 'value':v} |
|
64 |
r = self.conn.execute(s, values) |
|
65 |
r.close() |
|
66 |
|
|
67 |
def policy_unset(self, path): |
|
68 |
s = self.policies.delete().where(self.policies.c.path==path) |
|
69 |
r = self.conn.execute(s) |
|
70 |
r.close() |
|
71 |
|
|
72 |
def policy_get(self, path): |
|
73 |
s = select([self.policies.c.key, self.policies.c.value], |
|
74 |
self.policies.c.path==self.policies.c.path==path) |
|
75 |
r = self.conn.execute(s) |
|
76 |
d = dict(r.fetchall()) |
|
77 |
r.close() |
|
78 |
return d |
b/pithos/backends/lib/sqlite/__init__.py | ||
---|---|---|
34 | 34 |
from dbwrapper import DBWrapper |
35 | 35 |
from node import Node |
36 | 36 |
from permissions import Permissions |
37 |
from policy import Policy |
|
38 | 37 |
|
39 |
__all__ = ["DBWrapper", "Node", "Permissions", "Policy"]
|
|
38 |
__all__ = ["DBWrapper", "Node", "Permissions"] |
|
40 | 39 |
|
b/pithos/backends/lib/sqlite/node.py | ||
---|---|---|
111 | 111 |
foreign key (parent) |
112 | 112 |
references nodes(node) |
113 | 113 |
on update cascade |
114 |
on delete cascade )""") |
|
114 |
on delete cascade ) """)
|
|
115 | 115 |
execute(""" create unique index if not exists idx_nodes_path |
116 | 116 |
on nodes(path) """) |
117 | 117 |
|
118 |
execute(""" create table if not exists policy |
|
119 |
( node integer, |
|
120 |
key text, |
|
121 |
value text, |
|
122 |
primary key (node, key) |
|
123 |
foreign key (node) |
|
124 |
references nodes(node) |
|
125 |
on update cascade |
|
126 |
on delete cascade ) """) |
|
127 |
|
|
118 | 128 |
execute(""" create table if not exists statistics |
119 | 129 |
( node integer, |
120 | 130 |
population integer not null default 0, |
... | ... | |
125 | 135 |
foreign key (node) |
126 | 136 |
references nodes(node) |
127 | 137 |
on update cascade |
128 |
on delete cascade )""") |
|
138 |
on delete cascade ) """)
|
|
129 | 139 |
|
130 | 140 |
execute(""" create table if not exists versions |
131 | 141 |
( serial integer primary key, |
... | ... | |
323 | 333 |
self.execute(q, (node,)) |
324 | 334 |
return True |
325 | 335 |
|
336 |
def policy_get(self, node): |
|
337 |
q = "select key, value from policy where node = ?" |
|
338 |
self.execute(q, (node,)) |
|
339 |
return dict(self.fetchall()) |
|
340 |
|
|
341 |
def policy_set(self, node, policy): |
|
342 |
q = "insert or replace into policy (node, key, value) values (?, ?, ?)" |
|
343 |
self.executemany(q, ((node, k, v) for k, v in policy.iteritems())) |
|
344 |
|
|
326 | 345 |
def statistics_get(self, node, cluster=0): |
327 | 346 |
"""Return population, total size and last mtime |
328 | 347 |
for all versions under node that belong to the cluster. |
/dev/null | ||
---|---|---|
1 |
# Copyright 2011 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or |
|
4 |
# without modification, are permitted provided that the following |
|
5 |
# conditions are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above |
|
8 |
# copyright notice, this list of conditions and the following |
|
9 |
# disclaimer. |
|
10 |
# |
|
11 |
# 2. Redistributions in binary form must reproduce the above |
|
12 |
# copyright notice, this list of conditions and the following |
|
13 |
# disclaimer in the documentation and/or other materials |
|
14 |
# provided with the distribution. |
|
15 |
# |
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 |
# POSSIBILITY OF SUCH DAMAGE. |
|
28 |
# |
|
29 |
# The views and conclusions contained in the software and |
|
30 |
# documentation are those of the authors and should not be |
|
31 |
# interpreted as representing official policies, either expressed |
|
32 |
# or implied, of GRNET S.A. |
|
33 |
|
|
34 |
from dbworker import DBWorker |
|
35 |
|
|
36 |
|
|
37 |
class Policy(DBWorker): |
|
38 |
"""Paths can be assigned key, value pairs, representing policy.""" |
|
39 |
|
|
40 |
def __init__(self, **params): |
|
41 |
DBWorker.__init__(self, **params) |
|
42 |
execute = self.execute |
|
43 |
|
|
44 |
execute(""" create table if not exists policy |
|
45 |
( path text, |
|
46 |
key text, |
|
47 |
value text, |
|
48 |
primary key (path, key) ) """) |
|
49 |
|
|
50 |
def policy_set(self, path, policy): |
|
51 |
q = "insert or replace into policy (path, key, value) values (?, ?, ?)" |
|
52 |
self.executemany(q, ((path, k, v) for k, v in policy.iteritems())) |
|
53 |
|
|
54 |
def policy_unset(self, path): |
|
55 |
q = "delete from policy where path = ?" |
|
56 |
self.execute(q, (path,)) |
|
57 |
|
|
58 |
def policy_get(self, path): |
|
59 |
q = "select key, value from policy where path = ?" |
|
60 |
self.execute(q, (path,)) |
|
61 |
return dict(self.fetchall()) |
b/pithos/backends/modular.py | ||
---|---|---|
132 | 132 |
self.permissions = self.mod.permissions.Permissions(**params) |
133 | 133 |
for x in ['READ', 'WRITE']: |
134 | 134 |
setattr(self, x, getattr(self.mod.permissions, x)) |
135 |
self.policy = self.mod.policy.Policy(**params) |
|
136 | 135 |
self.node = self.mod.node.Node(**params) |
137 | 136 |
for x in ['ROOTNODE', 'SERIAL', 'HASH', 'SIZE', 'MTIME', 'MUSER', 'CLUSTER']: |
138 | 137 |
setattr(self, x, getattr(self.mod.node, x)) |
... | ... | |
313 | 312 |
if container not in self._allowed_containers(user, account): |
314 | 313 |
raise NotAllowedError |
315 | 314 |
return {} |
316 |
path = self._lookup_container(account, container)[0]
|
|
317 |
return self.policy.policy_get(path)
|
|
315 |
path, node = self._lookup_container(account, container)
|
|
316 |
return self.node.policy_get(node)
|
|
318 | 317 |
|
319 | 318 |
@backend_method |
320 | 319 |
def update_container_policy(self, user, account, container, policy, replace=False): |
... | ... | |
323 | 322 |
logger.debug("update_container_policy: %s %s %s %s", account, container, policy, replace) |
324 | 323 |
if user != account: |
325 | 324 |
raise NotAllowedError |
326 |
path = self._lookup_container(account, container)[0]
|
|
325 |
path, node = self._lookup_container(account, container)
|
|
327 | 326 |
self._check_policy(policy) |
328 | 327 |
if replace: |
329 | 328 |
for k, v in self.default_policy.iteritems(): |
330 | 329 |
if k not in policy: |
331 | 330 |
policy[k] = v |
332 |
self.policy.policy_set(path, policy)
|
|
331 |
self.node.policy_set(node, policy)
|
|
333 | 332 |
|
334 | 333 |
@backend_method |
335 | 334 |
def put_container(self, user, account, container, policy=None): |
... | ... | |
347 | 346 |
if policy: |
348 | 347 |
self._check_policy(policy) |
349 | 348 |
path = '/'.join((account, container)) |
350 |
self._put_path(user, self._lookup_account(account, True)[1], path) |
|
349 |
node = self._put_path(user, self._lookup_account(account, True)[1], path)
|
|
351 | 350 |
for k, v in self.default_policy.iteritems(): |
352 | 351 |
if k not in policy: |
353 | 352 |
policy[k] = v |
354 |
self.policy.policy_set(path, policy)
|
|
353 |
self.node.policy_set(node, policy)
|
|
355 | 354 |
|
356 | 355 |
@backend_method |
357 | 356 |
def delete_container(self, user, account, container, until=None): |
... | ... | |
372 | 371 |
self.node.node_purge_children(node, inf, CLUSTER_HISTORY) |
373 | 372 |
self.node.node_purge_children(node, inf, CLUSTER_DELETED) |
374 | 373 |
self.node.node_remove(node) |
375 |
self.policy.policy_unset(path) |
|
376 | 374 |
|
377 | 375 |
@backend_method |
378 | 376 |
def list_objects(self, user, account, container, prefix='', delimiter=None, marker=None, limit=10000, virtual=True, keys=[], shared=False, until=None): |
Also available in: Unified diff