Skip to content

Commit aaebdfa

Browse files
authored
Merge pull request #155 from efajardo/sw3362
Xrootd Third Party Transfers SOFTWARE-3362
2 parents 36715da + 6f53f10 commit aaebdfa

File tree

7 files changed

+214
-7
lines changed

7 files changed

+214
-7
lines changed

files/test_sequence

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ test_130_gridftp
1010
test_140_lcmaps
1111
test_150_xrootd
1212
test_155_stashcache
13+
test_158_xrootd_tpc
1314
test_160_rsv
1415
test_170_pbs
1516
test_180_cvmfs
@@ -34,6 +35,7 @@ test_430_uberftp
3435
test_440_glexec
3536
test_450_xrootd
3637
test_460_stashcache
38+
test_465_xrootd_tpc
3739
test_470_rsv
3840
test_490_jobs
3941
test_510_edgmkgridmap
@@ -53,6 +55,7 @@ test_800_gratia
5355
test_820_cvmfs
5456
test_830_rsv
5557
test_835_stashcache
58+
test_838_xrootd_tpc
5659
test_840_xrootd
5760
test_850_lcmaps
5861
test_860_gridftp

osgtest/library/files.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import re
2626
import shutil
2727
import tempfile
28-
28+
import hashlib
2929
import osgtest.library.core as core
3030

3131

@@ -246,3 +246,21 @@ def safe_makedirs(directory, mode=0o777):
246246
"""
247247
if not os.path.isdir(directory):
248248
os.makedirs(directory, mode)
249+
250+
def checksum_file(path):
251+
"""Return the md5 checksum of a file """
252+
if os.path.exists(path):
253+
return hashlib.md5(open(path,'rb').read()).hexdigest()
254+
else:
255+
return False
256+
257+
def checksum_files_match(file1, file2):
258+
"""Returns true if the checksum of the files matches
259+
260+
"""
261+
checksum1 = checksum_file(file1)
262+
checksum2 = checksum_file(file2)
263+
if checksum1 and checksum2:
264+
return checksum1==checksum2
265+
else:
266+
return False

osgtest/library/service.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import time
33

44
import osgtest.library.core as core
5+
from osgtest.library import files
56

67
STATUS_RUNNING = 0 # LSB: program is running or service is OK
78
STATUS_STOPPED = 3 # LSB: program is not running according to LSB init standards
@@ -35,13 +36,13 @@ def start(service_name):
3536
core.check_system(command, 'Start ' + service_name + ' service')
3637
core.state[service_name + '.started-service'] = True
3738

38-
def check_start(service_name, timeout=10):
39+
def check_start(service_name, timeout=10, log_to_check = None):
3940
"""
4041
Start a service, 'service_name' via init script or systemd and ensure that
4142
it starts running within a 'timeout' second window (default=10s)
4243
"""
4344
start(service_name)
44-
assert is_running(service_name, timeout=10), "%s is not running" % service_name
45+
assert is_running(service_name, timeout=10, log_to_check = log_to_check), "%s is not running" % service_name
4546

4647
def stop(service_name):
4748
"""
@@ -89,7 +90,7 @@ def status(service_name):
8990
status_rc, _, _ = core.system(command)
9091
return status_rc
9192

92-
def check_status(service_name, expected_status, timeout=10):
93+
def check_status(service_name, expected_status, timeout=10, log_to_check = None):
9394
"""
9495
Return True if the exit code of the 'service_name' status check is
9596
expected_status before 'timeout' seconds. Otherwise, False.
@@ -101,15 +102,20 @@ def check_status(service_name, expected_status, timeout=10):
101102
time.sleep(1)
102103
timer += 1
103104

105+
if status_rc != expected_status and log_to_check:
106+
log_file_contents = files.read(log_to_check)
107+
core.log_message("Last lines of log: %s" % log_to_check)
108+
for line in log_file_contents[-9:]:
109+
core.log_message(line)
104110
return status_rc == expected_status
105111

106-
def is_running(service_name, timeout=1):
112+
def is_running(service_name, timeout=1, log_to_check = None):
107113
"""
108114
Return True if 'service_name' is determined to be running via init script or
109115
systemd, according to LSB init standards, before 'timeout'
110116
seconds. Otherwise, False.
111117
"""
112-
return check_status(service_name, STATUS_RUNNING, timeout)
118+
return check_status(service_name, STATUS_RUNNING, timeout, log_to_check)
113119

114120
def is_stopped(service_name, timeout=1):
115121
"""

osgtest/tests/test_150_xrootd.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"""
2525

2626
AUTHFILE_TEXT = """\
27-
u * /tmp a
27+
u * /tmp a /usr/share/ r
2828
u = /tmp/@=/ a
2929
u xrootd /tmp a
3030
"""
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import os
2+
import pwd
3+
import osgtest.library.core as core
4+
import osgtest.library.files as files
5+
import osgtest.library.service as service
6+
import osgtest.library.osgunittest as osgunittest
7+
8+
9+
HTTP_PORT1 = 9001 # chosen so it doesn't conflict w/ the stashcache instances
10+
HTTP_PORT2 = 9002
11+
12+
XROOTD_CFG_TEXT = """\
13+
cms.space min 2g 5g
14+
xrootd.seclib /usr/lib64/libXrdSec.so
15+
http.secxtractor /usr/lib64/libXrdLcmaps.so
16+
17+
sec.protocol /usr/lib64 gsi -d 2 -certdir:/etc/grid-security/certificates \
18+
-cert:/etc/grid-security/xrd/xrdcert.pem \
19+
-key:/etc/grid-security/xrd/xrdkey.pem \
20+
-crl:1 \
21+
-ca:0 \
22+
--gmapopt:10 \
23+
--gmapto:0 \
24+
%s
25+
26+
acc.authdb /etc/xrootd/auth_file
27+
ofs.authorize
28+
all.export /
29+
30+
if exec xrootd
31+
http.cadir /etc/grid-security/certificates
32+
http.cert /etc/grid-security/xrd/xrdcert.pem
33+
http.key /etc/grid-security/xrd/xrdkey.pem
34+
http.listingdeny yes
35+
http.desthttps yes
36+
http.trace all debug
37+
# Enable third-party-copy
38+
http.exthandler xrdtpc libXrdHttpTPC.so
39+
# Pass the bearer token to the Xrootd authorization framework.
40+
http.header2cgi Authorization authz
41+
42+
# Enable Macaroons
43+
ofs.authlib libXrdMacaroons.so
44+
xrd.port %d
45+
xrd.protocol http:%d /usr/lib64/libXrdHttp-4.so
46+
fi
47+
http.exthandler xrdmacaroons libXrdMacaroons.so
48+
all.sitename VDTTESTSITE
49+
50+
"""
51+
52+
class TestStartXrootdTPC(osgunittest.OSGTestCase):
53+
@core.elrelease(7,8)
54+
def test_01_configure_xrootd(self):
55+
core.config['xrootd.tpc.config-1'] = '/etc/xrootd/xrootd-third-party-copy-1.cfg'
56+
core.config['xrootd.tpc.config-2'] = '/etc/xrootd/xrootd-third-party-copy-2.cfg'
57+
core.config['xrootd.tpc.http-port1'] = HTTP_PORT1
58+
core.config['xrootd.tpc.http-port2'] = HTTP_PORT2
59+
core.state['xrootd.started-http-server-1'] = False
60+
core.state['xrootd.started-http-server-2'] = False
61+
core.state['xrootd.tpc.backups-exist'] = False
62+
63+
self.skip_ok_unless(core.options.adduser, 'user not created')
64+
core.skip_ok_unless_installed('globus-proxy-utils', 'xrootd', 'xrootd-scitokens', by_dependency=True)
65+
66+
user = pwd.getpwnam("xrootd")
67+
68+
lcmaps_packages = ('lcmaps', 'lcmaps-db-templates', 'xrootd-lcmaps', 'vo-client', 'vo-client-lcmaps-voms')
69+
if all([core.rpm_is_installed(x) for x in lcmaps_packages]):
70+
core.log_message("Using xrootd-lcmaps authentication")
71+
sec_protocol = '-authzfun:libXrdLcmaps.so -authzfunparms:--loglevel,5'
72+
sec_protocol += ',--policy,authorize_only'
73+
else:
74+
core.log_message("Using XRootD mapfile authentication")
75+
sec_protocol = '-gridmap:/etc/grid-security/xrd/xrdmapfile'
76+
77+
files.write(core.config['xrootd.tpc.config-1'],
78+
XROOTD_CFG_TEXT % (sec_protocol, core.config['xrootd.tpc.http-port1'], core.config['xrootd.tpc.http-port1']),
79+
owner='xrootd', backup=True, chown=(user.pw_uid, user.pw_gid))
80+
files.write(core.config['xrootd.tpc.config-2'],
81+
XROOTD_CFG_TEXT % (sec_protocol, core.config['xrootd.tpc.http-port2'], core.config['xrootd.tpc.http-port2']),
82+
owner='xrootd', backup=True, chown=(user.pw_uid, user.pw_gid))
83+
core.state['xrootd.tpc.backups-exist'] = True
84+
85+
def test_02_create_secrets(self):
86+
core.skip_ok_unless_installed('xrootd', 'xrootd-scitokens', by_dependency=True)
87+
core.config['xrootd.tpc.macaroon-secret-1'] = '/etc/xrootd/macaroon-secret-1'
88+
core.config['xrootd.tpc.macaroon-secret-2'] = '/etc/xrootd/macaroon-secret-2'
89+
core.check_system(["openssl", "rand", "-base64", "-out",
90+
core.config['xrootd.tpc.macaroon-secret-1'], "64"], "Creating symmetric key")
91+
core.check_system(["openssl", "rand", "-base64", "-out",
92+
core.config['xrootd.tpc.macaroon-secret-2'], "64"], "Creating symmetric key")
93+
files.append(core.config['xrootd.tpc.config-1'],
94+
"macaroons.secretkey %s"%(core.config['xrootd.tpc.macaroon-secret-1']),
95+
owner='xrootd', backup=False)
96+
files.append(core.config['xrootd.tpc.config-2'],
97+
"macaroons.secretkey %s"%(core.config['xrootd.tpc.macaroon-secret-2']),
98+
owner='xrootd', backup=False)
99+
100+
101+
def test_03_start_xrootd(self):
102+
core.skip_ok_unless_installed('xrootd', 'xrootd-scitokens', by_dependency=True)
103+
core.config['xrootd_tpc_service_1'] = "xrootd@third-party-copy-1"
104+
core.config['xrootd_tpc_service_2'] = "xrootd@third-party-copy-2"
105+
service.check_start(core.config['xrootd_tpc_service_1'], log_to_check = '/var/log/xrootd/third-party-copy-1/xrootd.log')
106+
service.check_start(core.config['xrootd_tpc_service_2'], log_to_check = '/var/log/xrootd/third-party-copy-2/xrootd.log')
107+
core.state['xrootd.started-http-server-1'] = True
108+
core.state['xrootd.started-http-server-2'] = True
109+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import os
2+
import json
3+
import pwd
4+
5+
import osgtest.library.core as core
6+
import osgtest.library.files as files
7+
import osgtest.library.osgunittest as osgunittest
8+
9+
10+
class TestXrootdTPC(osgunittest.OSGTestCase):
11+
12+
def test_01_create_macaroons(self):
13+
core.skip_ok_unless_installed('xrootd', 'xrootd-scitokens', 'x509-scitokens-issuer-client', by_dependency=True)
14+
self.skip_bad_unless(core.state['proxy.created'], 'Proxy creation failed')
15+
16+
uid = pwd.getpwnam(core.options.username)[2]
17+
usercert = '/tmp/x509up_u%d' % uid
18+
userkey = '/tmp/x509up_u%d' % uid
19+
20+
core.config['xrootd.tpc.url-1'] = "https://" + core.get_hostname() + ":9001" + "/usr/share/osg-test/test_gridftp_data.txt".strip()
21+
command = ('macaroon-init', core.config['xrootd.tpc.url-1'], '20', 'DOWNLOAD')
22+
23+
status, stdout, stderr = core.system(command, user=True)
24+
fail = core.diagnose('Obtain Macaroon one',
25+
command, status, stdout, stderr)
26+
core.config['xrootd.tpc.macaroon-1'] = stdout.strip()
27+
28+
core.config['xrootd.tpc.url-2'] = "https://" + core.get_hostname() + ":9002" + "/tmp/test_gridftp_data_tpc.txt".strip()
29+
command = ('macaroon-init', core.config['xrootd.tpc.url-2'], '20', 'UPLOAD')
30+
status, stdout, stderr = core.system(command, user=True)
31+
fail = core.diagnose('Obtain Macaroon number two',
32+
command, status, stdout, stderr)
33+
core.config['xrootd.tpc.macaroon-2'] = stdout.strip()
34+
35+
def test_02_initate_tpc(self):
36+
core.skip_ok_unless_installed('xrootd', 'xrootd-scitokens', 'x509-scitokens-issuer-client', by_dependency=True)
37+
headers = {}
38+
command = ('curl', '-A', 'Test', "-vk", "-X", "COPY",
39+
'-H', "Authorization: Bearer %s" % core.config['xrootd.tpc.macaroon-1'],
40+
'-H', "Source: %s" % core.config['xrootd.tpc.url-1'],
41+
'-H', 'Overwrite: T',
42+
'-H', 'Copy-Header: Authorization: Bearer %s'% core.config['xrootd.tpc.macaroon-2'],
43+
core.config['xrootd.tpc.url-2'])
44+
status, stdout, stderr = core.system(command, user=True)
45+
fail = core.diagnose('Initiate third party copy',
46+
command, status, stdout, stderr)
47+
file_copied = os.path.exists("/tmp/test_gridftp_data_tpc.txt")
48+
self.assert_(file_copied, 'Copied file missing')
49+
chechskum_match = files.checksum_files_match("/tmp/test_gridftp_data_tpc.txt", "/usr/share/osg-test/test_gridftp_data.txt")
50+
self.assert_(chechskum_match, 'Files have same contents')
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import osgtest.library.core as core
2+
import osgtest.library.files as files
3+
import osgtest.library.service as service
4+
import osgtest.library.osgunittest as osgunittest
5+
6+
class TestStopXrootdTPC(osgunittest.OSGTestCase):
7+
@core.elrelease(7,8)
8+
def test_01_stop_xrootd(self):
9+
if core.state['xrootd.tpc.backups-exist']:
10+
files.restore(core.config['xrootd.tpc.config-1'], "xrootd")
11+
files.restore(core.config['xrootd.tpc.config-2'], "xrootd")
12+
13+
core.skip_ok_unless_installed('xrootd', 'xrootd-scitokens', by_dependency=True)
14+
self.skip_ok_if(not core.state['xrootd.started-http-server-1'] and
15+
not core.state['xrootd.started-http-server-2'],
16+
'did not start any of the http servers')
17+
service.check_stop(core.config['xrootd_tpc_service_1'])
18+
service.check_stop(core.config['xrootd_tpc_service_2'])
19+
20+
def test_02_clean_test_files(self):
21+
files.remove("/tmp/test_gridftp_data_tpc.txt", force=True)

0 commit comments

Comments
 (0)