Skip to content

Commit 3ad65f0

Browse files
author
Yutaro Iiyama
committed
refactored group and user data sources
1 parent 2ce77c3 commit 3ad65f0

10 files changed

Lines changed: 96 additions & 24 deletions

File tree

bin/registry_users.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,10 @@
4242

4343
updated_users = []
4444

45-
for user_info in sitedb._make_request('people'):
46-
name = user_info[0]
47-
email = user_info[1]
48-
dn = user_info[4]
45+
sitedb_users = {}
46+
sitedb.get_user_list(sitedb_users)
4947

48+
for name, email, dn in sitedb_users.itervalues():
5049
try:
5150
known_user = known_users.pop(name)
5251
except KeyError:

lib/common/configuration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@
121121
)
122122

123123
activitylock = Configuration(
124-
default_user = 'paus'
124+
default_user = 'dynamo@dynamo.mit.edu'
125125
)
126126

127127
tape_sites = ['T1_*_MSS', 'T0_CH_CERN_MSS']

lib/common/interface/activitylock.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import logging
33

44
from common.interface.mysql import MySQL
5+
from common.interface.classes import default_interface
56
import common.configuration as config
67

78
logger = logging.getLogger(__name__)
@@ -21,6 +22,8 @@ def __init__(self, application, service = 'dynamo', asuser = '', db_params = con
2122
else:
2223
self.user = config.activitylock.default_user
2324

25+
self._userinfo = default_interface['user_source']()
26+
2427
def __enter__(self):
2528
self.lock()
2629

@@ -51,6 +54,13 @@ def lock(self):
5154
self._mysql.query('UNLOCK TABLES')
5255
time.sleep(60)
5356

57+
if self._mysql.query('SELECT COUNT(*) FROM `users` WHERE `name` = %s', self.user)[0] == 0:
58+
user_data = self._userinfo.get_user(self.user)
59+
if user_data is None:
60+
raise RuntimeError('Invalid user %s used for activity lock' % self.user)
61+
62+
self._mysql.query('INSERT INTO `users` (`name`, `email`, `dn`) VALUES (%s, %s, %s)', *user_data)
63+
5464
query = 'INSERT INTO `activity_lock` (`user_id`, `service_id`, `application`, `timestamp`, `note`)'
5565
query += ' SELECT `users`.`id`, `services`.`id`, %s, NOW(), \'Dynamo running\' FROM `users`, `services`'
5666
query += ' WHERE `users`.`name` = %s AND `services`.`name` = %s'

lib/common/interface/classes.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,11 @@ def __call__(self):
2020
return obj
2121

2222

23-
class DummyInterface(object):
24-
def __init__(self):
25-
pass
26-
2723
default_interface = {
2824
'dataset_source': Generator('phedexdbsssb', 'PhEDExDBSSSB'),
2925
'site_source': Generator('phedexdbsssb', 'PhEDExDBSSSB'),
26+
'user_source': Generator('sitedb', 'SiteDB'),
27+
'group_source': Generator('phedexdbsssb', 'PhEDExDBSSSB'),
3028
'replica_source': Generator('phedexdbsssb', 'PhEDExDBSSSB'),
3129
'copy': Generator('phedexdbsssb', 'PhEDExDBSSSB'),
3230
'deletion': Generator('phedexdbsssb', 'PhEDExDBSSSB'),

lib/common/interface/groupinfo.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
class GroupInfoSourceInterface(object):
2+
"""
3+
Interface specs for group information authority.
4+
"""
5+
6+
def __init__(self):
7+
pass
8+
9+
def get_group_list(self, groups, filt = '*'):
10+
"""
11+
Fill the list of groups with groups that match the wildcard name.
12+
13+
@param groups {name: Group} to be filled. Information of the groups already in the list will be updated.
14+
@param filt A wildcard string or a list of wildcard strings.
15+
"""
16+
pass

lib/common/interface/phedexdbsssb.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from common.interface.copy import CopyInterface
1212
from common.interface.deletion import DeletionInterface
1313
from common.interface.siteinfo import SiteInfoSourceInterface
14+
from common.interface.groupinfo import GroupInfoSourceInterface
1415
from common.interface.replicainfo import ReplicaInfoSourceInterface
1516
from common.interface.datasetinfo import DatasetInfoSourceInterface
1617
from common.interface.webservice import RESTService, GET, POST
@@ -27,7 +28,7 @@
2728
# PhEDEx does not document a hard limit on the length of POST request list.
2829
# 10000 was experimentally verified to be OK.
2930

30-
class PhEDExDBSSSB(CopyInterface, DeletionInterface, SiteInfoSourceInterface, ReplicaInfoSourceInterface, DatasetInfoSourceInterface):
31+
class PhEDExDBSSSB(CopyInterface, DeletionInterface, SiteInfoSourceInterface, GroupInfoSourceInterface, ReplicaInfoSourceInterface, DatasetInfoSourceInterface):
3132
"""
3233
Interface to PhEDEx/DBS/SSB using datasvc REST API.
3334
"""
@@ -36,6 +37,7 @@ def __init__(self, phedex_url = config.phedex.url_base, dbs_url = config.dbs.url
3637
CopyInterface.__init__(self)
3738
DeletionInterface.__init__(self)
3839
SiteInfoSourceInterface.__init__(self)
40+
GroupInfoSourceInterface.__init__(self)
3941
ReplicaInfoSourceInterface.__init__(self)
4042
DatasetInfoSourceInterface.__init__(self)
4143

@@ -465,7 +467,7 @@ def set_site_status(self, sites): #override (SiteInfoSourceInterface)
465467
else:
466468
site.status = Site.STAT_READY
467469

468-
def get_group_list(self, groups, filt = '*'): #override (SiteInfoSourceInterface)
470+
def get_group_list(self, groups, filt = '*'): #override (GroupInfoSourceInterface)
469471
logger.info('get_group_list Fetching the list of groups from PhEDEx')
470472
source = self._make_phedex_request('groups')
471473

lib/common/interface/sitedb.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,18 @@
44
import datetime
55

66
from common.interface.siteinfo import SiteInfoSourceInterface
7+
from common.interface.userinfo import UserInfoSourceInterface
78
from common.interface.webservice import RESTService, GET, POST
89
from common.dataformat import Site
910
import common.configuration as config
1011

1112
logger = logging.getLogger(__name__)
1213

13-
class SiteDB(SiteInfoSourceInterface):
14+
class SiteDB(SiteInfoSourceInterface, UserInfoSourceInterface):
1415
def __init__(self):
1516
self._interface = RESTService(config.sitedb.url_base)
1617

17-
def get_site_list(self, sites, filt = '*'): #override
18+
def get_site_list(self, sites, filt = '*'): #override (SiteInfoSourceInterface)
1819
"""
1920
Fill the list of sites with sites that match the wildcard name.
2021
Arguments:
@@ -81,6 +82,30 @@ def get_site_list(self, sites, filt = '*'): #override
8182

8283
sites[name] = site
8384

85+
def get_user(self, name): #override (UserInfoSourceInterface)
86+
result = self._interface.make_request('people', ['match=%s' % name])
87+
88+
if len(result) == 0:
89+
return None
90+
else:
91+
user_info = result[0]
92+
name = user_info[0]
93+
email = user_info[1]
94+
dn = user_info[4]
95+
96+
return (name, email, dn)
97+
98+
def get_user_list(self, users, filt = '*'): #override (UserInfoSourceInterface)
99+
result = self._interface.make_request('people')
100+
101+
for user in users:
102+
user_info = result[0]
103+
name = user_info[0]
104+
email = user_info[1]
105+
dn = user_info[4]
106+
107+
users[name] = (name, email, dn)
108+
84109
def _make_request(self, resource, options = []):
85110
"""
86111
Make a single API call to SiteDB, strip the "header" and return the body JSON.
@@ -118,3 +143,8 @@ def _make_request(self, resource, options = []):
118143
continue
119144

120145
out.write('UPDATE `sites` SET storage = %f, cpu = %f WHERE `name` LIKE \'%s\';\n' % (site.storage, site.cpu, site.name))
146+
147+
elif args.command == 'api':
148+
result = interface._make_request(args.options[0], args.options[1:])
149+
150+
pprint.pprint(result)

lib/common/interface/siteinfo.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,6 @@ def set_site_status(self, sites):
2323
"""
2424
pass
2525

26-
def get_group_list(self, groups, filt = '*'):
27-
"""
28-
Fill the list of groups with groups that match the wildcard name.
29-
Arguments:
30-
groups: the name->group dict to be filled. Information of the groups already in the list will be updated.
31-
filt: a wildcard string or a list of wildcard strings.
32-
"""
33-
pass
34-
3526

3627
if __name__ == '__main__':
3728

lib/common/interface/userinfo.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
class UserInfoSourceInterface(object):
2+
"""
3+
Interface specs for user data authority.
4+
"""
5+
6+
def __init__(self):
7+
pass
8+
9+
def get_user(self, name):
10+
"""
11+
Return info of a single user in the expected format. Return None for invalid user name.
12+
"""
13+
pass
14+
15+
def get_user_list(self, users, filt = '*'):
16+
"""
17+
Fill the given list with users with names matching the filter.
18+
@param users {name: userdata} to be filled with user information in the expected format.
19+
@param filt Wildcard pattern.
20+
"""
21+
pass

lib/common/inventory.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class ConsistencyError(Exception):
2222
class InventoryManager(object):
2323
"""Bookkeeping class to bridge the communication between remote and local data sources."""
2424

25-
def __init__(self, load_data = True, store_cls = None, site_source_cls = None, dataset_source_cls = None, replica_source_cls = None):
25+
def __init__(self, load_data = True, store_cls = None, site_source_cls = None, group_source_cls = None, dataset_source_cls = None, replica_source_cls = None):
2626
if store_cls:
2727
self.store = store_cls()
2828
else:
@@ -33,6 +33,11 @@ def __init__(self, load_data = True, store_cls = None, site_source_cls = None, d
3333
else:
3434
self.site_source = default_interface['site_source']()
3535

36+
if group_source_cls:
37+
self.group_source = group_source_cls()
38+
else:
39+
self.group_source = default_interface['group_source']()
40+
3641
if dataset_source_cls:
3742
self.dataset_source = dataset_source_cls()
3843
else:
@@ -148,7 +153,7 @@ def update(self, dataset_filter = '*', load_first = True, make_snapshot = True,
148153

149154
self.site_source.set_site_status(self.sites)
150155

151-
self.site_source.get_group_list(self.groups, filt = config.inventory.included_groups)
156+
self.group_source.get_group_list(self.groups, filt = config.inventory.included_groups)
152157

153158
if from_delta:
154159
if last_update == 0:

0 commit comments

Comments
 (0)